2013-02-08 14 views
17

Sto scrivendo un generatore di file Excel in C++.compila e aggiungi il file oggetto da binary con cmake

Ho tutto ciò di cui ho bisogno per lavorare, ma continuo a fare affidamento su un file xlsx vuoto esterno che decomprime, eseguo l'iterazione e aggiungo anche i dati necessari per creare il file finale.

Quello che voglio fare è quello di rimuovere questa dipendenza ruotando il file xlsx in un blob binario nella sezione .rodata del mio eseguibile, ruotandolo prima in un file oggetto in questo modo:

$ ld -r -b binary -o template.o template.xlsx 
$ objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o 

Ho ricevuto queste informazioni da qui: http://www.burtonini.com/blog/computers/ld-blobs-2007-07-13-15-50

Il secondo passo è collegarlo al binario, cosa che posso fare con ld.

La mia domanda è, come automatizzo questi due passaggi con cmake? Non ho idea di atm come eseguire comandi specifici come quello sopra ld per il primo passo, e ho provato ad aggiungere file/template.o ai miei target_link_libraries per il secondo, ma dice solo LD

/usr/bin/ld: cannot find -lfiles/template.o 

EDIT:

ho aggiunto il seguente comando personalizzato al mio CMakeLists.txt:

add_custom_command(OUTPUT files/template.o 
     COMMAND ld -r -b binary -o files/template.o files/template.xlsx 
     COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents files/template.o files/template.o) 

e ha aggiunto i file/template.o alla chiamata add_executable.

Purtroppo, cmake dice:

ld: cannot open output file files/template.o: No such file or directory 

E 'la mia comprensione che il comando di uscita nel add_custom_command ci permette di dire ciò che CMake file sia creato dai comandi COMANDO. Quindi sono un po 'confuso ora.

EDIT 2:

ho aggiornato il CMakeLists.txt, e ha aggiunto un obiettivo, per assicurarsi che il file di modello ma ho costruito:

add_custom_target(run ALL 
    DEPENDS template.o) 

e una dipendenza per assicurarsi che venga costruito prima l'obiettivo excelbuilder:

add_dependencies(excelbuilder run) 

ho anche aggiornato il comando personalizzato per assomigliare a questo:

add_custom_command(OUTPUT template.o 
     COMMAND ld -r -b binary -o template.o ${CMAKE_CURRENT_SOURCE_DIR}/files/template.xlsx 
     COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o) 

Quando si esegue questa operazione, l'uscita è la seguente (fare VERBOSE = 1)

