Cmake基础(7)

这次是Cmake的重点,多项目


其实我们在一个cmake中使用多个add_excuatable 和add_library就能有多个项目了。但是这样维护十分不方便。一般而言,一个项目一个cmake文件,并且放在一个独立的文件夹是常规做法。

add_subdirectory

add_subdirectory是cmake提供的函数,把其他目录下的cmake文件添加到此处。
add_subdirectory(subdirectory)
subdirectory 是相对于当前 CMakeLists.txt 文件的子目录路径。
.
.
add_subdirectory 是 CMake 中的一个命令,其语法如下:

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
  • source_dir:指定包含 CMakeLists.txt 文件的源代码目录。
  • binary_dir:可选参数,指定生成输出文件的二进制目录。如果未提供,CMake 将使用与源目录对应的二进制目录。
  • EXCLUDE_FROM_ALL:可选参数,如果存在,则将在默认构建目标中排除在子目录中生成的目标。
    EXCLUDE_FROM_ALL是make all的时候可以忽略这个文件,一般很少用。

binary_dir是用来存放cmake生成的文件

假如说我们有多个cmake文件,我们可以遍历:

# 当前cmake文件夹中的module文件夹下的所有的文件夹,存放在moduledirs 中
file(GLOB moduledirs "${CMAKE_SOURCE_DIR}/module/*")
# 遍历刚才的文件夹列表
foreach(dir in ${moduledirs})
# 如果文件夹下存在一个CMakeLists.txt文件
    if(EXISTS ${dir}/CMakeLists.txt)
		get_filename_component(MODULE ${dir} NAME)
		message("MODULE : " ${MODULE})
		add_subdirectory(${dir} ${CMAKE_SOURCE_DIR}/build/${MODULE})
	endif()
endforeach()

get_filename_component

是 CMake 中的一个命令,用于提取文件路径的不同部分。其语法如下:

get_filename_component(<variable> <filename> <component> [CACHE])
  • <variable>:指定一个变量来存储提取的组件的结果。
  • <filename>:指定要提取组件的文件路径。
  • <component>:指定要提取的组件,可以是以下之一:
    • DIRECTORY:目录部分。
    • NAME:文件名部分。
    • EXT:文件扩展名。
    • NAME_WE:文件名部分(不包含扩展名)。
  • [CACHE]:可选参数,如果存在,则将结果缓存,以便后续调用 get_filename_component 时直接使用缓存的值。

add_subdirectory 在 CMake 中用于将其他目录的 CMakeLists.txt 文件包含到当前项目中。关于变量的访问,有一些规则:

变量作用域

全局变量

PS E:\workspace\cmake_demo\simple_demo\build> cmake ..
-- Building for: Visual Studio 16 2019
-- ^^^^^^Compiler: MSVC
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^E:/workspace/cmake_demo/simple_demo/Lib/x64/Debug
MODULE : module1
-- ^^^^^^Compiler: MSVC
MODULE : module2
-- ^^^^^^Compiler: MSVC
-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^E:/workspace/cmake_demo/simple_demo/Lib/x64/Debug
-- Configuring done (0.0s)
-- Generating done (0.1s)
-- Build files have been written to: E:/workspace/cmake_demo/simple_demo/build

子目录和主目录同时打印下面这个,打印出来是同样的结果。

message(STATUS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG})

E:/workspace/cmake_demo/simple_demo/Lib/x64/Debug
E:/workspace/cmake_demo/simple_demo/Lib/x64/Debug
子目录打印

message(STATUS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^${CMAKE_SOURCE_DIR}/Lib/${platform}/Debug)

结果还是E:/workspace/cmake_demo/simple_demo/Lib/x64/Debug说明子目录的CMAKE_SOURCE_DIR是主目录一致

在CMake中,CMAKE_SOURCE_DIR 是一个全局变量,代表顶层CMakeLists.txt所在的目录,不是当前CMakeLists.txt文件所在的目录。因此,无论在主目录还是在子目录中使用 CMAKE_SOURCE_DIR,都将得到同样的结果,即顶层CMakeLists.txt所在的目录。
如果你想要在子目录中获取当前CMakeLists.txt所在的目录,可以使用 CMAKE_CURRENT_SOURCE_DIR。这个变量表示当前处理的 CMakeLists.txt 文件所在的目录。

所以,在你的例子中,如果想在子目录中获取与子目录相关的路径,可以使用 CMAKE_CURRENT_SOURCE_DIR,而不是 CMAKE_SOURCE_DIR。例如:

