我正在尝试将庞大的代码库从自定义内部工具链迁移到Cmake。该代码由许多共享库和一些可执行文件组成。

其中一些库是相互依赖的。让我们以Lib1和Lib2为例,其中Lib1使用来自Lib2的符号,而Lib2使用来自Lib1的符号。
为了创建Lib1 DLL,我们需要从Lib2导出符号,而Lib2又需要从Lib1导出符号。目前,我们通过链接两个阶段来解决此问题,如此处所述:Mutual Imports)。这为我们提供了以下步骤:

  • 创建lib1.lib和lib1.exp
    创建lib2.lib和lib2.exp
  • 使用lib1.obj和lib2.lib / lib2.exp创建lib1.DLL
    使用lib2.obj和lib1.lib / lib1.exp
  • 创建lib2.DLL

    我知道这是一种代码味道,但是代码库太大,无法尝试纠正所有这些周期。因此,我想使用Cmake获得类似的结果。除了仅使用自定义命令,否则完全找不到该工具的目的,我从文档中找不到任何实现此目的的方法。

    旧版工具链执行以下调用:

    # compile sources
    cl lib1\SRC\lib1help.cpp ... /Fo"build\cl\lib1.obj"
    cl lib2\SRC\lib2help.cpp ... /Fo"build\cl\lib2.obj"
    
    # create lib + exp symbols
    lib /DEF build\cl\lib1.obj /OUT:build\link1\lib1.lib
    lib /DEF build\cl\lib2.obj /OUT:build\link1\lib2.lib
    
    # create mutual dependant dll using exp
    link build\cl\lib1.obj build\link1\lib2.lib /DLL /OUT:build\link2\lib1.dll
    link build\cl\lib2.obj build\link1\lib1.lib /DLL /OUT:build\link2\lib2.dll
    

    到目前为止,我有以下CmakeLists.txt:
    add_library(lib2 SHARED lib2/src/lib2help.cpp)
    add_library(lib1 SHARED lib1/src/lib1help.cpp)
    
    target_include_directories(lib1 PUBLIC lib1/include/)
    target_compile_definitions(lib1 PRIVATE __LIB1)
    target_link_libraries(lib1 PRIVATE lib2)
    
    target_include_directories(lib2 PUBLIC lib2/include/)
    target_compile_definitions(lib2 PRIVATE __LIB2)
    target_link_libraries(lib2 PRIVATE lib1)
    

    这给我以下结果:
    [cmake] CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle)
    [cmake]   "lib2" of type SHARED_LIBRARY
    [cmake]     depends on "lib1" (weak)
    [cmake]   "lib1" of type SHARED_LIBRARY
    [cmake]     depends on "lib2" (weak)
    

    你们知道我可以使用Cmake实现此方法吗?
    目前,我仅计划针对Windows系统,但与OS无关的将非常棒!

    谢谢

    最佳答案

    我非常着迷于创建SHARED库,以至于我没有探索STATIC + SHARED的方式。感谢@arrowd@tsyvaref的建议。

    我使用以下CmakeLists.txt使它工作

    add_library(lib1_obj OBJECT src/lib1help.cpp)
    target_include_directories(lib1_obj PUBLIC include/)
    target_include_directories(lib1_obj PRIVATE $<TARGET_PROPERTY:lib2_obj,INCLUDE_DIRECTORIES>)
    target_compile_definitions(lib1_obj PRIVATE __LIB1)
    
    add_library(lib1_static STATIC $<TARGET_OBJECTS:lib1_obj>)
    target_link_libraries(lib1_static PUBLIC lib2_static)
    set_target_properties(lib1_static PROPERTIES STATIC_LIBRARY_OPTIONS "/DEF")
    set_target_properties(lib1_static PROPERTIES OUTPUT_NAME lib1)
    
    add_library(lib1_shared SHARED $<TARGET_OBJECTS:lib1_obj>)
    target_link_libraries(lib1_shared PRIVATE lib1_static)
    set_target_properties(lib1_shared PROPERTIES RUNTIME_OUTPUT_NAME lib1)
    
    add_library(lib1 ALIAS lib1_shared)
    

    除了切换名称外,用于lib2的文件完全相同。
    我不确定这是否是最好的方法,但我现在很高兴。
    这是正在发生的事情:
  • 将源代码编译成OBJECT库
  • 用“/ DEF”将相互依赖的库链接为静态,以创建导出文件
  • 重命名静态库输出,以方便将其用于链接器
  • 使用.obj,.lib和.exp预先创建的
  • 链接共享库
  • 重命名共享库dll,以便于使用

  • 在这里,我们可以使用Dependency Walker查看每个DLL的内容:
    c&#43;&#43; - 在Cmake中允许相互依赖-LMLPHP

    关于c++ - 在Cmake中允许相互依赖,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58043280/

    10-09 12:46