CMake Visual Studio Group 一起构建了来自 Conan

问题描述

我有一个项目,我使用 CMake 管理并使用 MSVC 构建它。 对于依赖管理,我将 Conancmake_find_package 生成器一起使用。

Build it self 可以正常工作,没有任何问题。但我不能运行,例如测试可执行文件,而无需将创建的 dlldll 从依赖项复制到 Test Executable 的位置。

这是我的conanfile.txt

[requires]
gtest/1.10.0

[generators]
cmake_find_package

[options]
gtest:shared=True
gtest:build_gmock=True

这是我的 CMakeLists.txt 文件 DLL

cmake_minimum_required(VERSION 3.14)

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
    message(FATAL_ERROR "Do not build in-source. Please remove CMakeCache.txt and the CMakeFiles/ directory. Then build out-of-source")
endif()

project("Commanddispatcher" VERSION 1.0.0 LANGUAGES CXX)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})

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

option(BUILD_SHARED_LIBS "Build shared (dynamic) libraries." ON)
option(ENABLE_TESTING "Build with Tests enabled." ON)

include(generate_product_version)
generate_product_version(
        VersionFilesOutputvariable
        ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/Product.ico
        NAME ${PROJECT_NAME}
        VERSION_MAJOR 1
        VERSION_MInor 0
        VERSION_PATCH 0
        VERSION_REVISION 0
)

add_library(${PROJECT_NAME})
add_library("Product::Commanddispatcher" ALIAS ${PROJECT_NAME})

target_sources(${PROJECT_NAME}
                        PUBLIC
                        include/${PROJECT_NAME}/export.hpp
                        include/${PROJECT_NAME}/command_dispatcher.hpp
                        PRIVATE
                        src/command_dispatcher.cpp
                        src/test.hpp
                        src/test.cpp
                        ${VersionFilesOutputvariable}
)

target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
                            "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>"
                            PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")

set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION 1 VERSION 1.0.0)

if (MSVC)
    set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "d")
endif()

include(GenerateExportHeader)
string(toupper ${PROJECT_NAME} PROJECT_NAME_UPPER)
generate_export_header(${PROJECT_NAME}
    EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}/export.hpp
    EXPORT_MACRO_NAME ${PROJECT_NAME_UPPER}_EXPORT
    STATIC_DEFINE ${PROJECT_NAME_UPPER}_STATIC
)

if(ENABLE_TESTING)
    message(STATUS "Build Library as Static Version for testing purpose")

    set(PROJECT_NAME_STATIC ${PROJECT_NAME}_static)
    add_library(${PROJECT_NAME_STATIC} STATIC)
    target_sources(${PROJECT_NAME_STATIC}
                        PUBLIC
                        include/${PROJECT_NAME}/export.hpp
                        include/${PROJECT_NAME}/command_dispatcher.hpp
                        PRIVATE
                        src/command_dispatcher.cpp
                        src/test.hpp
                        src/test.cpp
    )  
    
    target_include_directories(${PROJECT_NAME_STATIC}  PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
                                "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>"
                                PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")

    string(toupper ${PROJECT_NAME} PROJECT_NAME_UPPER)
    set_target_properties(${PROJECT_NAME_STATIC} PROPERTIES COMPILE_FLAGS -D${PROJECT_NAME_UPPER}_STATIC)   

    if (MSVC)
       # set_target_properties(${PROJECT_NAME_STATIC} PROPERTIES DEBUG_POSTFIX "d")
    endif()

    message(STATUS "Running Tests for Library ${PROJECT_NAME}")

    include(CTest)
    enable_testing()
    add_subdirectory(tests)
endif()

我首先将库构建为 DLLstatic 库,用于测试目的(同时测试库的私有部分。

这是 CMakeLists.txt 目录中的 tests

set(TEST_TARGET_NAME ${PROJECT_NAME}_TEST)

add_executable(${TEST_TARGET_NAME})

target_sources(${TEST_TARGET_NAME}
                    PRIVATE
                    ExampleTest.cpp
                    TestRunner.cpp
)                   

find_package(GTest)

if(TARGET GTest::GTest)
    message(STATUS "Target Found")
    target_link_libraries(${TEST_TARGET_NAME} PRIVATE GTest::GTest)
endif()

target_link_libraries(${TEST_TARGET_NAME} PRIVATE ${PROJECT_NAME_STATIC})

add_test(NAME ${TEST_TARGET_NAME}
         COMMAND ${TEST_TARGET_NAME}
         WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET_NAME}>)

target_include_directories(${TEST_TARGET_NAME} PRIVATE $<TARGET_PROPERTY:${PROJECT_NAME_STATIC},INCLUDE_DIRECTORIES>)                                                      

这里是与 GTest 一起安装的 Conan 库的链接

如果我运行构建,结果位于 Build 目录内的以下文件夹结构中:

+---build
    |
    +---Debug
    |       Commanddispatcherd.dll
    +---tests
    |   |               
    |   \---Debug
    |           Commanddispatcher_TEST.exe

GTest DLLs 在我的 Userfolder/.conan 下方。

将这些东西组合在一起的好方法是什么?例如。在 DLL 目录内的 Test Exe 文件夹中构建 Dependencies DLLbin/testbuild

我的第一个猜测是在 Conanfile.txt添加以下内容

[imports]
bin,gmockd.dll -> ./bin/test
bin,gmock_maind.dll -> ./bin/test
bin,gtestd.dll -> ./bin/test
bin,gtest_maind.dll -> ./bin/test

但为此我需要知道构建的 dlls名称

并将以下内容添加到 Main CMakeFile.txt

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/lib)

或者我应该根据 targetset_target_properties 进行更改吗?

或者有更好的解决方案吗?还要让柯南部分将 DLL 复制到正确的位置?

也欢迎对我的 CMakeFile.txt 进行任何改进 =)。

解决方法

但是为此我需要知道构建的 dll 的名称。

我认为您不需要知道 dll 的名称。您可以设置导入,如:

bin,*.dll -> ./bin/test @ root_package=gtest

注意 root_package 参数,它会告诉柯南从哪个包中复制 dll。 更多信息请访问:https://docs.conan.io/en/latest/reference/conanfile_txt.html#imports

或者在 conanfile.py 中它可以实现为:

def imports(self):
    self.copy("*.dll",f"bin\\tests","bin",root_package='gtest')