是否可以绕过add_subdirectory()命令的新范围创建?

时间:2012-12-31 18:06:51

标签: cmake

我目前有以下架构

`-- 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}_*变量为空。我读到了set(... PARENT_SCOPE),但是这些路径变成了无效状态,无论如何cmake在target_link_libraries() system/threads/CMakeLists.txt Cannot specify link libraries for target "system" which is not built by this project.的{​​{1}}调用{{1}}时产生错误。范围问题再次出现。

所以,如果我找到一个绕过范围创建的解决方案,我会很高兴,但我会采取任何保持架构逻辑的解决方案。

1 个答案:

答案 0 :(得分:6)

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

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

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

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命令。

在这种情况下,通过使用include命令交换add_subdirectory命令可以稍微简化一下,从而避免了范围问题。

要执行此操作,请从PARENT_SCOPE命令和顶级CMakeLists.txt中删除set args:

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)相关的其他问题仅限于以下事实:定义库add_library的{​​{1}}命令在 {{1}之后被称为命令。您最简单的选择可能是将${PROJECT_NAME}命令移动到父CMakeLists.txt