Каталог виводу / складання CMake


116

Я досить новачок у CMake, і прочитав кілька навчальних посібників, як ним користуватися, і написав кілька складних 50 рядків сценарію CMake, щоб зробити програму для 3-х різних компіляторів. Це, мабуть, завершує всі мої знання в CMake.

Тепер моя проблема полягає в тому, що у мене є якийсь вихідний код, папку якого я не хочу торкатися / плутати, коли я роблю програму. Я хочу, щоб усі CMake та makeвихідні файли та папки переходили ../Compile/, тому я змінив кілька змінних у своєму скрипті CMake для цього, і він працював колись, коли я робив щось подібне на своєму ноутбуці:

Compile$ cmake ../src
Compile$ make

Де я мав чистий вихід у теці, в якій я зараз перебуваю, саме це я і шукаю.

Тепер я перейшов на інший комп'ютер і перекомпілював CMake 2.8.11.2, і я майже повернувся до першого! Він завжди збирає річ у srcпапку, де CMakeLists.txtзнаходиться мій .

Частина, в якій я вибираю каталог у своєму скрипті CMake:

set(dir ${CMAKE_CURRENT_SOURCE_DIR}/../Compile/)
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${dir})
set(CMAKE_BUILD_FILES_DIRECTORY ${dir})
set(CMAKE_BUILD_DIRECTORY ${dir})
set(CMAKE_BINARY_DIR  ${dir})
SET(EXECUTABLE_OUTPUT_PATH ${dir})
SET(LIBRARY_OUTPUT_PATH ${dir}lib)
SET(CMAKE_CACHEFILE_DIR ${dir})

І тепер це завжди закінчується на:

-- Build files have been written to: /.../src

Я щось пропускаю?


4
Немає необхідності встановлювати всі змінні, які ви встановлюєте. CMake встановлює їх за умовчанням. Ви точно не повинні змінювати CMAKE_BINARY_DIRабо CMAKE_CACHEFILE_DIR. Що станеться, якщо ви видалите всі ці set()дзвінки і просто зробите cd Compile; rm -rf *; cmake ../src?
Ендже вже не пишається SO

5
В основному, якщо ви знаходитесь поза каталогом джерел під час запуску CMake, він не змінюватиме вихідний каталог, якщо ваш CMakeList прямо не каже про це.
Ендже вже не пишається SO

@Angew Дякую за пораду, що дивно! Я видалив усі ці рядки і просто використав cmake ../src, і це спрацювало як шарм! Це так дивно, тому що я спробував це раніше, коли я вперше вивчив CMake, і це не вийшло. Будь ласка, поставте свою відповідь в офіційній відповіді, щоб дати вам велику жирову галочку :)
Фізік-квант

1
Що мене врятувало, - зауваження @Adam Bowen, що "не можна створити збірку з вихідного коду для вихідного каталогу зі збіркою в джерелі"
Aur Saraf

Відповіді:


60

Немає необхідності встановлювати всі змінні, які ви встановлюєте. CMake встановлює їх за умовчанням. Ви точно не повинні змінювати CMAKE_BINARY_DIRабо CMAKE_CACHEFILE_DIR. Ставтесь до них як лише для читання.

Спочатку видаліть існуючий проблемний файл кешу з каталогу src:

cd src
rm CMakeCache.txt
cd ..

Потім видаліть усі set()команди і виконайте:

cd Compile
rm -rf *
cmake ../src

Поки ви знаходитесь поза каталогом джерел під час запуску CMake, він не змінює вихідний каталог, якщо ваш CMakeList прямо не скаже про це.

Після цього ви зможете подивитися, де CMake розміщує речі за замовчуванням, і лише якщо вас не влаштовують місця за замовчуванням (наприклад, значення за замовчуванням EXECUTABLE_OUTPUT_PATH), змінюйте лише ті, що вам потрібні. І спробувати виразити їх щодо CMAKE_BINARY_DIR, CMAKE_CURRENT_BINARY_DIR, і PROJECT_BINARY_DIRт.д.

Якщо ви подивитеся на документацію CMake, ви побачите змінні, розділені на семантичні розділи. За винятком дуже особливих обставин, ви повинні ставитися до всіх перелічених у розділі "Змінні, які надають інформацію" як лише для читання всередині CMakeLists.


2
Я почав використовувати cmake зі збірками в каталозі src ... спочатку ця техніка не вдалася. Після того як я видалив усі файли / кеші cmake в каталозі src, ця техніка спрацювала. Дякую!
Аві Тевет

18
Можливо, краще не радити користуватися rm -rf *. Це не дуже добре, якщо cd Compileне вдасться ...
Роман

2
@Roman Я вважаю такі приклади командного рядка досить псевдокодом. Це менш дослівно і точніше, ніж введення "введіть у каталог Compile, видаліть усе там, а потім запустіть CMake зі шляху до вихідного dir". Я припускаю основний здоровий глузд і судження частини читача.
Ендже вже не пишається SO

@AviTevet: Я думаю, що це правильна відповідь. Якщо в каталозі джерела є файли кешу cmake з попереднього виклику cmake, ви не зможете cmake вибрати інший каталог для створених файлів, якщо ви не видалите всі старі з вихідного каталогу. На мою думку досить розбита поведінка CMake. Чому б вам не написати ще одну відповідь?
Jo So

113

