Was ist CMake-Äquivalent zu 'configure --prefix = DIR && make all install'?

386

Das tue ich cmake . && make all install. Dies funktioniert, wird aber installiert /usr/local.

Ich muss zu einem anderen Präfix installieren (zum Beispiel zu /usr).

Auf welcher cmakeund- makeBefehlszeile soll statt installiert /usrwerden /usr/local?

Andrei
quelle
1
Dies ist eine gute Frage, um das Installationsverzeichnis im laufenden Betrieb zu ändern, aber warum ist dies ein so scheinbar häufiges Bedürfnis? Aus meiner Sicht sollte die Antwort NICHT eine Befehlszeilenoption verwenden, sondern die Basis bearbeiten, CMakeLists.txtdamit Sie sie festlegen und vergessen können. Ich sage nicht, dass es keinen allgemeinen Anwendungsfall gibt, um das Installationsverzeichnis im laufenden Betrieb zu ändern - es wird eindeutig anhand der Anzahl der Stimmen beurteilt - ich bin für CMake noch ziemlich neu und neugierig, wenn dieses Problem auftritt.
CivFan
8
@CivFan richtet sich an Benutzer, die das Projekt an einem bestimmten Ort erstellen und installieren möchten, aber nicht dieselben Personen wie die Entwickler / Betreuer des Projekts sind.
David Röthlisberger
4
@CivFan Als Betreuer ist es nicht ungewöhnlich, dass ich meinen make installPfad auf einen temporären Pfad teste , um sicherzustellen, dass alles, was installiert werden muss, am richtigen Ort installiert wurde, ohne meine Entwicklungsmaschine zu beschädigen. Nur ein Beispiel. Ein anderer Fall ist das Cross-Compilieren für eine andere Architektur.
Daniel
5
@CivFan: Ich brauche das, weil ich ein RPM-Paket erstellen möchte. Wenn ich das ändern müsste, muss CMakeLists.txtich die Originalquelle patchen. Wenn ich nur eine Befehlszeilenoption habe, kann ich die Pfade direkt in der Fedora- specDatei finden.
Martin Ueding
1
@CivFan (und andere, die dies lesen) Zu Ihrer Information, es wird im Allgemeinen als schlechte Idee angesehen, die CMakeLists.txtDatei zu bearbeiten , wenn Sie nur Software erstellen und installieren - das Überschreiben / Festlegen von Variablen über die Befehlszeile oder die anfängliche Cache-Datei usw. ist der bevorzugte "Verbraucher". Art der Einstellung von Optionen.
Ryan Pavlik

Antworten:

444

Sie können jede CMake-Variable in der Befehlszeile übergeben oder zwischengespeicherte Variablen mit ccmake / cmake-gui bearbeiten. In der Befehlszeile

cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr. && alle installieren lassen

Würde das Projekt konfigurieren, alle Ziele erstellen und unter dem Präfix / usr installieren. Der Typ (PATH) ist nicht unbedingt erforderlich, würde jedoch dazu führen, dass die Qt-basierte cmake-gui den Dialog zur Verzeichnisauswahl anzeigt.

Einige kleinere Ergänzungen als Kommentare machen deutlich, dass die Bereitstellung einer einfachen Äquivalenz für einige nicht ausreicht. Die beste Vorgehensweise wäre, ein externes Build-Verzeichnis zu verwenden, dh nicht die Quelle direkt. Verwenden Sie auch eine allgemeinere CMake-Syntax, um den Generator zu abstrahieren.

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

Sie können sehen, dass es etwas länger wird und nicht mehr direkt gleichwertig ist, sondern in einer ziemlich präzisen Form näher an den Best Practices liegt ... Die --config wird nur von Generatoren mit mehreren Konfigurationen (dh MSVC) verwendet und ignoriert Von anderen.

Marcus D. Hanwell
quelle
21
Fragen Sie sich, was: PATH ist? Es ist nützlich für cmake-gui und hilft bei der Auswahl des Widgets für diese Variable. Siehe doc in linux.die.net/man/1/cmake-gui (Set-Abschnitt)
Albfan
2
Sie geben Hinweise auf die CMake-GUI, wie angegeben. Alles in CMake ist praktisch eine Zeichenfolge. Durch Festlegen von PATH, FILEPATH, STRING, BOOL usw. kann die GUI jedoch ein geeigneteres Widget präsentieren.
Marcus D. Hanwell
13
Sie können auch Folgendes verwenden: "cmake --build --target install." statt machen.
RobertJMaynard
2
Was ist der Punkt für after / usr? /usr .
Bodacydo
5
@ bodacydo Speicherort des Ordners mit CMakeLists.txt, aus dem wir generieren.
Kamiccolo
48

