Как получить решение VS со всеми проектами и решениями для отдельных проектов с CMake
TL;DR Я в принципе хочу модульное решение этого вопроса. Не только одно решение со всем в нем, но и решение для каждого исполняемого файла отдельно.
В своем вопросе я хотел узнать, как мне разбить мой CMakeLists.txt по разным папкам. Некоторые папки содержат код, который будет являться статической библиотекой, а часть кода будет исполняемым файлом или динамической библиотекой, основанной на этих статических библиотеках.
Структура папки выглядит следующим образом:
/path/to/base/
CMakeLists.txt
app1/
<src files for app1>
CMakeLists.txt
app2/
<src files for app2>
CMakeLists.txt
lib/
<src files for lib>
CMakeLists.txt
Если я выберу подход CMakeLists.txt
в родительской папке ко всем моим библиотекам и исполняемым файлам, а также из всех включенных каталогов у меня возникает проблема, заключающаяся в том, что когда я генерирую проекты / решения VS, мои проекты для каждой цели содержат все проекты, а не только те, которые необходимы для моей предполагаемой цели.
Содержание CMakeLists.txt
в базовой папке:
cmake_minimum_required(VERSION 3.1)
add_subdirectory(lib)
add_subdirectory(app1)
add_subdirectory(app2)
и CMakeLists.txt
в папке app1 (app2 эквивалентно)
cmake_minimum_required(VERSION 3.1)
project(app1)
add_executable(app1 <src of app1>)
target_link_libraries(app1 lib)
а также CMakeLists.txt
из lib:
add_library(lib <src of lib>)
Если я запускаю cmake на CMakeLists.txt
из базы решение содержит все проекты. И даже если я открою только один из проектов; это также содержит все. VS проект app1 также строит app2 - чего я не хочу.
Если бы я только запустить cmake на CMakeLists.txt
из app1 я получаю решение, которое не содержит app2, но оно также не содержит lib, потому что оно упоминается только для ссылок внутри файла cmake, а не как цель (оно находится в базовом файле)
1 ответ
CMake создаст решение для каждого звонка project
, который затем будет включать все цели текущего каталога и его подкаталогов (независимо от того, были ли они определены до или после фактического вызова project
).
Вот что должен делать хорошо ведущий себя сценарий CMake: каждый список CMake, который вы хотите использовать в качестве корня своего собственного поддерева в рамках более крупного проекта, должен начинаться с cmake_minimum_required
вызов, а затем project
вызов. Пишу project
в CMakeLists в основном означает: это полностью автономный компонент, который может быть собран независимо, даже если вы удалите все файлы из его родительских каталогов. Таким образом, имеет смысл иметь отдельное решение для каждого такого project
,
Имея это в виду, мы можем понять, почему это не работает в вашем случае: ваши приложения не полностью автономны, они зависят от lib. Решением этой проблемы является написание сценариев сборки для приложений, как если бы lib был предоставлен как сторонний компонент, с find_package
звонки и все. В составной сборке у вас уже есть цель для lib, поэтому скрипт, вызываемый find_package
должен быть сделан вызов для короткого замыкания на использование этой цели и только на самом деле начать очистку системы, если она не может найти эту существующую цель.
Также читайте о том, как работает система упаковки CMake, которая обеспечивает некоторую автоматизацию для обработки таких случаев довольно элегантно.