Я только что перенес довольно большой проект из решений Visual Studio в CMake и заметил странное поведение. У меня есть что-то вроде следующей структуры:
project/CMakeLists.txt
project/code/CMakeLists.txt
project/code/library-1/CMakeLists.txt
project/code/library-1/*.hpp
project/code/library-1/*.cpp
project/code/library-2/CMakeLists.txt
project/code/library-2/*.hpp
project/code/library-2/*.cpp
...
project/code/library-n/CMakeLists.txt
project/code/library-n/*.hpp
project/code/library-n/*.cpp
project/demo/CMakeLists.txt
project/demo/demo-1/CMakeLists.txt
project/demo/demo-1/*.hpp
project/demo/demo-1/*.cpp
project/demo/demo-2/CMakeLists.txt
project/demo/demo-2/*.hpp
project/demo/demo-2/*.cpp
...
project/demo/demo-n/CMakeLists.txt
project/demo/demo-n/*.hpp
project/demo/demo-n/*.cpp
- Корневой файл
CMakeLists.txt
настраивает флаги компиляции, определения макросов и т. Д. И использует CMake add_subdirectory()
для включения целей, определенных библиотеками и демонстрационными проектами.
- Подпапка
code
содержит плоский список подпапок, каждая из которых содержит исходный код статической библиотеки (а также ее цель, определенную в файле CMakeLists.txt
).
- Подпапка
demo
содержит плоский список подпапок. Каждый содержит исходный код для исполняемого файла и связанный файл CMakeLists.txt
.
- Каждая библиотека является автономным компонентом и создается независимо от всех других библиотек и демонстрационных проектов.
- Каждая демонстрационная программа зависит от одной или нескольких различных библиотек в подпапке
code
.
Эта настройка действительно хороша. Если я хочу изменить параметры сборки, мне нужно только изменить root CMakeLists.txt
, и все перекомпилируется с новыми настройками. Если я изменю какой-либо исходный код в любом месте дерева, соответствующие библиотеки, если таковые имеются, будут перекомпилированы, и все зависимые демонстрационные программы также будут пересобраны.
Однако, если я изменю любой файл CMakeLists.txt
в любом месте дерева, все дерево библиотек и программ будет перекомпилировано без учета зависимостей. Чтобы понять, что я имею в виду, приведу несколько частей сценариев сборки CMake.
project/demo/CMakeLists.txt
# Resolve libraries built in `code` sub-folder.
link_directories(${LIBRARY_OUTPUT_PATH})
set(demo-projects
demo-1
demo-2
...
demo-n
)
foreach(demo-project ${demo-projects})
add_subdirectory(${demo-project})
endforeach()
project/demo/demo-n/CMakeLists.txt
# Find all source code in the same folder.
file(GLOB ${demo-project}_headers
${CMAKE_CURRENT_SOURCE_DIR}/*.hpp
)
file(GLOB ${demo-project}_sources
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
# Select libraries to link with.
set(${demo-project}_libraries
library-1
library-2
library-5
)
# Build the demo program.
add_executable(${demo-project}
${${demo-project}_headers}
${${demo-project}_sources}
)
if(${demo-project}_libraries)
target_link_libraries(${demo-project} ${${demo-project}_libraries})
endif()
# Manually register some dependencies on other targets.
if(${demo-project}_dependencies)
add_dependencies(${demo-project} ${${demo-project}_dependencies})
endif()
Если мне случится изменить project/demo/demo-n/CMakeLists.txt
, добавив дополнительную библиотеку, например:
set(${demo-project}_libraries
library-1
library-2
library-5
library-6
)
Затем весь исходный код для всех библиотек и демонстрационных программ в проекте перекомпилируется. Почему это так? Есть ли лучший способ структурировать мои сценарии, чтобы избежать этого?