cmake之add_library 语法
1 2 3 add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
name:库的名字,无需加lib,会自动添加这个前缀
STATIC | SHARED | MODULE:静态库 | 动态库 | 在使用dyld的系统有效,否则被视为SHARED
EXCLUDE_FROM_ALL:这个库不会被默认构建,除非有其他的组件依赖或者手动构建
使用
1 2 3 SET(LIBHELLO_SRC hello.c) ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
注意
上面构建的libhello.so与libhello_static.a,本质区别一个是动态库,一个是静态库,合理的命名为libhello.so与libhell.a,但显然名字不同。原因在于,如果将第三行代码改成
1 ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
则会因为重名,导致静态库无法构建。
解决办法为,修改libhello_static.a的属性-OUTPUT_NAME
1 SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
这样就可以生成libhello.so与libhello.a了
cmake之target_include_directories 语法
1 2 3 target_include_directories(<target> [SYSTEM] [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
指定编译target时需要包含的目录或者目标。
target必须是由add_executable()或者add_library()命令创建的目标
INTERFACE|PUBLIC|PRIVATE关键字用于指定items1等参数的范围,PRIVATE和PUBLIC的items将产生target的INCLUDE_DIRECTORIES属性,PUBLIC和INTERFACE的items将产生target的INTERFACE_INCLUDE_DIRECTORIES属性,也就是添加了公共默认搜索路径。。
target_include_directories的参数也可以使用“生成表达式”$<…>这样的语法,如$和$被用于描述不同的使用要求。
1 2 3 4 target_include_directories(mylib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/mylib> $<INSTALL_INTERFACE:include/mylib> # <prefix>/include/mylib )
cmake之target_compile_definitions 语法
1 2 3 target_compile_definitions(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
给target添加编译选项,格式与target_include_directories类似。
PRIVATE 和 PUBLIC 项将产生 target>的 COMPILE_DEFINITIONS 属性。PUBLIC 和 INTERFACE 项将产生 target>的INTERFACE_COMPILE_DEFINITIONS 属性。其后的参数指定编译定义。重复调用相同的目标将按照调用顺序追加(定义)。
target_compile_definitions的参数可以使用带语法$<…>的“生成表达式”。
1 2 3 4 5 6 7 target_compile_definitions(foo PUBLIC FOO) target_compile_definitions(foo PUBLIC -DFOO) # -D removed target_compile_definitions(foo PUBLIC "" FOO) # "" ignored target_compile_definitions(foo PUBLIC -D FOO) # -D becomes "" , then ignored #定义带值的 target_compile_definitions( Tutorial PRIVATE "LOG_LEVEL=2" )
cmake+ROS2之rclcpp_components_register_node 背景
ROS2中的组件,类似与ROS1中的nodelet,这样无需写main函数,而是直接将组件编译成库。
组件通常都是rclcpp::Node的子类,因为组件不能控制线程,所以其构造函数不能运行占用太多时间或者阻塞的任务。
语法
写好一个Node,然后加上下面那句
1 2 3 4 5 6 #include "rclcpp_components/register_node_macro.hpp" // Register the component with class_loader. // This acts as a sort of entry point, allowing the component to be discoverable when its library // is being loaded into a running process. RCLCPP_COMPONENTS_REGISTER_NODE(composition::Talker)
然后组件的CMakeLists.txt中必须加上
1 2 3 4 5 add_library(talker_component SHARED src/talker_component.cpp) rclcpp_components_register_nodes(talker_component "composition::Talker") # To register multiple components in the same shared library, use multiple calls # rclcpp_components_register_nodes(talker_component "composition::Talker2")
action设计中的示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 cmake_minimum_required(VERSION 3.8) project(action_tutorials_cpp) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(action_tutorials_interfaces REQUIRED) find_package(rclcpp REQUIRED) find_package(rclcpp_action REQUIRED) find_package(rclcpp_components REQUIRED) # 表示将cpp编译为名为action_server的共享库 add_library(action_server SHARED src/fibonacci_action_server.cpp) # 编译action_server所依赖的头文件的搜索路径 target_include_directories(action_server PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>) # 在编译时灵活注入需要的宏定义 target_compile_definitions(action_server PRIVATE "ACTION_TUTORIALS_CPP_BUILDING_DLL") ament_target_dependencies(action_server "action_tutorials_interfaces" "rclcpp" "rclcpp_action" "rclcpp_components") rclcpp_components_register_node(action_server PLUGIN "action_tutorials_cpp::FibonacciActionServer" EXECUTABLE fibonacci_action_server) install(TARGETS action_server ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin) add_library(action_client SHARED src/fibonacci_action_client.cpp) target_include_directories(action_client PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>) target_compile_definitions(action_client PRIVATE "ACTION_TUTORIALS_CPP_BUILDING_DLL") ament_target_dependencies(action_client "action_tutorials_interfaces" "rclcpp" "rclcpp_action" "rclcpp_components") rclcpp_components_register_node(action_client PLUGIN "action_tutorials_cpp::FibonacciActionClient" EXECUTABLE fibonacci_action_client) install(TARGETS action_client ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # uncomment the line when a copyright and license is not present in all source files #set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # uncomment the line when this package is not in a git repo #set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() ament_package()