Это то, что я думаю. Полный отказ от ответственности: я на самом деле не гуру cmake
, и этот ответ основан исключительно на моих исследованиях после прочтения вопроса. У меня нет проекта, чтобы проверить это, и я никогда не использовал vpath
в Makefile
, который я написал.
Кроме того, этот вопрос не публикует пример Makefile
и не публикует макрос, используемый OP, что заставляет меня сомневаться в том, чтобы дать ответ «используй это», но здесь идет речь.
Во-первых: почему мы используем vpath
в нашем Makefile
?
Поскольку я не знал, что такое vpath
, я посмотрел его. Из GNU Make Manual , раздел 4.5:
Функции поиска по каталогам make облегчают это, автоматически выполняя поиск по нескольким каталогам, чтобы найти необходимое условие ...
Аналогично переменной VPATH
, но более избирательной является директива vpath
(обратите внимание на нижний регистр), которая позволяет указывать путь поиска для определенного класса имен файлов: тех, которые соответствуют определенному шаблону. Таким образом, вы можете предоставить определенные каталоги поиска для одного класса имен файлов и другие каталоги (или ни одного) для других имен файлов.
Итак, вы используете vpath
для поиска файлов, которые распределены по нескольким каталогам. Я предполагаю, что эти файлы являются либо исходными файлами, либо промежуточными файлами, созданными в процессе сборки.
Я нашел несколько примеров vpath
, которые кажутся показательными для его использования - этот вопрос StackOverflow , этот и, наконец, Управление проектами с помощью GNU make, третий Редакция раздел 2.3.
Так вот , почему вы бы использовали vpath
. Итак, двигаясь дальше:
Во-вторых, как добиться того же, используя cmake
. И здесь полезен дальнейший вклад со стороны ОП.
Если у вас есть несколько целей , которые вы строите из структуры каталогов, подобной этой:
|- library1/
|-- {C++ Source}
|- Tool/
|-- {C++ Source}
|- Project/
|-- src/
|---- {C++ Source}
Вы должны использовать несколько CMakeLists.txt
, по одному в каждом из подкаталогов. В library1
вы создадите библиотеку (ADD_LIBRARY( libNAME src1.cxx src2.cxx src3.cxx )
), в Tool
вы добавите исполняемый файл (ADD_EXECUTABLE( theTOOL src1.cxx src2.cxx )
). Наконец, в Project/src/
вы создадите исполняемый файл вашего проекта с ADD_EXECUTABLE
, связав его с libNAME
, который вы встроили в library1
.
В этом сценарии вам не нужно искать , потому что ваш источник явно помещен в CMakeLists.txt
.
Если вы не делаете что-то подобное выше, и ваш источник просто распределен по многим многим каталогам, примерно так:
|-Project/
|--src/
|----maths/
|------ { SOURCE FILES }
|----sound/
|------ { SOURCE FILES }
|----imagegeneration/
|------ { SOURCE FILES }
В этом случае вы создаете только одну вещь и просто распространяете свой источник для простоты использования. В этом случае есть несколько вариантов для вас.
Вы можете использовать ответ, отправленный здесь , чтобы автоматически добавлять все файлы типа к цели. Это НЕ должно быть сделано! Из cmake --help-command file
(выделено мной):
GLOB сгенерирует список всех файлов, которые соответствуют выражениям globbing, и сохранит его в переменной ... Мы не рекомендуем использовать GLOB для сбора списка источников файлы из вашего исходного дерева .
[См. ниже причину, по которой это так]
Вы можете использовать директиву add_subdirectory
, чтобы добавить несколько подкаталогов, по одному для каждого вашего исходного подкаталога. Это тоже не идеально. (Некоторая подтверждающая документация: ссылка , в которой обсуждается использование add_subdirectory
таким образом)
Вы можете использовать aux_source_directory
для сбора исходных файлов из указанного каталога и сохранения в переменной. (Прочтите cmake --help-command aux_source_directory
, если вам это интересно). Однако, это тоже , а не рекомендуется.
Итак почему не следует использовать (1), (2) или (3)? cmake
не является заменой для make
или Makefiles
. Скорее, cmake
генерирует a build system
, который вы затем используете для создания своего проекта. Это различие стоит отметить. Хотя вы можете легко добавить несколько источников к вашему CMakeLists.txt
автоматически, вы вызовете неоднозначность для cmake
: cmake
не сможет создать систему сборки, которая знает исходные файлы, чтобы определить, что изменилось!
Это проблема всех трех методов, упомянутых выше. От cmake --help-command aux_source_directory
:
Хотя это, кажется, работает,
CMake не может сгенерировать систему сборки, которая знает, когда
новый исходный файл был добавлен. Обычно сгенерированная система сборки
знает, когда нужно перезапустить CMake, потому что файл CMakeLists.txt
изменен, чтобы добавить новый источник. Когда источник только что добавлен в
каталог без изменения этого файла, придется вручную
Перезапустите CMake, чтобы сгенерировать систему сборки, включающую новый файл.
Суммирование: как добавить исходные файлы в cmake
?
При использовании cmake
вы должны явно добавлять исходные файлы к каждому из ваших CMakeLists.txt
. Если вы используете несколько каталогов для разделения логических фрагментов кода, это должно быть явно указано в CMakeLists.txt
, что-то похожее на следующее:
set ( MyApplication_SRC_FILES
maths/a.cpp
maths/b.cpp
sound/c.cpp
sound/d.cpp
imagegeneration/e.cpp
imagegeneration/f.cpp
)
ADD_EXECUTABLE ( MyApplication ${MyApplication_SRC_FILES} )
Это позволяет cmake
создать систему сборки, которая может собрать ваш код. Существуют подходящие методы для добавления многочисленных файлов в каталогах в систему сборки, описанные в (1), (2) и (3) выше; но к ним следует относиться с осторожностью, а не использовать их только потому, что «так я и поступил со своим Makefile
». Вы не пишете саму систему сборки; это шаг назад от Makefile
, и поэтому к нему следует относиться немного по-другому.