Installiere nur ein Ziel (und seine Abhängigkeiten) aus einem komplexen Projekt mit cmake (offen für bessere Lösungen)

8

Nehmen wir an, ich habe ein Projekt aus mehreren Teilprojekten A, B, C, D ... Alle Unterprojekte hängen von A ab, was sich ziemlich häufig ändert. Außerdem könnte es noch weitere Abhängigkeiten geben: In diesem Beispiel hängt D von B ab.

Jetzt: Viele Leute arbeiten an diesen Projekten. Die Hauptdatei CMakeLists.txt sollte alle Verzeichnisse enthalten, so dass der Build alles erstellt. Aber die Leute möchten auch nur in der Lage sein, an einem dieser Projekte zu arbeiten und müssen nicht jedes Mal alles neu bauen / installieren.

Wenn ich an D arbeite, kann ich einfach "nur" D durch Aufruf von

erstellen %Vor%

oder

%Vor%

Dies wird auch A und B bauen, wenn sich etwas für sie geändert hat. Perfekt.

Aber wie kann ich die Installation nur für D aufrufen, ohne alle Builds auszulösen? Ich möchte das, wenn ich rufe:

%Vor%

es hat nur D (und Abhängigkeiten) gebaut und dann nur D und seine Abhängigkeiten (A und B) installiert. Stattdessen baut es das Ziel all und installiert alles.

Ich möchte, dass das Ziel alle weiterhin alles baut. Daher wäre EXCLUDE_FROM_ALL keine Option. Aber in diese Richtung konnte ich keine Lösung finden.

Ich denke also an die folgende Strategie:

  • Abgesehen von Teilprojekt A sind alle anderen Ziele auf EXCLUDE_FROM_ALL und OPTIONAL bei der Installation festgelegt.
  • Ich füge ein zusätzliches Unterprojekt hinzu, das einfach von allen anderen Unterprojekten abhängt (vielleicht lasse ich jedes Ziel seinen Namen veröffentlichen, indem ich eine Variable bei PARENT_SCOPE verwende), und die Leute müssen das aufrufen, wenn sie alles erstellen und installieren wollen .

Wird es funktionieren? Gibt es eine bessere Lösung?

Wir möchten vermeiden, dass jeder die Hauptdatei CMakeLists.txt bearbeiten muss, um Projekte auszuschließen, an denen er nicht interessiert ist. Die Lösung sollte für verschiedene Betriebssysteme portierbar sein.

Bearbeiten:

Ich habe die von mir vorgeschlagene Strategie ausprobiert, aber es hat nicht funktioniert: In meinem Fall wird das Setzen einer Installationsanweisung für ein Ziel (selbst wenn es als OPTIONAL angegeben ist) unwirksam machen, EXCLUDE_FROM_ALL. Lesen Sie besser in der Dokumentation Ich fand heraus:

%Vor%

Ich bekomme auch diese Warnung:

%Vor%

Bearbeiten 2:

Ich habe versucht, EXCLUDE_FROM_ALL als eine Option von add_subdirectory (anstelle von add_library / add_executable) zu setzen, aber dann scheinen alle Installationsanweisungen in diesem Unterverzeichnis ignoriert zu werden: nur install-Anweisungen in nicht ausgeschlossenen Unterverzeichnissen werden installiert .

Bearbeiten 3:

Auch wenn ich CMAKE_SKIP_INSTALL_ALL_DEPENDENCY aktiviere:

%Vor%

in der Hauptdatei CMakeLists.txt, und ich lasse alle EXCLUDE_FROM_ALL weg, setze die Installation von so vielen Zielen, wie ich möchte, optional (in meinem Fall alle außer A), und wenn das Erstellen bestimmter Ziele der Installation vorangeht, noch der Befehl:

%Vor%

schlägt aus irgendeinem Grund fehl und besagt, dass C (dessen Installation auf OPTIONAL gesetzt wurde) nicht existiert (es wurde nicht erstellt, weil D nur von A und B abhing) ...

%Vor%

Bearbeiten Sie 4:

Es sieht aus wie ein CMake-Bug für mich. (Ich verwende 2.8.11 unter Windows, auch getestet 2.8.10) Dieser INSTALL-Befehl

%Vor%

wird in cmake_install.cmake wie folgt konvertiert:

%Vor%      

FILE (INSTALL DESTINATION "$ {CMAKE_INSTALL_PREFIX} /." TYP SHARED_LIBRARY-DATEIEN * path_to_dll *)

     

IF (EXISTS "$ ENV {DESTDIR} $ {CMAKE_INSTALL_PREFIX} /./" UND NICHT IS_SYMLINK "$ ENV {DESTDIR} $ {CMAKE_INSTALL_PREFIX} /./ * dll_name *")

%Vor%

mit dem Befehl DATEI fehlt OPTIONAL! Wenn ich OPTIONAL manuell hinzufüge, funktioniert es! (Hinweis: Ich habe hier bearbeitet, um * dll_name * und * path_to_dll * Platzhalter zu setzen)

Bearbeiten Sie 5:

Ich bestätige, dass es ein Fehler von cmake oder zumindest eine falsche Dokumentation ist. Ich werde das melden. Die Situation löste sich entweder durch ein einfacheres

%Vor%

(aber das wird in meinem Fall auch .lib.a Dateien installieren, die ich nicht will)

