4

我目前有以下架构

`-- system
    |-- CMakeLists.txt
    |-- dll
    |   |-- CMakeLists.txt
    |   |-- UnixDLoader.cpp
    |   |-- ...
    |   `-- WinDLoader.hh
    |-- sockets
    |   |-- CMakeLists.txt
    |   |-- crossplateform_utils.h
    |   |-- ...
    |   `-- Udp.hh
    `-- threads
        |-- CMakeLists.txt
        |-- IMutex.hh
        |-- ...
        `-- WinThread.hh

我的根CMakeLists.txt如下

project(system)

add_subdirectory(dll)
add_subdirectory(sockets)
add_subdirectory(threads)

add_library(${PROJECT_NAME}
    ${${PROJECT_NAME}_HEADERS}
    ${${PROJECT_NAME}_SOURCES}
)

threads/例如,我有以下

list(APPEND ${PROJECT_NAME}_HEADERS
    IThread.hh
    UnixThread.hh
    WinThread.hh
    IMutex.hh
    UnixMutex.hh
    WinMutex.hh
)
set(${PROJECT_NAME}_HEADERS ${${PROJECT_NAME}_HEADERS} PARENT_SCOPE)

list(APPEND ${PROJECT_NAME}_SOURCES
    UnixThread.cpp
    WinThread.cpp      
    UnixMutex.cpp
    WinMutex.cpp    
    PARENT_SCOPE
)
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES} PARENT_SCOPE)

if(UNIX)
    target_link_libraries(${PROJECT_NAME} pthread)
endif(UNIX)

但是,当add_subdirectory()创建一个新范围时,我的${PROJECT_NAME}_*变量是空的。我读过,但路径变得无效,无论如何cmake在set(... PARENT_SCOPE)调用时会产生错误。又是范围问题。target_link_libraries()system/threads/CMakeLists.txtCannot specify link libraries for target "system" which is not built by this project.

因此,如果我找到一个绕过范围创建的解决方案,我会很好,但我会采用任何能保持我的架构逻辑的解决方案。

4

1 回答 1

6

我认为你有几个合理的选择。

add_subdirectory命令通常用于包含一个目录(它实际上不必是文件系统意义上的子目录),该目录实际上包含一个独立模块,例如库或可执行文件;一个可以在没有父 CMakeLists 文件帮助的情况下构建的。在这种情况下,子模块的 CMakeLists.txt 将包含它自己的project命令,从而使全局${PROJECT_NAME}变量的使用变得困难。

在您的情况下,您似乎只是希望子目录的 CMakeLists 文件将文件列表附加到父范围中定义的变量。您可以通过使用CMAKE_CURRENT_LIST_DIR从属 CMakeLists 中的 CMake 变量来实现此目的:

set(${PROJECT_NAME}_HEADERS
    ${${PROJECT_NAME}_HEADERS}
    ${CMAKE_CURRENT_LIST_DIR}/IThread.hh
    ${CMAKE_CURRENT_LIST_DIR}/UnixThread.hh
    ${CMAKE_CURRENT_LIST_DIR}/WinThread.hh
    ${CMAKE_CURRENT_LIST_DIR}/IMutex.hh
    ${CMAKE_CURRENT_LIST_DIR}/UnixMutex.hh
    ${CMAKE_CURRENT_LIST_DIR}/WinMutex.hh
    PARENT_SCOPE
)

set(${PROJECT_NAME}_SOURCES
    ${${PROJECT_NAME}_SOURCES}
    ${CMAKE_CURRENT_LIST_DIR}/UnixThread.cpp
    ${CMAKE_CURRENT_LIST_DIR}/WinThread.cpp      
    ${CMAKE_CURRENT_LIST_DIR}/UnixMutex.cpp
    ${CMAKE_CURRENT_LIST_DIR}/WinMutex.cpp    
    PARENT_SCOPE
)

确保子目录的 CMakeLists 文件中没有project命令。

在这种情况下,可以通过将add_subdirectory命令与include命令交换来稍微简单一些,从而避免范围问题。

为此,请PARENT_SCOPE从命令中删除 args set,并在顶级 CMakeLists.txt 中:

add_subdirectory(dll)
add_subdirectory(sockets)
add_subdirectory(threads)
include(dll/CMakeLists.txt)
include(sockets/CMakeLists.txt)
include(threads/CMakeLists.txt)


您与此相关的另一个问题仅仅是在命令之后调用定义库的命令这一target_link_libraries(${PROJECT_NAME} pthread)事实。您最简单的选择可能是将命令移动到父 CMakeLists.txtadd_library${PROJECT_NAME}target_link_librariestarget_link_libraries

于 2012-12-31T21:48:08.693 回答