Автоматично додавати всі файли в папці до цілі за допомогою CMake?


163

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

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


Btw. у програмі Visual Studio, принаймні, у проектах C #, у провіднику проектів є кнопка панелі інструментів під назвою показати всі файли. Це робить усі підкаталоги проекту видимими, сірими, якщо вони не містять файлів, логічно включених у проект. Ви можете включити ці каталоги через контекстне меню, яке включає всі вихідні файли всередині них, рекурсивно :)
yeoman

Відповіді:


228

Можливо. Наприклад, з 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.
Seamus Connor


8
> "Ми не рекомендуємо використовувати GLOB для збору списку вихідних файлів з вашого вихідного дерева. Якщо жоден файл CMakeLists.txt не змінюється, коли джерело додається або видаляється, то створена система збірки не може знати, коли просити CMake відновити." Це більше не рекомендується в документах CMAKE3.7, пов’язаних Hand1Cloud
потрійний

4
яка альтернатива GLOB тоді?
Shayne

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
Це не відповідь, це коментар щодо відповіді @ Клейста.
Neowizard

3
@Neowizard не в термінології Stackoverflow.
kara deniz

1
Цей коментар приємний, але він "стандартний", правда? Аскер вже використовує cmake, тому пропозиція робити може бути "розумнішою" - це не так корисно.
frankliuao

Так чи є можливість додати нові вихідні файли та потім створити без повторного запуску cmake?
artin

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

Так чому б не використати повноваження, щоб створити список вихідних файлів для вас. Погляньте на цей сценарій

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

Тепер збережіть цей файл як "generatorSourceList.ps1", наприклад, і запустіть сценарій як

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

Файл out.txt буде містити

set(SOURCE "A/a.cpp" "B/b.cpp")

Питання позначено крос-платформою - повноваження не є крос-платформою.
рейххарт

@reichhart powershell працює на linux та і mac теж
ніхто

Я знаю. Але немає тегів для powershell, і "CMake" вже є кросплатформою. "Powershell" була б додатковою залежністю і дуже рідко використовується в інших ОС, ніж Windows. Ви можете знайти навіть більше розробників C # в Linux, ніж людей з повноцінними оболонками. І найважливішим фактом є питання: "Чи можна це зробити безпосередньо в CMake? Як?"
рейххарт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.