oder Vorziehen der OPTIONAL-Flagge:

%Vor%

Was man von der CMake-Dokumentation versteht, ist, dass OPTIONAL dies sollte als letzte Option gesetzt werden.

    
Antonio 18.06.2013, 09:01
quelle

4 Antworten

10

Was funktioniert:

  • Entferne die Abhängigkeit von "install" target zu "all" target (einmal in der CMakeLists.txt Hauptdatei) ):

    set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)

  • Wählen Sie OPTIONALE Installation aller Ziele, die Sie nicht immer erstellen möchten:

    install(TARGETS <<targetname>> DESTINATION . OPTIONAL)

  • Erstellen Sie die Ziele, die Sie installieren möchten

    ninja -j7 <<list of targets>> oder allgemeiner:

    <<your builder>> <<your options>> <<list of targets>>

    Dadurch werden alle aufgelisteten Ziele und ihre Abhängigkeiten

    erstellt
  • Rufen Sie das Installationsprogramm an %Code%. Dadurch werden alle Bibliotheken installiert, die Sie erstellt haben, die Sie explizit erwähnt haben und diejenigen, auf die sie angewiesen sind. Dies löst das Problem, dass ein bestimmtes Ziel zusammen mit seinen Abhängigkeiten installiert wird!

  • Um die Befehle sowohl unter Unix als auch unter Windows zu verketten, können Sie

    verwenden

    ninja install

  • Beachten Sie, dass Sie, zumindest für Ninja, nicht einfach "Installieren" der Liste der Ziele voranstellen können, da das Ziel "Installieren" nicht mehr von einem Ziel abhängig ist und Ninja bei der Parallelisierung des Jobs installiert wird, während Sie stillstehen Erstellen Sie Ihre Ziele. Ein Ersatz für das alte ninja -j7 <<list of targets>> && ninja install ist

    ninja -j7 install .

    Das Ziel "all" ist immer noch verfügbar (und es ist immer noch das Standardziel).

  • Wenn Sie eine Liste von Zielen erstellen müssen, die Sie zusammen erstellen möchten, können Sie einen benutzerdefiniertes Ziel :

    ninja -j7 && ninja install

    Dies wird nicht alle im Ziel enthalten sein. Das Hinzufügen eines COMMANDs würde es auch ermöglichen, ein Installationsziel für beliebig viele Ziele zu erstellen, wie zum Beispiel add_custom_target(<<collective target name>> DEPENDS <<list of targets>>) , aber ich denke, jetzt sind wir über den Rahmen dieser Frage hinaus.

Weitere Überlegungen:

  • Wenn Sie RUNTIME DESTINATION, BIBLIOTHEK DESTINATION usw. verwenden, wird das OPTIONAL-Schlüsselwort höchstwahrscheinlich aufgrund eines CMake-Fehlers genau an die unten angegebene Position gesetzt:

    ninja -j7 install_D

    Das widerspricht dem, was in der Dokumentation geschrieben wurde, und ich werde es tun Fahren Sie fort, es den CMake-Entwicklern als Fehler zu melden.

  • Die Verwendung von install(TARGETS <<targetname>> OPTIONAL RUNTIME DESTINATION <<some dir>> LIBRARY DESTINATION <<some (other) dir>>) in Kombination mit EXCLUDE_FROM_ALL + INSTALL ist eine schlechte Idee

      

    Das Installieren eines Ziels mit EXCLUDE_FROM_ALL, das auf "true" gesetzt ist, hat ein nicht definiertes Verhalten.

    (und cmake versucht, Sie zu warnen, wenn der Code analysiert wird)

Antonio 19.06.2013 21:08
quelle
2

Wenn Sie add_subdirectory verwendet haben, um Ihre Unterprojekte zu Ihrer CMakeLists.txt hinzuzufügen, werden Sie sehen, dass Sie in Ihrem Build-Verzeichnis Unterverzeichnisse für alle Ihre Unterprojekte haben.

Wenn Sie nur die Ziele von D installieren möchten, tun Sie einfach:

%Vor%

Dies wird nur die D-Ziele installieren.

Natürlich musst du dein Projekt vorher in build-dir erstellt haben. Ich benutze es so mit Gnu-make. Ich weiß nicht, ob es mit Ninja funktioniert.

    
Patrick B. 18.06.2013 09:09
quelle
1

Als ich hier antwortete , Neuere Versionen von Ninja bieten die Option, nur Ziele in einem Unterverzeichnis zu erstellen.

Die gleiche Funktion gilt für die Installation. Wenn Ihr Ziel D aus Ihrer Frage in einem Unterverzeichnis D ist, können Sie diesen Befehl ausführen:

%Vor%

Weitere Informationen finden Sie in der CMake-Dokumentation zum Ninja Generator hier .

    
Unapiedra 16.07.2017 12:17
quelle
0

Wie von unapiedra erwähnt, enthält die von cmake erzeugte Ninja-Builddatei Regeln zum Erstellen / Testen / Installieren / Packen, was sich in einem bestimmten Verzeichnis befindet.

Das ist in Ordnung, aber Sie können nicht tun:

%Vor%

Das geht nur

%Vor%

Wenn Sie nicht wissen, wo der targetName ist, können Sie Folgendes verwenden:

%Vor%

um die Ausgaben zu sehen.

    
Erk 18.12.2017 10:47
quelle

Tags und Links