将静态库与CMake中的测试应用程序一起使用时的链接器错误

问题描述

我的静态库的项目结构与this question中定义的项目结构完全相同,而我的CMakeList.txt也完全相同:

cmake_minimum_required (VERSION 2.8) 
project (project_name) 

add_subdirectory (src) 
add_subdirectory (test) 

我想在我的静态库之后构建测试文件夹。我还添加了add_test(),但是只有问题是我的测试目录不包含单元测试,而是实际的测试应用程序,例如以下代码:

#include <iostream>
main() {
 /* 
   this code uses static library functions in it. There is not Unit Test defined in it.
*/
}

add_test()并没有帮助我,我仍然遇到cannot find -ldal错误。 dal是我的静态库名称,我已将其作为target_link_library添加到测试应用程序中。

libdal / src / CMakeList.txt

cmake_minimum_required(VERSION 3.12)
project(dal)

# Flags Variables
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")

# Include Directeries
include_directories(${CPP_KAFKA_INC})
include_directories(${CPP_MYSQL_INC})
include_directories(${CPP_ALTIBASE_INC})
include_directories(${AFN_STATE_INC})
include_directories(${AFN_DAL_INC})
include_directories(${AFN_COMMONS_INC})
include_directories(${AFN_CONFIG_INC})
include_directories(${SQL_ODBC_INC})
# Executable Target(s)
file(GLOB SOURCES *.cpp)
add_library(${PROJECT_NAME} ${SOURCES})

target_link_libraries(${PROJECT_NAME}
        ${AFN_LIB}
        "-lafinit_state"
        "-luuid"
        "-lz"
        "-lpthread"
        ${PQXX_LIB}
        ${PQ_LIB}
        "-lmysqlcppconn"
        ${libmscpp}
        ${kafkacpplib}
        ${rdkafkalib}
        ${rdkafkacpplib}
        afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
        )

# Installation
install(CODE "MESSAGE(\"Installing ${PROJECT_NAME} \")")
install(TARGETS ${PROJECT_NAME}
        RUNTIME DESTINATION bin
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)

libdal / test / CMakeList.txt

cmake_minimum_required(VERSION 3.12)
project(testdal)

# Flags Variables
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17" )

option(DAL_PUSH_TESTER      "enable DAL push tester"    ON)

# Include Directeries
include_directories(${CPP_KAFKA_INC})
include_directories(${AFN_DAL_INC})
include_directories(${CPP_MYSQL_INC})
include_directories(${AFN_STATE_INC})
include_directories(${AFN_CONFIG_INC})

add_executable(${PROJECT_NAME}  main.cpp)
target_link_libraries(${PROJECT_NAME}
        ${AFN_LIB}
        "-lmysqlcppconn"
        "-luuid"
        "-lz"
        ${libmscpp}
        "-ldal"
        ${PQXX_LIB}
        ${PQ_LIB}
        ${kafkacpplib}
        ${rdkafkalib}
        ${rdkafkacpplib}
        "-lafinit_state"
        "-luuid"
        "-lpthread"
        afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
        ${AFN_LICENSE_LIB} "-laf_license_manager"
        )
    # Installation
install(CODE "MESSAGE(\"Installing ${PROJECT_NAME} \")")
install(TARGETS ${PROJECT_NAME}
        RUNTIME DESTINATION bin/tests
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)


if (DAL_PUSH_TESTER)
    add_executable(dal_push_tester dal_push_tester.cpp)
    target_link_libraries(dal_push_tester
            ${AFN_LIB}
            "-lmysqlcppconn"
            "-luuid"
            "-lz"
            ${libmscpp}
            "-ldal"
            ${PQXX_LIB}
            ${PQ_LIB}
            ${kafkacpplib}
            ${rdkafkalib}
            ${rdkafkacpplib}
            "-lafinit_state"
            "-luuid"
            "-lpthread"
            afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
            ${AFN_LICENSE_LIB} "-laf_license_manager"
            )
# Installation
install(CODE "MESSAGE(\"Installing dal_push_tester  \")")
install(TARGETS dal_push_tester 
        RUNTIME DESTINATION bin/tests
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib)

endif ()

解决方法

该问题在网站上已经提出过几次,但是您的CMake文件还有其他一些问题值得解释。

问题是链接器不知道在哪里可以找到dal库,因为您只提供了"-ldal",而没有到库或其他任何东西的完整路径。您可以通过使用dal中的CMake库 target 名称(target_link_libraries())来解决此问题,因为它是在同一CMake调用中定义的。

target_link_libraries(${PROJECT_NAME}
        ${AFN_LIB}
        "-lmysqlcppconn"
        "-luuid"
        "-lz"
        ${libmscpp}
        dal              #   <------ Note the change on this line.
        ${PQXX_LIB}
        ${PQ_LIB}
        ${kafkacpplib}
        ${rdkafkalib}
        ${rdkafkacpplib}
        "-lafinit_state"
        "-luuid"
        "-lpthread"
        afiniti_config $<$<CONFIG:DEBUG>:-lgcov>
        ${AFN_LICENSE_LIB} "-laf_license_manager"
        )

此外,target_link_libraries不需要添加明确的-l链接标志;它会自动添加。另外,您应始终为此和其他PRIVATE调用指定范围参数(例如PUBLICtarget_*等)。此外,您还链接了uuid 两次,因此您可以删除其中之一:

target_link_libraries(${PROJECT_NAME} PRIVATE
        ${AFN_LIB}
        mysqlcppconn
        uuid
        z
        ${libmscpp}
        dal
        ${PQXX_LIB}
        ${PQ_LIB}
        ${kafkacpplib}
        ${rdkafkalib}
        ${rdkafkacpplib}
        afinit_state
        pthread
        afiniti_config $<$<CONFIG:DEBUG>:gcov>
        ${AFN_LICENSE_LIB} af_license_manager
        )

此外,此行中的CMAKE_CXX_FLAGS的手动修改:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
不鼓励

高度。要设置C ++标准,您应该使用:

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

或本question中讨论的其他更现代的方法之一。

我建议您浏览有关modern CMake practices的某些内容。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...