Автоматически добавлять все файлы в папке к цели с помощью CMake?

163

Я рассматриваю возможность переключения кроссплатформенного проекта с отдельных систем управления сборками в Visual C ++, XCode и make-файлах на CMake.

Одна важная функция, которая мне нужна, - это автоматическое добавление всех файлов в каталоге к цели. Хотя это легко сделать с помощью make, это нелегко сделать с помощью Visual C ++ и XCode (поправьте меня, если я ошибаюсь). Возможно ли сделать это непосредственно в CMake? Как?

martjno
источник
Btw. в Visual Studio, по крайней мере в проектах C #, в проводнике проекта есть кнопка на панели инструментов с именем show all files. Это делает все подкаталоги проекта видимыми, серыми, если они не содержат никаких файлов, логически включенных в проект. Вы можете включить эти каталоги через контекстное меню, которое включает все исходные файлы внутри них, рекурсивно :)
yeoman

Ответы:

229

Это возможно. Например, с file(GLOB:

cmake_minimum_required(VERSION 2.8)

file(GLOB helloworld_SRC
    "*.h"
    "*.cpp"
)

add_executable(helloworld ${helloworld_SRC})

Обратите внимание, что это требует повторного запуска вручную,cmake если исходный файл добавлен или удален, поскольку сгенерированная система сборки не знает, когда запросить CMake для регенерации, и выполнение этого при каждой сборке увеличит время сборки.

Клейст
источник
11
Альтернативой ручному повторному запуску cmake является прикосновение к файлу CMakeLists.txt перед запуском make.
Симус Коннор
8
> «Мы не рекомендуем использовать GLOB для сбора списка исходных файлов из дерева исходных текстов. Если файл CMakeLists.txt не изменяется при добавлении или удалении источника, то сгенерированная система сборки не может знать, когда попросить CMake сгенерировать заново». Это больше не рекомендуется в документах CMAKE3.7, связанных с Hand1Cloud
трижды,
4
какая тогда альтернатива GLOB?
Шейн
13
Лучший способ, так как v3.1 предлагается здесь: target_sources () crascit.com/2016/01/31/…
Sheen
34

Ответ Клейста, конечно, работает, но есть важное предостережение:

Когда вы пишете Makefileвручную, вы можете сгенерировать SRCSпеременную, используя функцию для выбора всех .cppи .hфайлов. Если исходный файл добавлен позже, повторный запуск makeвключит его.

Тем не менее, CMake (с такой командой file(GLOB ...)) явно генерирует список файлов и помещает его в автоматически сгенерированный Makefile. Если у вас есть новый исходный файл, вам нужно будет заново сгенерировать его Makefileпутем повторного запуска cmake.

редактировать: не нужно удалять Makefile.

Кара Дениз
источник
4
Нельзя просто перезапустить cmake, что должно удалить / изменить устаревший Makefile?
Итан
25
Это не ответ, это комментарий об ответе @ Kleist.
Neowizard
3
@Neowizard не в терминологии Stackoverflow.
Кара Дениз
1
Этот комментарий хорош, но он "стандартный", верно? Аскер уже использует cmake, поэтому предположение, что make может быть «умнее», не так уж полезно.
frankliuao
Так есть ли способ добавить новые исходные файлы, а затем собрать без повторного запуска cmake?
артины
6

Расширение для ответа @Kleist :

Так как CMake 3.12 дополнительные опции CONFIGURE_DEPENDS будет поддерживаться с помощью команд file(GLOB)и file(GLOB_RECURSE). С помощью этой опции нет нет потребности в вручную повторно запустить CMake после добавления / удаления исходного файла в каталоге - CMake будет повторно запускаться автоматически на следующий строительный проект.

Однако опция CONFIGURE_DEPENDS подразумевает, что соответствующий каталог будет перепроверяться при каждом запросе сборки , поэтому процесс сборки будет занимать больше времени, чем без CONFIGURE_DEPENDS .

Даже с доступной опцией CONFIGURE_DEPENDS, документация CMake по-прежнему не рекомендует использовать file(GLOB)или file(GLOB_RECURSE)собирать источники.

Цыварев
источник
«Документация CMake все еще не рекомендует использовать file(GLOB)или file(GLOB_RECURSE)собирать источники» Что они тогда рекомендуют? Используя что-то еще, чтобы собрать источники или вручную перечислить каждый отдельный исходный файл?
Томас
1
@Thomas: они рекомендуют вручную перечислять каждый исходный файл. Этот ответ дает отличное объяснение рекомендации.
Цыварев
-2

Так почему бы не использовать powershell для создания списка исходных файлов для вас. Посмотрите на этот скрипт

param (
    [Parameter(Mandatory=$True)]
    [string]$root 
)

if (-not (Test-Path  -Path $root)) {    
throw "Error directory does not exist"
}

#get the full path of the root
$rootDir = get-item -Path $root
$fp=$rootDir.FullName;


$files = Get-ChildItem -Path $root -Recurse -File | 
         Where-Object { ".cpp",".cxx",".cc",".h" -contains $_.Extension} | 
         Foreach {$_.FullName.replace("${fp}\","").replace("\","/")}

$CMakeExpr = "set(SOURCES "

foreach($file in $files){

    $CMakeExpr+= """$file"" " ;
}
$CMakeExpr+=")"
return $CMakeExpr;

Предположим, у вас есть папка с этой структурой

C:\Workspace\A
--a.cpp
C:\Workspace\B 
--b.cpp

Теперь сохраните этот файл как «generateSourceList.ps1», например, и запустите скрипт как

~>./generateSourceList.ps1 -root "C:\Workspace" > out.txt

файл out.txt будет содержать

set(SOURCE "A/a.cpp" "B/b.cpp")
Alcoforado
источник
Вопрос помечен кроссплатформенным - powershell не кроссплатформенный.
Рейххарт
@reichhart PowerShell работает на Linux и Mac и тоже
Noone
Я знаю. Но для PowerShell нет тега, а CMake уже кроссплатформенный. «Powershell» будет дополнительной зависимостью и очень редко используется в других ОС, кроме Windows. Вы можете найти даже больше разработчиков C # для Linux, чем людей с PowerShell. И самым важным фактом является вопрос: «Можно ли сделать это непосредственно в CMake? Как?»
Рейххарт