Der Teil ": PATH" in der akzeptierten Antwort kann weggelassen werden. Diese Syntax kann einprägsamer sein:

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

... wie in den Antworten hier verwendet .

user2023370
quelle
7
:PATHist kein Fehler .
Kirbyfan64sos
29

Beachten Sie, dass Sie sowohl in CMake als auch in Autotools nicht immer den Installationspfad zur Konfigurationszeit festlegen müssen. Sie können DESTDIR zur Installationszeit verwenden (siehe auch hier ), wie in:

make DESTDIR=<installhere> install

Siehe auch diese Frage, die den subtilen Unterschied zwischen DESTDIR und PREFIX erklärt.

Dies ist für inszenierte Installationen vorgesehen und ermöglicht das Speichern von Programmen an einem anderen Ort als dem, an dem sie ausgeführt werden, z /etc/alternatives. B. über symbolische Links.

Wenn Ihr Paket jedoch verschiebbar ist und keine fest codierten (Präfix-) Pfade benötigt, die über die Konfigurationsphase festgelegt wurden, können Sie es möglicherweise überspringen. Also statt:

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

du würdest rennen:

cmake . && make DESTDIR=/usr all install

Beachten Sie, dass dies, wie user7498341 betont, nicht für Fälle geeignet ist, in denen Sie PREFIX wirklich verwenden sollten.

Bruce Adams
quelle
9
Ich mag es, die Verwendung von zu zeigen DESTDIR. Aber eigentlich ist das falsch. Sie sollten auf das verweisen Cmake docs cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html ... , make DESTDIR=/home/john installwelche die betreffende Software mit dem Installations Präfix, zB installieren „/ usr / local“ mit dem DESTDIR Wert vorangestellt was schließlich "/ home / john / usr / local" gibt.
Joakim
1
Ich denke nicht, dass das widersprüchlich ist. Wenn Ihr Paket verschiebbar ist, benötigen Sie CMAKE_INSTALL_PREFIX nicht. Sie können auch eine der beiden Methoden auswählen. Wenn Sie dies nicht tun, wird CMAKE_INSTALL_PREFIX zur Erstellungszeit irgendwo eingebrannt.
Bruce Adams
Wenn Sie wissen, dass Ihr Generator Makefile ist ... Ich bevorzuge cmake --build build --target install -- DESTDIR=/usrHinweis: Dies sollte auch mit Ninja Generator funktionieren (Regeln scheinen zu enthalten $ENV{DESTDIR})
Mizux
@Joakim so oft ich CMAKE_INSTALL_PREFIX verwenden möchte, wobei der Installationspfad in die kompilierten Dateien eingebettet wurde. Zufällig habe ich lediglich ein RPM-Paket erstellt, das würde also nicht funktionieren. DESTDIR wirkte wie ein Zauber, um Dinge in die Wurzel zu bekommen.
Herr Redstoner
18

Die Art und Weise, wie ich plattformübergreifende CMake-Projekte erstelle, ist folgende:

