Що таке CMake еквівалент "configure --prefix = DIR && make all install"?


386

Я роблю cmake . && make all install. Це працює, але встановлюється в /usr/local.

Мені потрібно встановити інший префікс (наприклад, до /usr).

Що таке cmakeі makeкомандний рядок для установки на /usrа /usr/local?


1
Це чудове запитання щодо зміни каталогу встановлення на ходу, але чому це така, очевидно, загальна потреба? З моєї точки зору, відповідь повинна бути НЕ використовувати параметр командного рядка, а не редагувати базу, CMakeLists.txtщоб ви могли встановити її та забути. Я не кажу, що не існує загального випадку використання для зміни каталогу встановлення на ходу - очевидно, судячи з кількості голосів - я просто новачок CMake і цікавий, коли виникає ця проблема.
CivFan

8
@CivFan - це задоволення користувачів, які хочуть створити та встановити проект у певному місці, але вони не такі ж люди, як розробники / підтримувачі проекту.
Девід Ретлісбергер

4
@CivFan Отже, як сервіс, не рідкість для мене тестувати свій make installтимчасовий шлях, щоб переконатися, що все, що потрібно встановити, встановити в потрібне місце, не псуючи мою розробку. Лише один приклад. Інший випадок - перехресне компілювання для іншої архітектури.
Даніель

5
@CivFan: Мені це потрібно, тому що я хочу створити пакет RPM. Якщо мені потрібно змінити CMakeLists.txt, тоді мені потрібно проклеїти початкове джерело. Наявність опції командного рядка дозволяє мені отримати шляхи прямо у specфайл Fedora .
Мартін Удінг

1
@CivFan (та інші, що читають це) FYI, зазвичай вважається поганою ідеєю редагувати CMakeLists.txtфайл, якщо ви просто створюєте та встановлюєте програмне забезпечення - переосмислення / налаштування змінних з командного рядка або початкового файлу кешу тощо є кращим "споживачем" спосіб налаштування параметрів.
Райан Павлик

Відповіді:


444

Ви можете передавати будь-яку змінну CMake в командному рядку або редагувати кешовані змінні за допомогою ccmake / cmake-gui. У командному рядку

cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr. && змусити все встановити

Налаштував би проект, створив усі цілі та встановив би префікс / usr. Тип (PATH) не є суворо необхідним, але це призведе до того, що на основі Qt cmake-gui буде представлено діалог вибору каталогу.

Деякі незначні доповнення як коментарі дають зрозуміти, що надання простої еквівалентності для деяких недостатньо. Найкращою практикою було б використання зовнішнього каталогу збірки, тобто не джерела безпосередньо. Також використовувати більш загальний синтаксис CMake, що абстрагує генератор.

mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr .. && cmake --build. - встановити ціль - випустити конфіг

Ви можете бачити, що вона стає зовсім трохи довшою, і вже не є прямо еквівалентною, але ближче до найкращих практик у досить стислому вигляді ... --config використовується лише генераторами з декількома конфігураціями (тобто MSVC), ігнорується іншими.


21
Цікаво, що: ПАТ? Це корисно для cmake-gui, допомагаючи вибрати віджет для цієї змінної. Дивіться doc у linux.die.net/man/1/cmake-gui (розділ set)
albfan

2
Вони надають підказки для GUI CMake, як зазначено, все в CMake - це фактично рядок, але налаштування PATH, FILEPATH, STRING, BOOL тощо допомагає GUI представити більш відповідний віджет.
Маркус Д. Ганвелл

13
Ви також можете використовувати: "cmake --build --target install." замість робити.
RobertJMaynard

2
Що таке точка після / usr? /usr .
bodacydo

5
@bodacydo розташування папки із CMakeLists.txt, з якого ми генеруємо.
Каміколо

48

Частину ": PATH" у прийнятій відповіді можна опустити. Цей синтаксис може бути більш пам'ятним:

cmake -DCMAKE_INSTALL_PREFIX=/usr . && make all install

... як він використовується в відповідях тут .



29

Зауважте, що і в CMake, і в Autotools вам не завжди потрібно встановлювати шлях установки під час налаштування. Ви можете використовувати DESTDIR під час встановлення (див. Також тут ) замість цього:

make DESTDIR=<installhere> install

Дивіться також це питання, яке пояснює тонку різницю між DESTDIR та PREFIX.

Це призначено для поетапних встановлень і для того, щоб зберігати програми в іншому місці, де вони виконуються, наприклад, /etc/alternativesчерез символічні посилання.

Однак якщо ваш пакет переміщується і не потребує жодних жорстких кодованих (префіксів) шляхів, встановлених через етап налаштування, можливо, ви зможете його пропустити. Тож замість:

cmake -DCMAKE_INSTALL_PREFIX=/usr . && make all install

ти біжиш:

cmake . && make DESTDIR=/usr all install

Зауважте, що, як вказує user7498341, це не підходить для випадків, коли ви дійсно повинні використовувати PREFIX.


9
Мені подобається показувати використання DESTDIR. Але насправді це неправильно. Вам слід посилатися на cmake docs cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html ..., make DESTDIR=/home/john installякий встановить відповідне програмне забезпечення за допомогою префікса встановлення, наприклад, "/ usr / local", заздалегідь встановленому значенням DESTDIR що нарешті дає "/ home / john / usr / local".
Йоаким

1
Я не думаю, що це суперечливо. Якщо ваш пакет переміщається, вам не потрібен CMAKE_INSTALL_PREFIX, а точніше, ви можете вибрати будь-який спосіб. Якщо цього не зробити, тому що CMAKE_INSTALL_PREFIX буде випечений десь під час збирання.
Брюс Адамс

