2013-03-07 8 views
8

Ich bin neu in CMake und ich habe ein Problem, dass ich nicht herausfinden, eine Lösung für. Ich verwende CMake, um ein Projekt mit einer Reihe von optionalen Unterverzeichnissen zu kompilieren, und es erstellt gemeinsam genutzte Bibliotheksdateien wie erwartet. Dieser Teil scheint gut zu funktionieren. Jedes dieser Unterverzeichnissen enthält eine SQL-Datei. Ich muss alle ausgewählten SQL-Dateien zu einer SQL-Header-Datei concat und installieren Sie das Ergebnis. So eine Datei wie:Mit CMake, wie kann ich concat Dateien und installieren sie

sql_header.sql 
sub_dir_A.sql 
sub_dir_C.sql 
sub_dir_D.sql 

Wenn ich das tat direkt in einer Make-Datei könnte ich so etwas wie das folgende tun nur intelligenter zu behandeln nur die ausgewählten Unter dirs:

cat sql_header.sql > "${INSTALL_PATH}/somefile.sql" 
cat sub_dir_A.sql >> "${INSTALL_PATH}/somefile.sql" 
cat sub_dir_C.sql >> "${INSTALL_PATH}/somefile.sql" 
cat sub_dir_D.sql >> "${INSTALL_PATH}/somefile.sql" 

Ich habe sort von heraus Stücke dieser, wie ich verwenden kann:

LIST(APPEND PACKAGE_SQL_FILES "some_file.sql") 

, die ich nehme an, ich in jedem der Unter dirs CMakeLists.txt Dateien platzieren können die Dateinamen zu sammeln. Und ich kann einen Makro wie erstellen:

CAT(IN "${PACKAGE_SQL_FILES}" OUT "${INSTALL_PATH}/somefile.sql") 

Aber ich bin verloren, wenn der zwischen CMake zunächst läuft und wenn es aus dem make install läuft. Vielleicht gibt es einen besseren Weg, dies zu tun. Ich brauche das für Windows und Linux.

Ich wäre mit einigen Hinweisen glücklich, um mich in die richtige Richtung zu zeigen.

Antwort

10

Sie können die verkettete Datei hauptsächlich mit den CMake-Befehlen file und function erstellen.

Erstellen Sie zunächst eine cat Funktion:

function(cat IN_FILE OUT_FILE) 
    file(READ ${IN_FILE} CONTENTS) 
    file(APPEND ${OUT_FILE} "${CONTENTS}") 
endfunction() 

Angenommen, Sie die Liste der Eingabedateien in der Variable PACKAGE_SQL_FILES haben, können Sie die Funktion wie folgt verwendet werden:

# Prepare a temporary file to "cat" to: 
file(WRITE somefile.sql.in "") 

# Call the "cat" function for each input file 
foreach(PACKAGE_SQL_FILE ${PACKAGE_SQL_FILES}) 
    cat(${PACKAGE_SQL_FILE} somefile.sql.in) 
endforeach() 

# Copy the temporary file to the final location 
configure_file(somefile.sql.in somefile.sql COPYONLY) 

Der Grund für das Schreiben zu einem temporären ist, so wird die reale Zieldatei nur aktualisiert, wenn sich ihr Inhalt geändert hat. Siehe this answer für warum das eine gute Sache ist.

Wenn Sie die Unterverzeichnisse über den Befehl add_subdirectory einbeziehen, sollten Sie beachten, dass die Unterverzeichnisse alle ihren eigenen Geltungsbereich haben, soweit CMake-Variablen betroffen sind. In den Unterverzeichnissen wirkt sich die Verwendung von list nur auf Variablen im Bereich dieses Unterverzeichnisses aus. Wenn Sie eine Liste im übergeordneten Bereich erstellen möchten, müssen Sie set(... PARENT_SCOPE), z.

All dies bisher hat einfach die verkettete Datei im Stammverzeichnis Ihres Build-Baums erstellt. Um es zu installieren, möchten Sie wahrscheinlich den install(FILES ...) Befehl verwenden:

install(FILES ${CMAKE_BINARY_DIR}/somefile.sql 
     DESTINATION ${INSTALL_PATH}) 

Also, wenn CMake läuft (entweder weil Sie es manuell aufrufen, oder weil es Änderungen erkennt, wenn Sie „make“), wird es die verketteten aktualisieren Datei in der Build-Struktur. Nur wenn Sie "make install" ausführen, wird die Datei schließlich vom Build-Stammverzeichnis zum Installationsverzeichnis kopiert.

+0

Schöne Verwendung von configure_file ... ;-) – DLRdave

+0

Danke, das war sehr hilfreich.Es ist schwierig, die Ergebnisse aufblühen zu lassen, wenn Sie mehrere Verzeichnisse in mehreren Tiefen haben, aber ich habe es mit Ihren sehr hilfreichen Vorschlägen zum Laufen gebracht. Vielen Dank! –

+0

Ich habe es versucht, und es hat funktioniert ... es sei denn, die Datei hat Semikolons, an welcher Stelle es fehlschlägt, weil die Semikolons stillgelegt werden. Dies ist eine normale Folge von Semikola als Listentrennzeichen in cmake. Der einfachste Testfall, der das Problem zeigt, ist 'set (INHALT "a; b; c \ n") Datei (WRITE out.txt $ {CONTENTS}) 'Die Lösung besteht darin, Inhalte beim Schreiben anzugeben, z. '" $ {INHALT} "' –

Verwandte Themen