message(STATUS "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ${CMAKE_CURRENT_SOURCE_DIR}/Lib/${platform}/Debug")

这样可以确保在子目录中获取到正确的路径。

主目录定义变量可以在子目录访问到

主目录添加 set(fock “fock”)
子目录可以打印出来 message(STATUS ^^^^^^^^^^${fock})
多层级的子目录也可以访问到,也就是多次执行add_subdirectory

字目录定义PARENT_SCOPE变量可以在主目录访问到

子目录设置变量 set(MY_VARIABLE “Hello” PARENT_SCOPE)
主目录可以打印出来
后加载的子目录可以把先加载的子目录中的PARENT_SCOPE变量打印出来:假如MY_VARIABLE 在module1中定义,module2后加载那么module2可以打印MY_VARIABLE 。

PARENT_SCOPE 只能穿透到上一层的作用域,即它将变量传递到调用 add_subdirectory 的上一层目录。如果有多层的 add_subdirectory,则需要多次使用 PARENT_SCOPE 才能传递到更上一层目录。

例如:

# CMakeLists.txt (Level 1)
set(MY_VARIABLE "Value" PARENT_SCOPE)
add_subdirectory(subdir)
# subdir/CMakeLists.txt (Level 2)
set(MY_VARIABLE "NewValue" PARENT_SCOPE)

在这个例子中,subdir/CMakeLists.txt 中的 MY_VARIABLE 通过 PARENT_SCOPE 被传递到 CMakeLists.txt (Level 1) 中,但如果存在更上一层的目录,你需要在更上一层再次使用 PARENT_SCOPE 才能传递到更上一层。

添加依赖项

# 设置依赖库
SET(Depends
	module1)

# 设置依赖关系和链接库
foreach(loop_var ${Depends})
	if(EXISTS ${PROJECT_SOURCE_DIR}/${loop_var})
		add_dependencies(${LIN_NAME} ${loop_var})
	endif()
# 顺势加载库
	SET(LINK_LIBRARY optimized ${PROJECT_SOURCE_DIR}/Lib/x64/Release/${loop_var}${CMAKE_RELEASE_POSTFIX}.lib 
	debug ${PROJECT_SOURCE_DIR}/Lib/x64/Debug/${loop_var}${CMAKE_DEBUG_POSTFIX}.lib)
	target_link_libraries(${SAMPLE_NAME} PRIVATE ${LINK_LIBRARY})
endforeach()

两个子目录,一个是module1,一个是module2,module1先被add_subdirectory,module2即使还没有被add_subdirectory,module1也可以依赖于module2。

但是不要循环依赖

CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
  "MYLIBADD" of type SHARED_LIBRARY
    depends on "MYLIBSUB" (strong)
  "MYLIBSUB" of type SHARED_LIBRARY
    depends on "MYLIBADD" (strong)
At least one of these targets is not a STATIC_LIBRARY.  Cyclic dependencies are allowed only among static libraries.

相关推荐

  1. Cmake基础(7)

    2023-12-19 06:46:02       32 阅读
  2. Cmake基础(2)

    2023-12-19 06:46:02       31 阅读
  3. Cmake基础(6)

    2023-12-19 06:46:02       34 阅读
  4. Cmake基础(5)

    2023-12-19 06:46:02       46 阅读
  5. CMake基本使用

    2023-12-19 06:46:02       32 阅读
  6. Cmake

    2023-12-19 06:46:02       38 阅读
  7. <span style='color:red;'>Cmake</span>

    Cmake

    2023-12-19 06:46:02      47 阅读
  8. cmake

    2023-12-19 06:46:02       34 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-19 06:46:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-19 06:46:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-19 06:46:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-19 06:46:02       20 阅读

热门阅读

  1. 【Leetcode】计算器

    2023-12-19 06:46:02       42 阅读
  2. 数据的输入输出(C++)

    2023-12-19 06:46:02       41 阅读
  3. Docker (Dockerfile运行jar) -day 05

    2023-12-19 06:46:02       42 阅读
  4. .net web API的文件传输(上传和下载)客户端winform

    2023-12-19 06:46:02       33 阅读
  5. 【Node】npm使用手册

    2023-12-19 06:46:02       46 阅读
  6. 文件相关工具类Utils(WORD,PDF,PNG)

    2023-12-19 06:46:02       33 阅读
  7. 第六章--- 实现微服务:匹配系统(下)

    2023-12-19 06:46:02       28 阅读
  8. 在iframe怎么把外面的dialog关掉

    2023-12-19 06:46:02       37 阅读