$ make VERBOSE=1 
/usr/bin/cmake -H/home/ravloony/projects/excelparser -B/home/ravloony/projects/excelparser/build --check-build-system CMakeFiles/Makefile.cmake 0 
/usr/bin/cmake -E cmake_progress_start /home/ravloony/projects/excelparser/build/CMakeFiles /home/ravloony/projects/excelparser/build/CMakeFiles/progress.marks 
make -f CMakeFiles/Makefile2 all 
make[1]: Entering directory `/home/ravloony/projects/excelparser/build' 
make -f src/lib/minizip/CMakeFiles/minizip_1-1.dir/build.make src/lib/minizip/CMakeFiles/minizip_1-1.dir/depend 
make[2]: Entering directory `/home/ravloony/projects/excelparser/build' 
cd /home/ravloony/projects/excelparser/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/ravloony/projects/excelparser /home/ravloony/projects/excelparser/src/lib/minizip /home/ravloony/projects/excelparser/build /home/ravloony/projects/excelparser/build/src/lib/minizip /home/ravloony/projects/excelparser/build/src/lib/minizip/CMakeFiles/minizip_1-1.dir/DependInfo.cmake --color= 
make[2]: Leaving directory `/home/ravloony/projects/excelparser/build' 
make -f src/lib/minizip/CMakeFiles/minizip_1-1.dir/build.make src/lib/minizip/CMakeFiles/minizip_1-1.dir/build 
make[2]: Entering directory `/home/ravloony/projects/excelparser/build' 
make[2]: Nothing to be done for `src/lib/minizip/CMakeFiles/minizip_1-1.dir/build'. 
make[2]: Leaving directory `/home/ravloony/projects/excelparser/build' 
/usr/bin/cmake -E cmake_progress_report /home/ravloony/projects/excelparser/build/CMakeFiles 17 18 19 20 21 
[ 22%] Built target minizip_1-1 
make -f CMakeFiles/run.dir/build.make CMakeFiles/run.dir/depend 
make[2]: Entering directory `/home/ravloony/projects/excelparser/build' 
cd /home/ravloony/projects/excelparser/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/ravloony/projects/excelparser /home/ravloony/projects/excelparser /home/ravloony/projects/excelparser/build /home/ravloony/projects/excelparser/build /home/ravloony/projects/excelparser/build/CMakeFiles/run.dir/DependInfo.cmake --color= 
Dependee "/home/ravloony/projects/excelparser/build/CMakeFiles/run.dir/DependInfo.cmake" is newer than depender "/home/ravloony/projects/excelparser/build/CMakeFiles/run.dir/depend.internal". 
Dependee "/home/ravloony/projects/excelparser/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/ravloony/projects/excelparser/build/CMakeFiles/run.dir/depend.internal". 
Scanning dependencies of target run 
make[2]: Leaving directory `/home/ravloony/projects/excelparser/build' 
make -f CMakeFiles/run.dir/build.make CMakeFiles/run.dir/build 
make[2]: Entering directory `/home/ravloony/projects/excelparser/build' 
/usr/bin/cmake -E cmake_progress_report /home/ravloony/projects/excelparser/build/CMakeFiles 22 
[ 27%] Generating template.o 
ld -r -b binary -o template.o /home/ravloony/projects/excelparser/files/template.xlsx 
objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o 
make[2]: Leaving directory `/home/ravloony/projects/excelparser/build' 
/usr/bin/cmake -E cmake_progress_report /home/ravloony/projects/excelparser/build/CMakeFiles 22 
[ 27%] Built target run 
make -f CMakeFiles/excelbuilder.dir/build.make CMakeFiles/excelbuilder.dir/depend 
make[2]: Entering directory `/home/ravloony/projects/excelparser/build' 
cd /home/ravloony/projects/excelparser/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/ravloony/projects/excelparser /home/ravloony/projects/excelparser /home/ravloony/projects/excelparser/build /home/ravloony/projects/excelparser/build /home/ravloony/projects/excelparser/build/CMakeFiles/excelbuilder.dir/DependInfo.cmake --color= 
make[2]: Leaving directory `/home/ravloony/projects/excelparser/build' 
make -f CMakeFiles/excelbuilder.dir/build.make CMakeFiles/excelbuilder.dir/build 
make[2]: Entering directory `/home/ravloony/projects/excelparser/build' 
Linking CXX executable excelbuilder 
/usr/bin/cmake -E cmake_link_script CMakeFiles/excelbuilder.dir/link.txt --verbose=1 
/usr/bin/c++ -std=c++0x -g -ftest-coverage -fprofile-arcs -fpermissive CMakeFiles/excelbuilder.dir/src/common/exception.cpp.o CMakeFiles/excelbuilder.dir/src/excelbuilder/retriever.cpp.o CMakeFiles/excelbuilder.dir/src/excelbuilder/xlsx.cpp.o CMakeFiles/excelbuilder.dir/src/common/config.cpp.o CMakeFiles/excelbuilder.dir/src/excelbuilder/main.cpp.o -o excelbuilder -rdynamic src/lib/minizip/libminizip_1-1.so -ltinyxml2 -lmysqlcppconn -lboost_regex-mt -ltemplate.o -lz -Wl,-rpath,/home/ravloony/projects/excelparser/build/src/lib/minizip 
/usr/bin/ld: cannot find -ltemplate.o 
collect2: error: ld returned 1 exit status 
make[2]: *** [excelbuilder] Error 1 
make[2]: Leaving directory `/home/ravloony/projects/excelparser/build' 
make[1]: *** [CMakeFiles/excelbuilder.dir/all] Error 2 
make[1]: Leaving directory `/home/ravloony/projects/excelparser/build' 
make: *** [all] Error 2 

ma template.o sia stata correttamente generato ed è nella cartella. Sembra che ld si aspetti una libreria di sistema.

+0

Che cosa hai provato? Controlla la documentazione, in particolare add_custom_command e add_custom_target da qui http://www.cmake.org/cmake/help/v2.8.10/cmake.html#section_Commands –

+0

Sì, l'ho provato, ma mi manca qualcosa perché non è in esecuzione. Lo aggiungerò alla domanda. –

+0

Non riesco ancora a ottenere quello che fai. Hai il file template.cpp che dovrebbe essere compilato per primo, quindi combini questo file oggetto con .xlsx? Ho ragione? Errore abbastanza descrittivo. O template.cpp non è compilato prima di invocare ld o è sufficiente fornire $ {CMAKE_BINARY_DIR} /files/template.o al comando ld. –

risposta

20

Alla fine, questo è il modo in cui l'ho fatto.

add_custom_command(OUTPUT template.o 
     COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR}/files && ld -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/template.o template.xlsx 
     COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/template.o ${CMAKE_CURRENT_BINARY_DIR}/template.o) 

I comandi cd sono lì perché ld imposta i nomi delle variabili dichiarate automaticamente a qualcosa a seconda del percorso completo passato al file di input. Quindi se il file di input era /home/user/project/files/template.xlsx, la variabile sarebbe qualcosa come _binary_home_user_project_files_template_xlsx_start. Non fantastico per la compilazione portatile.

add_library(template 
     STATIC 
     template.o) 

indica al linker di compilare il file oggetto nel file binario. Questo aggiunge anche un obiettivo chiamato template.

Poi

SET_SOURCE_FILES_PROPERTIES(
    template.o 
    PROPERTIES 
    EXTERNAL_OBJECT true 
    GENERATED true 
) 

per dire CMake di non compilare il file, che viene generato in fase di compilazione.

SET_TARGET_PROPERTIES(
    template 
    PROPERTIES 
    LINKER_LANGUAGE C 
) 

Oppure si ottiene un messaggio di errore, perché CMake non riesco a capire dalla ".o" -suffix che si tratta di un C-linker abbiamo bisogno.

e quindi nel mio passaggio target_link_libraries, ho semplicemente aggiunto template come destinazione.

target_link_libraries (excelbuilder 
      ${MINIZIP_LIB_NAME} 
      ${TINYXML_LIBRARIES} 
      ${MYSQLCONNECTORCPP_LIBRARY} 
      ${Boost_LIBRARIES} 
      template 
      ) 
+1

Considera di utilizzare kwarg "WORKING_DIRECTORY' su" add_custom_command' invece di "COMANDO cd ...". – ulidtko

0

Per collegare il file oggetto nell'exectuable, aggiungerlo all'elenco dei file di origine in add_executable() invece di provare ad aggiungerlo a target_link_libraries().

Per generare il file oggetto in primo luogo, vedere add_custom_command(). In questo caso, dovrai utilizzare il suo modulo che specifica un parametro OUTPUT.

+2

Anche questo non funziona. Il file oggetto non è collegato, quindi quando ld fa il collegamento di altre librerie, le variabili dichiarate nel file .o non vengono referenziate e falliscono. –