якщо ви знаєте, що ваш генератор Makefile ... Я вважаю за краще cmake --build build --target install -- DESTDIR=/usr: це також має працювати з генератором Ninja (правила, схоже, містять $ENV{DESTDIR})
Mizux

@Joakim стільки, скільки я хотів би використовувати CMAKE_INSTALL_PREFIX, зробивши так, вбудований шлях встановлення у компільовані файли. Як це буває, я просто будував пакет .rpm, щоб цього не робити. DESTDIR працював як принадність для отримання речей у buildroot.
Містер Редстонер

18

Я будую крос-платформу проектів CMake наступним чином:

/project-root> mkdir build
/project-root> cd build
/project-root/build> cmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
/project-root/build> cmake --build . --target=install --config=Release
  • Перші два рядки створюють каталог збірки вихідних джерел
  • Третій рядок генерує систему збирання, вказуючи, куди слід помістити результат установки (який я завжди розміщую ./project-root/build/stage- шлях завжди вважається відносно поточного каталогу, якщо він не є абсолютним)
  • Четвертий рядок будує проект, сконфігурований .із системою builds, налаштованою в рядку раніше. Він виконає installціль, яка також будує всі необхідні залежні цілі, якщо їх потрібно створити, а потім скопіює файли в CMAKE_INSTALL_PREFIX(що в цьому випадку є ./project-root/build/stage. Для складання багатоконфігурації, як у Visual Studio, ви також можете вказати конфігурацію з необов'язковий --config <config>прапор.
  • Хороша частина команди при використанні cmake --buildкоманди полягає в тому, що вона працює для всіх генераторів (тобто makefiles та Visual Studio), не потребуючи різних команд.

Після цього я використовую встановлені файли для створення пакетів або включення їх до інших проектів ...


Дякуємо за покрокове пояснення! IMO - це єдиний спосіб, інакше вся суть cmake (незалежності платформи) відкидається ...
helmesjo

1
Ви забули включити шлях до джерел (../) у рядок 3? До речі, це повинна бути прийнята відповідь.
Слава

1
LIne 3 має бутиcmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
codenamezero

1
В якості додаткової примітки, прагматично, люди використовують make -j $(nproc)для визначення кількості ниток збірки, роблять cmake --build . --target=install --config=Release -- -j 8для генератора Makefile або cmake --build . --target=install --config=Release -- /m:8для генератора Visual Studio з 8 потоками. Насправді, ви можете передати будь-які параметри командного рядка після--
Cloud Cloud

1
@MrRedstoner -jне є прапором для cmake, усі прапори з'являються після того, --як переходять до основної системи збирання ...
Хмара

4

Щодо відповіді Брюса Адамса:

Ваша відповідь створює небезпечну плутанину. DESTDIR призначений для встановлення з кореневого дерева. Це дозволяє побачити, що було б встановлено в кореневому дереві, якби не вказано DESTDIR. PREFIX - базовий каталог, на якому базується реальна установка.

Наприклад, PREFIX = / usr / local вказує, що кінцевим пунктом призначення пакету є / usr / local. Використовуючи DESTDIR = $ HOME встановить файли так, ніби $ HOME був коренем (/). Якщо, скажімо, DESTDIR, був / tmp / destdir, можна було б побачити, що вплине на "встановлення". У цьому дусі DESTDIR ніколи не повинен впливати на побудовані об'єкти.

Сегмент makefile, щоб пояснити це:

install:
    cp program $DESTDIR$PREFIX/bin/program

Програми повинні припускати, що PREFIX є базовим каталогом остаточного (тобто виробничого) каталогу. Можливість посилання на програму, встановлену в DESTDIR = / щось означає, що програма не має доступу до файлів, заснованих на PREFIX, як це просто не працює. cat (1) - програма, яка (у найпростішому вигляді) може працювати з будь-якого місця. Ось приклад, який не буде:

prog.pseudo.in:
    open("@prefix@/share/prog.db")
    ...

prog:
    sed -e "s/@prefix@/$PREFIX/" prog.pseudo.in > prog.pseudo
    compile prog.pseudo

install:
    cp prog $DESTDIR$PREFIX/bin/prog
    cp prog.db $DESTDIR$PREFIX/share/prog.db

Якщо ви спробували запустити прогу з іншого місця, ніж $ PREFIX / bin / prog, prog.db ніколи не знайдеться, оскільки він не знаходиться в очікуваному місці.

Нарешті, / etc / alternative дійсно не працює таким чином. Існують посилання на програми, встановлені в кореневому дереві (наприклад, vi -> / usr / bin / nvi, vi -> / usr / bin / vim тощо).


1
Ця відповідь може бути краще розміщена як відповідь на stackoverflow.com/questions/11307465/destdir-and-prefix-of-make
Брюс Адамс

2

Вважається поганою практикою викликати фактичний генератор (наприклад, через make), якщо використовується CMake . Дуже рекомендується робити це так:

  1. Налаштування фази:

    cmake -Hfoo -B_builds/foo/debug -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX=/usr
    
  2. Побудова та встановлення фаз

    cmake --build _builds/foo/debug --config Debug --target install
    

Дотримуючись такого підходу, генератор можна легко перемикати (наприклад, -GNinjaдля Ninja ), не запам'ятовуючи жодних конкретних для генератора команд.


1
Відповідь могла бути кращою, якби пояснення було надано всім використаним аргументам та чому вони використовуються. Зокрема, в чому суть --configаргументу?
Дмитро Кабанов

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.