使用install
命令在構建時移動文件通常是不好的方法。該命令旨在用於設置在用戶執行make install
或同等操作時將安裝的文件和目標。由於你沒有運行make install
,我預計這就是爲什麼install(FILES ...)
命令似乎不起作用。
你有一些稍微不同的方法來完成這項工作。
我推薦不是如果您不需要移動標題。假設你的庫稱爲MyLib
,那麼你可以通過target_include_directories
使這些頭可作爲MyLib
目標的一部分:
target_include_directories(MyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
這意味着,如果有一個相關的目標,如MyExe
:
target_link_libraries(MyExe MyLib)
則自動有權訪問MyLib
的源代碼目錄。
如果庫的目錄結構不適合將API頭與其餘源和頭分開,那麼這可能不太理想。假設MyLib
由以下文件組成:my_lib.cpp,my_lib_api.hh(API標頭 - 用於其他項目)和my_lib_detail.hh(不包含在其他項目中)。一個理想的結構將保持API標題與其餘的不同,例如,
/my_lib
- CMakeLists.txt
- src/
- my_lib.cpp
- my_lib_detail.hh
- include/
- my_lib/
- my_lib_api.hh
有了這個結構,你可以只指定
target_include_directories(MyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src")
和MyLib
來源將能夠遏制#include "my_lib_detail.hh"
和#include "my_lib/my_lib_api.hh"
,但依賴的目標的來源只能包含#include "my_lib/my_lib_api.hh"
。
所以,如果MyLib
剛剛平面結構或不內部接頭從API孩子們分開,你可能希望將API頭的位置複製了在構建樹,並添加到該路徑致電target_include_directories
。在這種情況下,如果MyLib
本身不需要訪問複製的文件(只是源樹中的原始文件),則可以在調用target_include_directories
時使用INTERFACE
而不是PUBLIC
。但是,這個問題的關鍵(並回答你的實際問題我想)是作爲配置過程(當CMake運行時)或構建過程(當運行時)的一部分複製這些文件 - 而不是作爲部分的安裝過程。
所以,讓我們假設MyLib
不具有上文所示的有用的目錄結構,而是是平坦的(即和的CMakeLists.txt三個源文件都在相同的目錄)。我們可以使用一個生成後命令API頭複製出來,以構建樹:
project(my_lib)
cmake_minimum_required(VERSION 2.8.12.2) # for 'target_include_directories'
add_library(MyLib SHARED my_lib.cpp my_lib_api.hh my_lib_detail.hh)
target_include_directories(MyLib INTERFACE "${CMAKE_BINARY_DIR}/include"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/my_lib")
add_custom_command(TARGET MyLib POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/my_lib_api.hh"
"${CMAKE_BINARY_DIR}/include/my_lib"
COMMENT "Copying MyLib public headers to ${CMAKE_BINARY_DIR}/include/my_lib"
VERBATIM)
那麼對於MyExe
的的CMakeLists.txt,你可以做:
project(my_exe)
cmake_minimum_required(VERSION 2.8.12.2)
add_executable(MyExe main.cpp)
target_link_libraries(MyExe MyLib)
# Copy MyLib.so to this build dir to allow MyExe to find it at runtime
add_custom_command(TARGET MyExe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:MyLib>"
"$<TARGET_FILE_DIR:MyExe>"
VERBATIM)
這不會像MSVC那樣工作 - 您需要處理Windows導出庫(有關更多詳細信息,請參見CMake wiki和GenerateExportHeader
的文檔),但它只是涉及諸如將以下內容添加到MyLib
的的CMakeLists.txt:
include(GenerateExportHeader)
generate_export_header(MyLib
BASE_NAME MyLib
EXPORT_MACRO_NAME MyLib_EXPORT
EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/include/my_lib/my_lib_export.hh"
STATIC_DEFINE MyLib_BUILT_AS_STATIC)
如果你確實需要這樣,你必須改變INTERFACE
到PUBLIC
在target_include_directories(MyLib ...)
,因爲MyLib
然後將自己需要訪問生成的文件"${CMAKE_BINARY_DIR}/include/my_lib/my_lib_export.hh"
。
嗨弗雷澤,謝謝你。不幸的是,我不能試試這個,因爲我沒有cmake 2.8.12.2。但是你的解決方案似乎很有前途,我會在稍後嘗試。在此之前,我將使用文件(COPY)將頭文件複製到所需位置。再次感謝! – czappa
不用擔心 - '文件(COPY ...)'應該可以正常工作。 – Fraser