cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
cmake_minimum_required
指定构建您的项目所需的 CMake 的最低版本。在这个例子中,VERSION 3.16
意味着您的项目需要使用 CMake 3.16 或更高版本来构建。
FATAL_ERROR
参数告诉 CMake,如果当前使用的 CMake 版本低于指定的最低版本,构建过程应该中止并显示错误信息。
find_package(fastcdr REQUIRED)
根据指定的软件包名称,在系统中查找该软件包的安装位置和配置文件,在系统上查找并加载 fastcdr
软件包。会查找与该软件包关联的 Find<PackageName>.cmake
文件或 <PackageName>-config.cmake
文件。这两种类型的文件可以提供有关软件包的配置信息,例如头文件路径、库文件路径和编译选项等。
REQUIRED
参数表示 fastcdr
软件包是必需的,如果找不到该软件包或无法加载正确的配置文件,CMake 将会发出错误并停止构建。
include(${COMMUNICATION_ROOT_DIR}/cmake/gen_config.cmake)
在 CMakeLists.txt 文件中,include
命令用于包含其他 CMake 脚本文件
此命令用于引入 ${COMMUNICATION_ROOT_DIR}/cmake/gen_config.cmake
文件中定义的 CMake 配置信息。可以将 gen_config.cmake
文件中的变量、函数或宏等内容导入到当前的 CMakeLists.txt 文件中,从而在构建和配置过程中使用其中定义的内容。
${COMMUNICATION_ROOT_DIR}
是一个变量(之前应该设置好在用),用于表示通信模块的根目录路径。
自定义函数的语法和代码块类似,你可以在其中使用 CMake 的命令、变量和表达式。在 CMakeLists.txt 中定义的自定义函数可以在同一个文件中或其他的 CMake 模块中调用
在 CMakeLists.txt
或其他相关的 source 文件中实现自定义函数,建议在定义源代码编译规则之前定义,这样在编译源代码时,生成的文件就可以包含自定义函数的内容。在 CMakeLists.txt
中定义自定义函数,可以使用 function()
或 macro()
命令进行定义。
如上图:先在本cmakelists中利用function定义了一个my_custom_fuction函数,里面是message功能。接下来我就可以写成my_custom_fuction()调用它。
如果你不想在调用的CMakeLists.txt
文件中定义自定义函数,你可以将自定义函数的实现放在另一个独立的 CMake 模块中,并在需要使用该函数的 CMakeLists.txt 文件中引入这个模块。 假设你的自定义函数被定义在名为my_custom_functions.cmake
的文件中,你可以在需要使用该函数的CMakeLists.txt
文件中通过include()
命令引入该模块,并在引入后即可使用自定义函数。示例如下:
my_custom_functions.cmake文件内容
include引入该模块,接下来才能用
项目案例:
include(gen_protobuf_source_file)
gen_protobuf_source_file_single(${COMMUNICATION_ROOT_DIR}/protocol/mxnavi/localization_fusion.proto ${CMAKE_CURRENT_LIST_DIR}/gen)
第一句是在CMakeLists.txt
中引入一个名为gen_protobuf_source_file.cmake
的CMake模块或脚本,第二句是调用了gen_protobuf_source_file_single这个函数,并传入了橙/紫两参数。
在CMake中,你可以使用add_custom_command()
和add_custom_target()
来创建自定义命令。如下:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h
COMMAND ln -sf ${CMAKE_CURRENT_LIST_DIR}/../fusionloc/interface/ifusionloc_data_def.h ${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h
DEPENDS ${PROTO_GEN_SOURCES}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
BYPRODUCTS ${CMAKE_CURRENT_LIST_DIR}/include/ifusionloc_data_def.h
COMMENT "ln ifusionloc_data_def.h to localization include"
)
这是一个使用add_custom_command()
命令的CMake指令示例。add_custom_command()
命令允许你在构建过程中添加自定义的操作。
该例子是在构建过程中创建一个符号链接 (symbolic link),将${CMAKE_CURRENT_LIST_DIR}/../fusionloc/interface/ifusionloc_data_def.h
链接到${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h
。
解释一下每个参数的含义:
-
OUTPUT
:指定生成的输出文件路径,即${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h
。这将告诉CMake在构建过程中生成这个文件。 -
COMMAND
:指定要执行的命令。在这个例子中,我们使用ln -sf
命令创建了一个符号链接。${CMAKE_CURRENT_LIST_DIR}/../fusionloc/interface/ifusionloc_data_def.h
是链接的目标文件,${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h
是链接的路径和名称。 -
DEPENDS
:指定生成这个文件所依赖的其他文件。${PROTO_GEN_SOURCES}
是一个表示其他文件的变量,你可以根据项目需要设置这个变量。 -
WORKING_DIRECTORY
:指定工作目录,即${CMAKE_CURRENT_LIST_DIR}
。这将使得在执行命令时,使用${CMAKE_CURRENT_LIST_DIR}
作为命令的工作目录。 -
BYPRODUCTS
:指定生成的副产品文件路径,即${CMAKE_CURRENT_LIST_DIR}/include/ifusionloc_data_def.h
。CMake会在构建完成后检查这个文件是否存在,并将其列入构建过程的依赖关系。 -
COMMENT
:指定要显示的构建过程中的注释信息,即"ln ifusionloc_data_def.h to localization include"。
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/source/localization localization_obj)
使用 CMake 的命令add_subdirectory 在当前目录下添加一个子目录
表示将 ${CMAKE_CURRENT_LIST_DIR}/source/localization
目录作为子目录添加到项目中, CMake 将进入 ${CMAKE_CURRENT_LIST_DIR}/source/localization
目录,并执行该目录中的 CMakeLists.txt 文件,以构建该子目录中的源文件和其他资源。构建的结果可能是一个静态库、共享库或可执行文件,具体取决于子目录中的 CMakeLists.txt 文件中的设置。并将生成的目标存储在 localization_obj
变量中。这样,主目录中的其他代码可以使用 localization_obj
变量引用子目录中的构建目标。
add_subdirectory(directory [binary_dir] [exclude_from_all])
参数1为要添加的目录的路径,可以是相对路径或绝对路径。
参数2为目标文件的输出目录,如果未指定,将使用 ${CMAKE_BINARY_DIR}/${directory}
参数3是一个可选的参数,用于设置是否将子目录添加到 ALL
或 default
目标中,取值为 ON
或 OFF
。默认为 OFF
add_library(<name> [<type>] [<source_files>])
add_library()
是一个CMake命令,用于创建库文件,并将源文件添加到库中。 <name>
是库文件的名称, <type>
是库文件的类型,可以是 STATIC
、 SHARED
或MODULE
,分别表示静态库、共享库和Mac OS X模块。<source_files>
是要编译成库文件的源文件列表。
例:add_library(localization SHARED ${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h source/trace.cpp source/factory.cpp )
在该命令中,我们创建了一个名为localization
的共享库,类型为SHARED
。然后,我们通过 ${CMAKE_CURRENT_LIST_DIR}/include/localization/ifusionloc_data_def.h
指定库的头文件,source/trace.cpp
和 source/factory.cpp
则是库的源文件。在默认情况下,CMake将使用编译器根据源文件生成库文件。
target_sources()
函数是将指定的源文件添加到localization
这个目标中
例:
target_sources(localization PRIVATE ${PROTO_GEN_SOURCES} )
PRIVATE
关键字表明这些源文件只会用于该目标的编译过程中,不会被用于链接到该目标所依赖的其他目标中
${PROTO_GEN_SOURCES}
则是需要添加到目标中的源文件列表,他
可能是一个变量,该变量可能是在其他地方定义的,或是在你的 CMake 文件中定义的。它可能会包含一个或多个源文件的路径。
target_sources()
函数可以由add_executable()
或add_library()
等命令调用,用于将源文件添加到目标中。
例如,以下示例展示了如何使用target_sources()
将main.cpp
、foo.cpp
和bar.cpp
这三个源文件添加到my_program
目标中:
这些源文件的路径使用了${CMAKE_CURRENT_LIST_DIR}
变量来获取当前 CMake 文件所在的目录。
PRIVATE
是指定源文件的属性和使用范围的选项之一。除了PRIVATE
之外,还可以使用PUBLIC
和INTERFACE
选项。
这些选项是用来指定源文件的属性和可见性,以控制它们在目标中的使用范围。这可以影响编译目标的其他组件对这些源文件的可见性。
-
PRIVATE
:将源文件标记为私有,只能在当前目标内部使用。这意味着其他依赖当前目标的目标不能直接使用这些源文件。这个选项通常用于定义和实现目标的内部逻辑。 -
PUBLIC
:将源文件标记为公共,可以在当前目标以及依赖当前目标的其他目标中使用。这意味着其他目标可以直接引用和访问这些源文件。这个选项通常用于定义目标的公共接口。 -
INTERFACE
:将源文件标记为接口,可以在依赖当前目标的其他目标中使用,但不能在当前目标中使用。这个选项通常用于定义目标的公共接口,但不包含实现细节。
请注意,这些选项不仅适用于target_sources
命令,还适用于其他CMake命令,如target_include_directories
和target_link_libraries
。
target_include_directories
是 CMake 的一个命令,用于告诉编译器在编译某个目标(如库或可执行文件)时应该包含哪些头文件目录。
该命令接受两个参数:目标:告诉 CMake 哪个目标需要包含头文件目录 目录列表:需要包含的头文件所在的目录列表 目标通常是一个库或可执行文件,可以通过 add_library
或 add_executable
命令定义。目录列表是一个 CMake 列表,其中包含了需要包含的头文件所在的目录。
项目案例:target_include_directories(localization PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/localization)
这段代码告诉 CMake 在编译名为 “localization” 的目标时要包含两个目录: 第一个是公共目录,里面包含了一些公共的头文件。其他依赖于该目标的项目也应该包含这个目录,以便正确引用公共头文件。第二个是一个私有目录,它包含了一些只在 “localization” 目标内部使用的头文件。其他依赖于 “localization” 的项目不需要包含这个目录,因为这些头文件仅在目标内部可见。
target_link_libraries
是 CMake 的一个命令,用于指定一个目标(例如库或可执行文件)所依赖的其他库 。 该命令有两个参数 目标:告诉 CMake 哪个目标需要链接其他库 库列表:需要链接到目标的库列表
项目案例:target_link_libraries(localization
PUBLIC
foundation PRIVATE adapter )不都写在一行,这样显得更清晰易读。
这个代码片段中,它用于将名为 localization
的目标与 foundation
库进行公开链接,同时与 adapter
库进行私有链接。 这意味着 localization
目标将可以访问 foundation
库提供的函数和符号,而对于 adapter
库中的函数和符号,则只能在 localization
目标内部使用。