Скомпилируйте и добавьте объектный файл из двоичного файла с помощью CMake - программирование
Подтвердить что ты не робот

Скомпилируйте и добавьте объектный файл из двоичного файла с помощью CMake

Я пишу конструктор файлов Excel в C++.

У меня есть все, что мне нужно для работы, но я все еще полагаюсь на внешний пустой файл .xlsx, который я распаковываю, перебираю и добавляю данные по мере необходимости для создания окончательного файла.

Я хочу удалить эту зависимость, превратив файл .xlsx в двоичный двоичный объект в разделе .rodata моего исполняемого файла, превратив его сначала в объектный файл, например так:

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

Я получил эту информацию из блога http://www.burtonini.com/blog/computers/ld-blobs-2007-07-13-15-50.

Второй шаг - связать его в двоичный файл, что я могу сделать с ld.

Как мне автоматизировать эти два шага с помощью CMake?

В настоящий момент я понятия не имею, как запускать определенные команды, такие как ld выше для первого шага, и я попытался добавить files/template.o в мои target_link_libraries для второго, но ld просто говорит:

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

Я добавил в свой 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)

и добавил файлы /template.o к вызову add_executable.

К сожалению, CMake говорит это:

ld: не могу открыть файл вывода файла /template.o: такого файла или каталога нет

Насколько я понимаю, команда OUTPUT в add_custom_command позволяет нам сообщить CMake, какой файл создается командами COMMAND. Поэтому я немного растерялся.

Я обновил файл CMakeLists.txt и добавил цель, чтобы убедиться, что файл шаблона создан:

add_custom_target(run ALL
    DEPENDS template.o)

И зависимость, чтобы удостовериться, что он будет построен до цели excelbuilder:

add_dependencies(excelbuilder run)

Я также обновил пользовательскую команду, чтобы она выглядела следующим образом:

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)

Когда я запускаю это, вывод будет следующим (make 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

Но файл template.o был сгенерирован правильно и находится в папке. Похоже, что ld ожидает системную библиотеку.

4b9b3361

Ответ 1

В конце концов, так я и сделал.

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)

Команды cd присутствуют, потому что ld устанавливает имена автоматически объявленных переменных в зависимости от полного пути, передаваемого во входной файл. Поэтому, если бы входным файлом был /home/user/project/files/template.xlsx, переменная была бы что-то вроде _binary_home_user_project_files_template_xlsx_start. Не круто для портативной компиляции.

add_library(template
        STATIC
        template.o)

говорит компоновщику скомпилировать объектный файл в двоичный файл. Это также добавляет цель под названием template.

Тогда

SET_SOURCE_FILES_PROPERTIES(
  template.o
  PROPERTIES
  EXTERNAL_OBJECT true
  GENERATED true
  )

сказать CMake не компилировать файл, который генерируется во время сборки.

SET_TARGET_PROPERTIES(
  template
  PROPERTIES
  LINKER_LANGUAGE C 
  )

Или же мы получаем сообщение об ошибке, потому что CMake не может понять из ".o" -suffix, что нам нужен компоновщик C.

А затем на своем шаге target_link_libraries я просто добавил template в качестве цели.

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

Ответ 2

Чтобы связать файл объекта с exectuable, добавьте его в список исходных файлов в add_executable() вместо того, чтобы добавить его в target_link_libraries().

Для создания объектного файла в первую очередь см. add_custom_command(). В этом случае вам понадобится использовать его форму, которая указывает параметр OUTPUT.