Quel est l'équivalent CMake de 'configure --prefix = DIR && make all install'?

386

Oui cmake . && make all install. Cela fonctionne, mais s'installe sur /usr/local.

Je dois installer sur un préfixe différent (par exemple, pour /usr).

Quelle est la ligne de commande cmakeet makesur laquelle installer au /usrlieu de /usr/local?

Andrei
la source
1
C'est une excellente question pour changer le répertoire d'installation à la volée, mais pourquoi est-ce un besoin apparemment si commun? De mon point de vue, la réponse devrait être N'UTILISEZ PAS une option de ligne de commande, éditez plutôt la base CMakeLists.txtpour pouvoir la définir et l'oublier. Je ne dis pas qu'il n'y a pas de cas d'utilisation commun pour changer le répertoire d'installation à la volée - il y a clairement à en juger par le nombre de votes - je suis juste assez nouveau pour CMake et curieux quand ce problème se pose.
CivFan
8
@CivFan est destiné aux utilisateurs qui souhaitent construire et installer le projet à un emplacement particulier, mais qui ne sont pas les mêmes personnes que les développeurs / mainteneurs du projet.
David Röthlisberger
4
@CivFan Donc, en tant que responsable, il n'est pas rare que je teste mon make installchemin temporaire pour m'assurer que tout ce qui doit être installé est installé au bon endroit sans gâcher ma machine de développement. Un seul exemple. Un autre cas est la compilation croisée pour une autre architecture.
Daniel
5
@CivFan: J'en ai besoin car je veux construire un package RPM. Si je dois changer le CMakeLists.txt, je dois patcher la source d'origine. Le simple fait d'avoir une option en ligne de commande me permet d'obtenir les bons chemins dans le specfichier Fedora .
Martin Ueding
1
@CivFan (et d'autres qui lisent ceci) pour info, il est généralement considéré comme une mauvaise idée de modifier le CMakeLists.txtfichier si vous êtes juste en train de créer et d'installer un logiciel - remplacer / définir des variables à partir de la ligne de commande ou du fichier de cache initial, etc. est le "consommateur" préféré façon de définir les options.
Ryan Pavlik

Réponses:

444

Vous pouvez passer n'importe quelle variable CMake sur la ligne de commande ou modifier des variables mises en cache à l'aide de ccmake / cmake-gui. Sur la ligne de commande,

cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr. && faire tout installer

Configurerait le projet, créerait toutes les cibles et installerait le préfixe / usr. Le type (PATH) n'est pas strictement nécessaire, mais entraînerait le cmake-gui basé sur Qt à présenter la boîte de dialogue de sélection de répertoire.

Quelques ajouts mineurs en tant que commentaires montrent clairement que fournir une équivalence simple ne suffit pas pour certains. La meilleure pratique serait d'utiliser un répertoire de construction externe, c'est-à-dire pas directement la source. Également pour utiliser une syntaxe CMake plus générique faisant abstraction du générateur.

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

Vous pouvez voir qu'il devient un peu plus long et n'est plus directement équivalent, mais est plus proche des meilleures pratiques sous une forme assez concise ... Le --config n'est utilisé que par les générateurs multi-configuration (c'est-à-dire MSVC), ignoré par d'autres.

Marcus D. Hanwell
la source
21
Vous vous demandez quoi: PATH est? C'est utile pour cmake-gui, aidant à choisir le widget pour cette variable. Voir le doc dans linux.die.net/man/1/cmake-gui (section set)
albfan
2
Ils fournissent des conseils à l'interface graphique de CMake comme indiqué, tout dans CMake est en fait une chaîne, mais la définition de PATH, FILEPATH, STRING, BOOL, etc. aide l'interface graphique à présenter un widget plus approprié.
Marcus D. Hanwell
13
Vous pouvez également utiliser: "cmake --build --target install." au lieu de faire.
RobertJMaynard
2
Quel est le point pour après / usr? /usr .
bodacydo
5
@bodacydo emplacement du dossier avec CMakeLists.txt à partir duquel nous générons.
Kamiccolo
48

La partie ": CHEMIN" de la réponse acceptée peut être omise. Cette syntaxe peut être plus mémorable:

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

... comme utilisé dans les réponses ici .

user2023370
la source
7
:PATHn'est pas une erreur .
kirbyfan64sos
29

Notez que dans CMake et Autotools, vous n'avez pas toujours à définir le chemin d'installation au moment de la configuration. Vous pouvez utiliser DESTDIR au moment de l'installation (voir également ici ) à la place comme dans:

make DESTDIR=<installhere> install

Voir aussi cette question qui explique la subtile différence entre DESTDIR et PREFIX.

Ceci est destiné aux installations par étapes et permet de stocker des programmes dans un emplacement différent de celui où ils sont exécutés, par exemple /etc/alternativesvia des liens symboliques.

Cependant, si votre package est déplaçable et n'a pas besoin de chemins codés en dur (préfixe) définis via l'étape de configuration, vous pourrez peut- être l'ignorer. Donc au lieu de:

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

vous courriez:

cmake . && make DESTDIR=/usr all install

Notez que, comme le souligne user7498341, ce n'est pas approprié dans les cas où vous devriez vraiment utiliser PREFIX.

