![](/img/trans.png)
[英]How can I pass the directory of boost library to CMakeLists.txt file for compilation?
[英]How can I use library in cmake-base project if sources and CMakeLists.txt file for this library I have to generate by external tool
我必須通過外部工具生成源代碼(我從 IDL 文件為 fastDDS 消息生成 c++ 個類),該工具還生成 CMakeLists.txt 文件,允許我將生成的文件編譯為 <msgs_lib>.a 文件。
在我的一個執行目標的大型超級項目中,我不會檢查生成的文件及其構建結果是否存在。 如果 <msgs_lib>.a 不存在,我將調用生成並構建它。
我知道 CMake 命令add_custom_command
和add_custom_target
。 但是我不能以正確的方式使用它們,在某些情況下,即使所有文件都存在並且它們是按正確的順序構建的,在某些情況下也不會生成任何內容(並且在清理后也不會生成任何內容),在某些情況下 exec-target 會不明白它應該檢查並調用生成。
例如我將在上面寫一個案例來開始討論。 我已經簡化了很多:
github 上的項目: https://github.com/gladijos/test_project
一個 zip 文件中的項目: mediaDrive-link
或者就在這里:
項目目錄樹:
.
├── CMakeLists.txt
├── deps
│ ├── gen_deps
│ └── gen_source
│ └── tb_msgs
│ ├── CMakeLists.txt
│ ├── tb_msg.cpp
│ └── tb_msg.h
├── scripts
│ └── build_msgs.sh
└── test_app
├── CMakeLists.txt
└── main.cpp
根-CMakeLists.txt:
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
project(test_project LANGUAGES CXX VERSION 0.0.3)
set(TB_MSGS ${CMAKE_HOME_DIRECTORY}/deps/gen_deps/tb_msgs/build/libtb_msgs_lib.a)
add_custom_command(
OUTPUT ${TB_MSGS}
WORKING_DIR ${CMAKE_HOME_DIRECTORY}
COMMAND ${CMAKE_HOME_DIRECTORY}/scripts/build_msgs.sh ${CMAKE_HOME_DIRECTORY}
)
add_custom_target(build_dds_msgs
# ALL
DEPENDS ${TB_MSGS}
)
# apps
add_subdirectory(test_app)
add_dependencies(test_app build_dds_msgs)
tb_msgs CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.1)
project("tb_lib")
set(CMAKE_CXX_STANDARD 11)
add_library(tb_msgs_lib
tb_msg.cpp
)
tb_msg.cpp:
#include "tb_msg.h"
MyClass::MyClass(){};
tb_msg.h:
#pragma once
class MyClass
{
public:
MyClass();
};
build_msgs.sh:
cp -rf $1/deps/gen_source/* $1/deps/gen_deps/;
cd $1/deps/gen_deps/tb_msgs;
mkdir -p $1/deps/gen_deps/tb_msgs/build;
cd $1/deps/gen_deps/tb_msgs/build;
cmake .. ;
make;
test_app CMakeListst.txt:
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
project(test_app LANGUAGES CXX VERSION 0.0.1)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME}
${CMAKE_HOME_DIRECTORY}/deps/gen_deps/tb_msgs/build/libtb_msgs_lib.a
)
test_app main.cpp:
#include "../deps/gen_deps/tb_msgs/tb_msg.h"
int main()
{
MyClass myClass;
return 0;
}
在這種情況下,我每次構建都會調用 scripts/build_msgs.sh,即使libtb_msgs_lib.a
存在,並且是在test_app
之前構建的。
就比較單一。 在add_custom_command
OUTPUT
部分我放了.a
,但在最好的情況下這里應該是 dir gen_source/* 中的所有文件,但我認為這是另一個問題,我可以在解決主要問題后解決它。
為了解決您的問題,我建議不要依賴外部工具的 cmake 腳本,而是管理 IDL 文件的生成並構建庫。 我假設您的項目有一個包含 IDL 文件的文件夾,我們稱它為idl
。 在此文件夾中還放置一個CMakeLists.txt
文件以生成和構建庫。
項目結構變成如下:
.
├── CMakeLists.txt
├── idl
│ ├── CMakeLists.txt
│ ├── Bar.idl
│ ├── Foo.idl
│ └── MyClass.idl
├── scripts
│ └── fastmsg.sh
└── test_app
├── CMakeLists.txt
└── main.cpp
在此示例中,文件idl/Bar.idl
、 idl/Foo.idl
和idl/MyClass.idl
可以為空,只有它們的存在很重要。
cmake_minimum_required(VERSION 3.0)
project(test_project LANGUAGES CXX VERSION 0.0.3)
set(GENERATOR ${CMAKE_SOURCE_DIR}/scripts/fastmsg.sh)
# apps
add_subdirectory(idl)
add_subdirectory(test_app)
對於IDL_LIST
中的每個文件,都會調用一個外部工具(根 CMakeLists.txt 中的GENERATOR
)來生成cpp
和h
文件。 生成的cpp
文件列表用於構建build_dds_msgs
庫。
cmake_minimum_required(VERSION 3.0)
set(IDL_LIST MyClass.idl Foo.idl Bar.idl)
set(IDL_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(CPP_DIR ${CMAKE_CURRENT_BINARY_DIR})
foreach(IDL_FILE ${IDL_LIST})
string(REPLACE ".idl" ".cpp" CPP_FILE ${IDL_FILE})
string(REPLACE ".idl" ".h" HDR_FILE ${IDL_FILE})
list(APPEND CPP_LIST ${CPP_DIR}/${CPP_FILE})
add_custom_command(
OUTPUT ${CPP_DIR}/${CPP_FILE} ${CPP_DIR}/${HDR_FILE}
COMMAND ${GENERATOR} ${IDL_DIR}/${IDL_FILE}
WORKING_DIRECTORY ${CPP_DIR}
DEPENDS ${IDL_DIR}/${IDL_FILE}
VERBATIM
)
endforeach()
add_library(build_dds_msgs ${CPP_LIST})
target_include_directories(build_dds_msgs PUBLIC ${CPP_DIR})
# Add dependencies on an external instrument, if any.
# target_include_directories(build_dds_msgs PRIVATE include_from_gen)
# target_link_libraries(build_dds_msgs PRIVATE libs_from_gen)
這里的變化很小,主要是風格上的。
cmake_minimum_required(VERSION 3.0)
project(test_app LANGUAGES CXX VERSION 0.0.1)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} build_dds_msgs)
#include "MyClass.h"
int main()
{
MyClass myClass;
return 0;
}
這是一個真實發電機的模擬器。 它采用FileName.idl
並創建FileName.h
和FileName.cpp
文件, FileName
名為空 class。
#!/bin/bash
if [ -z "$1" ]
then
echo "Usage: `basename $0` filename"
exit 1
fi
FILE=$(basename -- "$1")
CLASS=${FILE%.*}
cat > $CLASS.h <<EndHpp
#pragma once
class $CLASS
{
public:
$CLASS();
};
EndHpp
cat > $CLASS.cpp <<EndCpp
#include "$CLASS.h"
$CLASS::$CLASS(){};
EndCpp
exit 0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.