Це здається, що ви хочете зібрати джерело . Є кілька способів створити збірку з вихідного коду.

  1. Робіть те, що ви робили, бігайте

    cd /path/to/my/build/folder
    cmake /path/to/my/source/folder

    що призведе до CMake для створення збірки дерева в /path/to/my/build/folderдля дерева вихідних текстів в /path/to/my/source/folder.

    Після створення файлу cmake запам'ятовує, де знаходиться папка вихідного коду - так що ви можете повторно запустити cmake на дереві збірки за допомогою

    cmake /path/to/my/build/folder

    або навіть

    cmake .

    якщо ваш поточний каталог вже папка збірки.

  2. Для CMake 3.13 або новішої версії використовуйте ці параметри для встановлення джерела та створення папок

    cmake -B/path/to/my/build/folder -S/path/to/my/source/folder
  3. Для старих CMake використовуйте деякі незадокументовані параметри для встановлення джерела та створення папок :

    cmake -B/path/to/my/build/folder -H/path/to/my/source/folder

    який буде робити те саме, що і (1), але без опори на поточний робочий каталог.

CMake за замовчуванням розміщує всі свої результати у дереві збірки , тому, якщо ви не використовуєте вільно ${CMAKE_SOURCE_DIR}або ${CMAKE_CURRENT_SOURCE_DIR}у своїх файлах cmake, він не повинен торкатися вашого вихідного дерева .

Найголовніше, що може піти не так, якщо ви раніше створили дерево збірки у своєму вихідному дереві (тобто у вас є збірка у джерелі ). Як тільки ви це зробите, друга частина (1) вище починається, а cmake не вносить жодних змін у джерело та місця розташування. Таким чином, ви не можете створити збірку без вихідних даних для вихідного каталогу із збіркою в джерелі . Ви можете це виправити досить легко, видаливши (як мінімум) CMakeCache.txtз вихідного каталогу. Є кілька інших файлів (в основному в CMakeFilesкаталозі), які CMake генерує, що ви також повинні видалити, але вони не спричинять cmake трактувати вихідне дерево як дерево збірки.

Оскільки збірки без вихідних джерел часто є більш бажаними, ніж збірки в джерелах, ви можете змінити свій cmake, щоб вимагати збірок з джерела:

# Ensures that we do an out of source build

MACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD MSG)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${CMAKE_BINARY_DIR}" insource)
     GET_FILENAME_COMPONENT(PARENTDIR ${CMAKE_SOURCE_DIR} PATH)
     STRING(COMPARE EQUAL "${CMAKE_SOURCE_DIR}"
     "${PARENTDIR}" insourcesubdir)
    IF(insource OR insourcesubdir)
        MESSAGE(FATAL_ERROR "${MSG}")
    ENDIF(insource OR insourcesubdir)
ENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)

MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
    "${CMAKE_PROJECT_NAME} requires an out of source build."
)

Вищевказаний макрос походить від часто використовуваного модуля, який називається MacroOutOfSourceBuild. У Google є чимало джерел, MacroOutOfSourceBuild.cmakeале я не можу знайти оригінал, і він досить короткий, щоб включити сюди повністю.

На жаль, cmake зазвичай записує кілька файлів до моменту виклику макросу, тому, хоча це не дозволить вам реально виконати збірку, вам все одно потрібно буде видалити CMakeCache.txtта CMakeFiles.

Вам може бути корисно встановити шляхи, до яких записуються бінарні файли, спільні бібліотеки та статичні бібліотеки - у такому випадку дивіться, як я можу зробити висновок cmake у din 'dir? (відмова, у мене є відповідь на це питання, але я знаю про це).


Насправді варіант встановлення вихідної папки є -S, а не-H
smac89

@ smac89 Дякую! Схоже, вони їх задокументували в 3.13 - я оновив відповідь, щоб відобразити сучасний CMake.
Адам Боуен

8

Перетворення мого коментаря у відповідь:

У випадку, якщо хтось зробив те, що я зробив, це було розпочато, помістивши всі файли збірки у вихідний каталог:

cd src
cmake .

CMake поставить купу файлів збірки і кеш - файли ( CMakeCache.txt, CMakeFiles, cmake_install.cmakeі т.д.) в srcреж.

Щоб перейти на збірку вихідних джерел, мені довелося видалити всі ці файли. Тоді я міг би зробити те, що @Angew рекомендував у своїй відповіді:

mkdir -p src/build
cd src/build
cmake ..

7

Станом на CMake Wiki :

CMAKE_BINARY_DIR, якщо ви будуєте джерело, це те саме, що і CMAKE_SOURCE_DIR, інакше це каталог верхнього рівня дерева вашої збірки

Порівняйте ці дві змінні, щоб визначити, чи було запущено збірку з джерела


6

Ви не повинні покладатися на жорстко закодоване ім’я dir build у своєму сценарії, тому рядок з ../Compileпотрібно змінити.

Це тому, що користувачеві слід куди компілювати.

Замість цього використовуйте одну із заздалегідь заданих змінних: http://www.cmake.org/Wiki/CMake_Useful_Variables (шукайте CMAKE_BINARY_DIRта CMAKE_CURRENT_BINARY_DIR)


2
це просто так, що я шукав - CMAKE_CURRENT_BINARY_DIR, як правило, розповість про поточний шлях бінарної збірки. Можливо, може бути використаний для встановлення залежних конструкцій libs / bin.
парасити
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.