Что 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 (и другие читающие это) К вашему сведению, обычно считается плохой идеей редактировать CMakeLists.txtфайл, если вы просто собираете и устанавливаете программное обеспечение - предпочтительным «потребителем» является переопределение / установка переменных из командной строки или исходного файла кэша и т. Д. способ настройки параметров.
Райан Павлик

Ответы:

444

Вы можете передать любую переменную CMake в командной строке или отредактировать кэшированные переменные, используя ccmake / cmake-gui. В командной строке

cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr. && сделать все установить

Настроит проект, создаст все цели и установит префикс / usr. Тип (PATH) не является строго обязательным, но может привести к тому, что cmake-gui на основе Qt представит диалоговое окно выбора каталога.

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

mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr .. && cmake --build. --target install --config Release

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

Маркус Д. Ханвелл
источник
21
Хотите знать, что: PATH? Это полезно для cmake-gui, помогая выбрать виджет для этой переменной. Смотрите документ в linux.die.net/man/1/cmake-gui (раздел set)
albfan
2
Они предоставляют подсказки для графического интерфейса CMake, как указано, все в CMake фактически является строкой, но установка PATH, FILEPATH, STRING, BOOL и т. Д. Помогает графическому интерфейсу представить более подходящий виджет.
Маркус Д. Ханвелл
13
Вы также можете использовать: "cmake --build --target install." вместо того, чтобы делать.
РобертДжейнард
2
Какова точка для после / usr? /usr .
бодасидо
5
@bodacydo расположение папки с CMakeLists.txt, из которого мы генерируем.
Kamiccolo
48

Часть ": PATH" в принятом ответе может быть опущена. Этот синтаксис может быть более запоминающимся:

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

... как используется в ответах здесь .

user2023370
источник
7
:PATHэто не ошибка .
kirbyfan64sos
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

Обратите внимание, что, как указывает пользователь 7498341, это не подходит для случаев, когда вам действительно следует использовать 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- путь всегда считается относительно текущего каталога, если он не абсолютен)
  • Четвертая строка .собирает проект, настроенный в системе сборки, настроенной в строке ранее. Он выполнит installцель, которая также создает все необходимые зависимые цели, если они должны быть собраны, и затем скопирует файлы в CMAKE_INSTALL_PREFIX(что в данном случае является ./project-root/build/stage. Для сборок с несколькими конфигурациями, как в Visual Studio, вы также можете указать конфигурацию с помощью необязательный --config <config>флаг.
  • Хорошая сторона при использовании cmake --buildкоманды заключается в том, что она работает для всех генераторов (т.е. make-файлов и Visual Studio) без необходимости использования других команд.

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

toeb
источник
Спасибо за пошаговое объяснение! ИМО это единственный способ, иначе весь смысл cmake (независимости от платформы) отбрасывается ...
helmesjo
1
Вы забыли включить путь к источникам (../) в строке 3? Кстати, это должен быть принятый ответ.
Слава
1
Линия 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
1
@MrRedstoner -j- это не флаг для cmake, все флаги приходят после того, --как он передается в базовую систему сборки ...
Облако
4

Относительно ответа Брюса Адамса:

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

Например, PREFIX = / usr / local указывает, что конечным пунктом назначения пакета является / usr / local. Использование DESTDIR = $ HOME установит файлы, как если бы $ HOME был корневым каталогом (/). Если, скажем, DESTDIR, был / tmp / destdir, можно было бы увидеть, как повлияет «make install». В этом духе 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

Если вы попытаетесь запустить prog из другого места, кроме $ PREFIX / bin / prog, prog.db никогда не будет найден, поскольку он не находится в ожидаемом месте.

Наконец, / etc / alternatives действительно не работает таким образом. Существуют символические ссылки на программы, установленные в корневом дереве (например, vi -> / usr / bin / nvi, vi -> / usr / bin / vim и т. Д.).

user7498341
источник
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для ниндзя ) без необходимости запоминать какие-либо специфичные для генератора команды.

Флориан Уолтерс
источник
1
Ответ мог бы быть лучше, если бы было дано объяснение всем использованным аргументам и почему они используются. В частности, в чем смысл --configаргумента?
Дмитрий Кабанов