Bruce Adams
la source
9
J'aime montrer l'utilisation de DESTDIR. Mais en fait, c'est faux. Vous devriez vous référer à la documentation de cmake cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html ... make DESTDIR=/home/john installqui installera le logiciel concerné en utilisant le préfixe d'installation, par exemple «/ usr / local» ajouté avec la valeur DESTDIR ce qui donne finalement «/ home / john / usr / local».
Joakim
1
Je ne pense pas que ce soit contradictoire. Si votre package est déplaçable, vous n'avez pas besoin de CMAKE_INSTALL_PREFIX, ou plutôt vous pouvez choisir l'une ou l'autre méthode. Si ce n'est pas le cas, car CMAKE_INSTALL_PREFIX sera intégré quelque part au moment de la construction.
Bruce Adams
si vous savez que votre générateur est Makefile ... Je préfère cmake --build build --target install -- DESTDIR=/usrnoter: cela devrait également fonctionner avec le générateur Ninja (les règles semblent contenir $ENV{DESTDIR})
Mizux
@Joakim autant que j'aimerais utiliser CMAKE_INSTALL_PREFIX, en incorporant ainsi le chemin d'installation dans les fichiers compilés. En l'occurrence, je construisais simplement un package .rpm, ce qui ne fonctionnerait pas. DESTDIR a fonctionné comme un charme pour mettre les choses en place.
M. Redstoner
18

La façon dont je construis la plateforme multi-projets CMake est la suivante:

/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
  • Les deux premières lignes créent le répertoire de construction hors source
  • La troisième ligne génère le système de construction spécifiant où placer le résultat de l'installation (que je place toujours dans ./project-root/build/stage - le chemin est toujours considéré par rapport au répertoire courant s'il n'est pas absolu)
  • La quatrième ligne crée le projet configuré .avec le buildsystem configuré dans la ligne précédente. Il exécutera la installcible qui crée également toutes les cibles dépendantes nécessaires si elles doivent être générées, puis copie les fichiers dans le CMAKE_INSTALL_PREFIX(ce qui est le cas dans ce cas ./project-root/build/stage. Pour les générations multi-configuration, comme dans Visual Studio, vous pouvez également spécifier la configuration avec le --config <config>drapeau optionnel .
  • La bonne partie lors de l'utilisation de la cmake --buildcommande est qu'elle fonctionne pour tous les générateurs (c'est-à-dire les makefiles et Visual Studio) sans avoir besoin de commandes différentes.

Ensuite, j'utilise les fichiers installés pour créer des packages ou les inclure dans d'autres projets ...

toeb
la source
Merci pour l'explication étape par étape! OMI c'est le seul moyen, sinon tout le point de cmake (indépendance de la plate-forme) est jeté ...
helmesjo
1
avez-vous oublié d'inclure le chemin vers les sources (../) à la ligne 3? BTW, cela devrait être la réponse acceptée.
Slava
1
La ligne 3 devrait êtrecmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
codenamezero
1
Comme note supplémentaire, de façon pragmatique, les gens utilisent make -j $(nproc), pour spécifier le nombre de threads de construction, faire cmake --build . --target=install --config=Release -- -j 8pour le générateur Makefile ou cmake --build . --target=install --config=Release -- /m:8pour le générateur Visual Studio avec 8 threads. En fait, vous pouvez passer tous les paramètres de ligne de commande après--
Cloud
1
@MrRedstoner -jn'est pas un drapeau pour cmake, tous les drapeaux qui suivent --passent au système de build sous-jacent ...
Cloud
4

Concernant la réponse de Bruce Adams:

Votre réponse crée une confusion dangereuse. DESTDIR est destiné aux installations hors de l'arborescence racine. Il permet de voir ce qui serait installé dans l'arborescence racine si l'on n'a pas spécifié DESTDIR. PREFIX est le répertoire de base sur lequel est basée l'installation réelle.

Par exemple, PREFIX = / usr / local indique que la destination finale d'un package est / usr / local. L'utilisation de DESTDIR = $ HOME installera les fichiers comme si $ HOME était la racine (/). Si, disons DESTDIR, était / tmp / destdir, on pourrait voir ce que «make install» affecterait. Dans cet esprit, DESTDIR ne devrait jamais affecter les objets construits.

Un segment makefile pour l'expliquer:

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

Les programmes doivent supposer que PREFIX est le répertoire de base du répertoire final (c'est-à-dire de production). La possibilité de créer un lien symbolique vers un programme installé dans DESTDIR = / quelque chose signifie simplement que le programme n'accède pas aux fichiers basés sur PREFIX car il ne fonctionnerait tout simplement pas. cat (1) est un programme qui (dans sa forme la plus simple) peut s'exécuter de n'importe où. Voici un exemple qui ne fonctionnera pas:

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

Si vous avez essayé d'exécuter prog ailleurs que $ PREFIX / bin / prog, prog.db ne sera jamais trouvé car il ne se trouve pas à son emplacement prévu.

Enfin, / etc / alternatives ne fonctionne vraiment pas de cette façon. Il existe des liens symboliques vers des programmes installés dans l'arborescence racine (par exemple, vi -> / usr / bin / nvi, vi -> / usr / bin / vim, etc.).

user7498341
la source
1
Cette réponse pourrait être mieux placée comme réponse à stackoverflow.com/questions/11307465/destdir-and-prefix-of-make
Bruce Adams
2

Il est considéré comme une mauvaise pratique d'invoquer le générateur réel (par exemple via make) si vous utilisez CMake . Il est fortement recommandé de le faire comme ceci:

  1. Configurer la phase:

    cmake -Hfoo -B_builds/foo/debug -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX=/usr
    
  2. Phases de construction et d' installation

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

En suivant cette approche, le générateur peut être facilement commuté (par exemple -GNinjapour Ninja ) sans avoir à mémoriser les commandes spécifiques au générateur.

Florian Wolters
la source
1
La réponse aurait pu être meilleure si une explication avait été fournie pour tous les arguments utilisés et pourquoi ils étaient utilisés. En particulier, quel est l'intérêt de l' --configargument?
Dmitry Kabanov