使用CMake编译并添加二进制文件中的目标文件

时间:2013-02-08 15:57:03

标签: c++ cmake ld

我正在用C ++编写Excel文件构建器。

我有我需要的所有工作,但我仍然依赖外部空的.xlsx文件,我解压缩,迭代,并根据需要添加数据以创建最终文件。

我希望通过将.xlsx文件转换为可执行文件的.rodata部分中的二进制blob来删除此依赖项,方法是将其首先转换为如下所示的目标文件:

$ 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中,但{{1只是说:

ld

我将以下自定义命令添加到我的CMakeLists.txt:

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

并将文件/ template.o添加到add_executable调用。

不幸的是,CMake说:

  

ld:无法打开输出文件files / template.o:没有这样的文件或目录

据我所知,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) 中的OUTPUT命令允许我们告诉CMake COMMAND命令正在创建什么文件。所以我现在有点困惑。

我更新了CMakeLists.txt文件并添加了一个目标,以确保模板文件已构建:

add_custom_command

依赖于确保它在add_custom_target(run ALL DEPENDS template.o) 目标之前构建:

excelbuilder

我还将自定义命令更新为:

add_dependencies(excelbuilder run)

当我运行它时,输出如下(使VERBOSE = 1)

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)

但文件template.o已正确生成并位于文件夹中。似乎$ 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 期待系统库。

2 个答案:

答案 0 :(得分:24)

最后,我就是这样做的。

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
            )

答案 1 :(得分:0)

要将目标文件链接到exectuable,请将其添加到add_executable()中的源文件列表中,而不是尝试将其添加到target_link_libraries()

首先要生成目标文件,请参阅add_custom_command()。在这种情况下,您需要使用其指定OUTPUT参数的表单。