web-dev-qa-db-ja.com

CMakeを使用してバイナリからオブジェクトファイルをコンパイルして追加します

私はC++でExcelファイルビルダーを書いています。

必要なものはすべて揃っていますが、それでも外部の空の.xlsxファイルに依存しています。このファイルを解凍し、繰り返し処理し、必要に応じてデータを追加して、最終的なファイルを作成します。

実行可能ファイルの.rodataセクションで.xlsxファイルをバイナリ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-5 =

2番目のステップは、それをバイナリにリンクすることです。これは、ldで実行できます。

CMakeでこれらの2つのステップを自動化するにはどうすればよいですか?

現時点では、最初のステップで上記のldのような特定のコマンドを実行する方法がわかりません。また、2番目のステップで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)

そして、files /template.oをadd_executable呼び出しに追加しました。

残念ながら、CMakeはこれを言います:

ld:出力ファイルfiles/template.oを開くことができません:そのようなファイルまたはディレクトリはありません

add_custom_commandのOUTPUTコマンドを使用すると、COMMANDコマンドによって作成されているファイルをCMakeに通知できると理解しています。だから私は今少し混乱しています。

テンプレートファイルがビルドされたことを確認するために、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)

これを実行すると、出力は次のようになります(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はシステムライブラリを期待しているようです。

20
Tom Macdonald

結局、これが私がやった方法です。

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」サフィックスから必要なCリンカーであることがわからないため、エラーメッセージが表示されます。

そして、target_link_librariesステップで、ターゲットとしてtemplateを追加しただけです。

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

オブジェクトファイルを実行可能ファイルにリンクするには、オブジェクトファイルをadd_executable()に追加するのではなく、target_link_libraries()のソースファイルのリストに追加します。

そもそもオブジェクトファイルの生成については、 add_custom_command() を参照してください。この場合、OUTPUTパラメーターを指定するフォームを使用する必要があります。