Как получить решение 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, которая обеспечивает некоторую автоматизацию для обработки таких случаев довольно элегантно.

Другие вопросы по тегам