/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
  • In den ersten beiden Zeilen wird das Build-Verzeichnis außerhalb der Quelle erstellt
  • In der dritten Zeile wird das Build-System generiert, das angibt, wo das Installationsergebnis abgelegt werden soll (das ich immer platziere ./project-root/build/stage- der Pfad wird immer relativ zum aktuellen Verzeichnis betrachtet, wenn er nicht absolut ist).
  • In der vierten Zeile wird das Projekt erstellt, das .mit dem in der vorherigen Zeile konfigurierten Buildsystem konfiguriert wurde. Es führt das installZiel aus, das auch alle erforderlichen abhängigen Ziele erstellt, wenn diese erstellt werden müssen, und kopiert dann die Dateien in das CMAKE_INSTALL_PREFIX(in diesem Fall ./project-root/build/stage. Bei Builds mit mehreren Konfigurationen, wie in Visual Studio, können Sie auch die Konfiguration mit angeben die optionale --config <config>Flagge.
  • Der gute Teil bei der Verwendung des cmake --buildBefehls ist, dass er für alle Generatoren (dh Makefiles und Visual Studio) funktioniert, ohne dass unterschiedliche Befehle erforderlich sind.

Danach verwende ich die installierten Dateien, um Pakete zu erstellen oder sie in andere Projekte aufzunehmen ...

toeb
quelle
Danke für die Schritt-für-Schritt-Erklärung! IMO ist dies der einzige Weg, sonst wird der ganze Punkt von cmake (Plattformunabhängigkeit) verworfen ...
helmesjo
1
Haben Sie vergessen, den Pfad zu den Quellen (../) in Zeile 3 aufzunehmen? Übrigens sollte dies die akzeptierte Antwort sein.
Slava
1
LIne 3 sollte seincmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
Codenamezero
1
Als zusätzliche Anmerkung verwenden die Benutzer pragmatisch, make -j $(nproc)um die Anzahl der Build-Threads anzugeben, cmake --build . --target=install --config=Release -- -j 8für den Makefile-Generator oder cmake --build . --target=install --config=Release -- /m:8für den Visual Studio-Generator mit 8 Threads. Tatsächlich können Sie alle Befehlszeilenparameter nach--
Cloud
1
@MrRedstoner -jist kein Flag für cmake, alle Flags, die danach kommen --, werden an das zugrunde liegende Build-System übergeben ...
Cloud
4

In Bezug auf Bruce Adams Antwort:

Ihre Antwort schafft gefährliche Verwirrung. DESTDIR ist für Installationen außerhalb des Stammbaums vorgesehen. Man kann sehen, was im Stammbaum installiert werden würde, wenn man DESTDIR nicht angeben würde. PREFIX ist das Basisverzeichnis, auf dem die eigentliche Installation basiert.

Beispielsweise gibt PREFIX = / usr / local an, dass das endgültige Ziel eines Pakets / usr / local ist. Wenn Sie DESTDIR = $ HOME verwenden, werden die Dateien so installiert, als ob $ HOME das Stammverzeichnis (/) wäre. Wenn, sagen wir DESTDIR, / tmp / destdir wäre, könnte man sehen, wie sich 'make install' auswirken würde. In diesem Sinne sollte DESTDIR niemals die gebauten Objekte beeinflussen.

Ein Makefile-Segment, um es zu erklären:

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

Programme müssen davon ausgehen, dass PREFIX das Basisverzeichnis des endgültigen Verzeichnisses (dh des Produktionsverzeichnisses) ist. Die Möglichkeit, ein in DESTDIR = / etwas installiertes Programm zu verknüpfen, bedeutet nur, dass das Programm nicht auf Dateien zugreift, die auf PREFIX basieren, da dies einfach nicht funktionieren würde. cat (1) ist ein Programm, das (in seiner einfachsten Form) von überall ausgeführt werden kann. Hier ist ein Beispiel, das nicht geht:

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

Wenn Sie versuchen würden, prog von einem anderen Ort als $ PREFIX / bin / prog auszuführen, wird prog.db niemals gefunden, da es sich nicht an der erwarteten Position befindet.

Schließlich funktioniert / etc / alternatives wirklich nicht so. Es gibt Symlinks zu Programmen, die im Stammbaum installiert sind (z. B. vi -> / usr / bin / nvi, vi -> / usr / bin / vim usw.).

user7498341
quelle
1
Diese Antwort könnte besser als Antwort auf stackoverflow.com/questions/11307465/destdir-and-prefix-of-make
Bruce Adams
2

Es wird als schlechte Praxis angesehen, den tatsächlichen Generator (z. B. via make) aufzurufen, wenn CMake verwendet wird . Es wird dringend empfohlen, dies folgendermaßen zu tun:

  1. Phase konfigurieren:

    cmake -Hfoo -B_builds/foo/debug -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX=/usr
    
  2. Phasen erstellen und installieren

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

Wenn Sie diesem Ansatz folgen, kann der Generator einfach umgeschaltet werden (z. B. -GNinjafür Ninja ), ohne sich an generatorspezifische Befehle erinnern zu müssen.

Florian Wolters
quelle
1
Die Antwort hätte besser sein können, wenn alle verwendeten Argumente erklärt worden wären und warum sie verwendet werden. Worum geht es insbesondere im --configArgument?
Dmitry Kabanov
2

Ab CMake 3.15 wäre der richtige Weg, dies zu erreichen, folgende:

cmake --install <dir> --prefix "/usr"

Offizielle Dokumentation

ExaltedBagel
quelle