Reputation: 13661
I currently have the following architecture
`-- 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
My root CMakeLists.txt
is as follow
project(system)
add_subdirectory(dll)
add_subdirectory(sockets)
add_subdirectory(threads)
add_library(${PROJECT_NAME}
${${PROJECT_NAME}_HEADERS}
${${PROJECT_NAME}_SOURCES}
)
and in threads/
for example, I have the following
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)
but, as add_subdirectory()
creates a new scope, my ${PROJECT_NAME}_*
variables are empty. I read about set(... PARENT_SCOPE)
, but the paths become invalids and anyhow cmake produces an error on the call to target_link_libraries()
in system/threads/CMakeLists.txt
saying Cannot specify link libraries for target "system" which is not built by this project.
. Scope issue again.
So I though I would be nice if I found a solution to bypass the scope creation, but I'll take any solution that keeps the logic of my architecture.
Upvotes: 4
Views: 1282
Reputation: 78320
You have a couple of reasonable options here I think.
The add_subdirectory
command is often used to include a directory (it needn't actually be a subdirectory in the filesystem sense) which really contains a standalone module, e.g. a library or executable; one which can be built without the help of a parent CMakeLists file. In this case, the submodule's CMakeLists.txt would contain its own project
command, rendering the use of a global ${PROJECT_NAME}
variable difficult.
In your case, it appears that you simply want the subdirectories' CMakeLists files to append lists of files to variables defined in the parent scope. You can achieve this by making use of the CMake variable CMAKE_CURRENT_LIST_DIR
in your subordinate CMakeLists:
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
)
Ensure you don't have a project
command in your subdirectories' CMakeLists files.
This can be made slightly simpler in this case by swapping the add_subdirectory
command with the include
command, hence avoiding scoping issues.
To do this, remove the PARENT_SCOPE
args from the set
commands, and in the top-level CMakeLists.txt:
add_subdirectory(dll)
add_subdirectory(sockets)
add_subdirectory(threads)
include(dll/CMakeLists.txt)
include(sockets/CMakeLists.txt)
include(threads/CMakeLists.txt)
Your other issue relating to target_link_libraries(${PROJECT_NAME} pthread)
is simply down to the fact that the add_library
command defining the library ${PROJECT_NAME}
is called after the target_link_libraries
command. Your simplest option is probably to move the target_link_libraries
command to the parent CMakeLists.txt
Upvotes: 6