CMake多模块的构建方式
前些天用 C 和 CPP 写了一个较为大型的项目(可能也没有那么大型),其中模块间有相互依赖关系,配环境时候卡了很久,主要是对 CMake 的多模块不熟悉,查资料、抄 llvm、瞎测搞出了一些规律,本文不保证很准确,选择性地阅读。
本文不保证很准确,请选择性地阅读。
一、单个模块和基本语法
基本属性
cmake_minimum_required(VERSION 3.13)
表示版本号,一般无所谓。
project(%s, C/CXX)
表示该项目是什么语言写的,这个很重要,因为编译出来的符号可能是不一致的。
1 | SET(CMAKE_C_FLAGS "-m32") |
设置这两个变量,SET 是一个常见的语法,表示赋值;如果要表示追加的话,可以使用这句 SET(CMAKE_C_FLAGS ${CMAKE_C_FLAG}"aaa")
,结果是 "-m32aaa" 如果用空格隔开,结果是 "-m32;aaa" ,还是有区别的。
构建动态链接库 add_library
add_library(A_shared SHARED fileA.c include/fileA.h)
这样会在目录下生成 libA_shared.dylib (或者libA_shared.so )
构建静态链接库 add_library
add_library(B_static STATIC fileB.c include/fileB.h)
这样会在目录下生成 libB_static.a
构建可执行文件 add_executable
1 | add_executable(C_execute main.c) |
编译 main.c 的源文件,再将A 连接进去,将 B 连接进去,最终生成可执行文件 C_exetute 。
指定当前 project 的 include 目录 include_directories
include_directories(%s)
一般指定一些第三方依赖,或者为了结构化,指定include文件夹,这样可以在c代码里将 #include "include/hello.h" 省略为 #include "hello.h" 。(不保证这句话的准确性)
指定动态/静态链接库对外暴露的头文件
target_include_directories(A_shared PUBLIC ${PROJECT_SOURCE_DIR}/include)
这样在其他的 project 里,就可以访问到 include 目录下的一些文件。
二、添加子模块
吼!有这些基础知识后,就可以讲一下多模块的构建了!
用这句话添加子模块:add_subdirectory(sub1)
目录结构:子模块里一定也要有 CMakeLists.txt ,即 sub1/CMakeLists.txt 。
在sub1/CMakeLists.txt 里,为所欲为,该干嘛干嘛,这里先假设自闭的情况,不和父模块、兄弟模块交互。 而且,会从父模块继承一些东西下来,继承什么我不大清楚。
三、模块相互依赖关系
以子模块sub2依赖子模块sub1为例。 目录结构为:
1 | - CMakeLists.txt |
主要内容为:
cat CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.13) |
cat sub1/CMakeLists.txt
1 | project(sub1 C) |
cat sub2/CMakeLists.txt
1 | project(sub2) |
有几条规则: 子模块的 project之间是相互可以访问到的,不需要额外操作,例如exec_2可以访问到shared_1。 target_include_directories 是为了让exec_2 访问到shared_1 的头文件,否则只能访问到共享库本身。
四、总结
有这些应该够用了,反正我开发是够了。