De compiler et d'ajouter un objet fichier binaire avec CMake
Je suis en train d'écrire un fichier Excel en C++ builder.
J'ai tout ce dont j'ai besoin de travail, mais je continue de s'appuyer sur un vide externe .xlsx fichier que je le décompresser, parcourir, et d'ajouter des données trop que nécessaire pour créer le fichier final.
Je veux supprimer cette dépendance en tournant la .fichier xlsx en un blob binaire dans le .rodata section de mon exécutable, en le tournant d'abord dans un fichier de l'objet comme suit:
$ ld -r -b binary -o template.o template.xlsx
$ objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o
J'ai obtenu cette information à partir du blog http://www.burtonini.com/blog/computers/ld-blobs-2007-07-13-15-50.
La deuxième étape consiste à lier, en binaire, ce que je peux faire avec ld
.
Comment puis-je automatiser ces deux étapes avec CMake?
Je n'ai aucune idée pour le moment comment exécuter des commandes spécifiques comme la ld
l'un au-dessus de la première étape, et j'ai essayé d'ajouter files/template.o
à mon target_link_libraries pour la deuxième, mais ld
dit seulement:
/usr/bin/ld: cannot find -lfiles/template.o
J'ai ajout de la commande personnalisée à mon 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)
et les fichiers ajoutés/modèle.o à la add_executable appel.
Malheureusement, CMake dit ceci:
ld: ne peut ouvrir le fichier de sortie des fichiers/modèle.o: Aucun fichier ou répertoire de
C'est ma compréhension que la SORTIE de la commande dans le add_custom_command
nous permet de dire CMake ce fichier est créé par la COMMANDE les commandes. Donc je suis un peu confus pour l'instant.
J'ai mis à jour le CMakeLists.txt fichier et l'ajout d'une cible, assurez-vous que le fichier de modèle s'est développé:
add_custom_target(run ALL
DEPENDS template.o)
Et une dépendance pour s'assurer qu'il se construit avant le excelbuilder
cible:
add_dependencies(excelbuilder run)
J'ai aussi mis à jour la commande personnalisée pour ressembler à ceci:
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)
Lorsque je l'exécute, le résultat est le suivant (faire 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
Mais le modèle de fichier.o a été correctement créé et qui est dans le dossier. Il semble que ld
s'attend à un système de bibliothèque.
- Qu'avez-vous essayé? Vérifier la documentation, en particulier add_custom_command et add_custom_target à partir d'ici, cmake.org/cmake/help/v2.8.10/cmake.html#section_Commands
- Yup j'ai essayé, mais je dois manquer quelque chose, car il n'est pas en cours d'exécution. Je vais l'ajouter à la question.
- Je ne suis toujours pas obtenir ce que vous faites. Vous avez template.cpp fichier qui doit être compilé d'abord, puis de combiner ce fichier objet avec .xlsx ? Suis-je la corriger? Erreur assez descriptif. Soit template.cpp n'est pas compilé avant d'appeler ld ou vous avez juste besoin de fournir ${CMAKE_BINARY_DIR}/fichiers/modèle.o ld commande.
- Il n'y a pas de template.cpp. Il est tout simplement un fichier xlsx, que je transforme en un fichier objet à l'aide de la ld de commande. Je ne veux pas de ld pour trouver le modèle.o, je le veux pour le générer.
- Pourriez-vous fournir des log complet pour la commande qui est en panne? "faire VERBOSE=1" devrait aider.
- Fait. En Plus, j'ai ajouté quelques autres trucs que j'avais réussi à se mettre au travail.
- Comme vous pouvez le voir à partir de journal il n'y a rien de mal avec la génération, de sorte add_custom_command fonctionne parfaitement. Le problème qu'on dirait que vous avez utilisé de modèle.o comme target_link_library. Suis-je la corriger?
- pourriez-vous nous communiquer votre objectif final des commandes dans cmakelists.txt?
- Le lien est rompu (404).
Vous devez vous connecter pour publier un commentaire.
En fin de compte, c'est comment je l'ai fait.
La
cd
commandes sont là parce queld
définit les noms des automatiquement les variables déclarées à quelque chose en fonction du chemin d'accès complet transmis au fichier d'entrée. Donc, si le fichier d'entrée a été/home/user/project/files/template.xlsx
, la variable serait quelque chose comme_binary_home_user_project_files_template_xlsx_start
. Pas cool pour portable compilation.indique à l'éditeur de liens pour compiler le fichier de l'objet dans le binaire. Cela ajoute aussi une cible appelée
template
.Puis
dire CMake pas à compiler le fichier est généré au moment de la construction.
Sinon on obtient un message d'erreur, parce que CMake ne pouvez pas comprendre à partir de l' ".o"-suffixe que c'est un C l'éditeur de liens dont nous avons besoin.
Et puis dans mon
target_link_libraries
étape, j'ai simplement ajoutétemplate
comme une cible.WORKING_DIRECTORY
kwarg àadd_custom_command
au lieu deCOMMAND cd ...
.De lier le fichier objet dans l'exécutable, l'ajouter à la liste des fichiers source dans
add_executable()
au lieu d'essayer de l'ajouter àtarget_link_libraries()
.Pour générer le fichier de l'objet, en premier lieu, voir add_custom_command(). Dans ce cas, vous aurez envie d'utiliser sa forme qui spécifie un
OUTPUT
paramètre.