1. 项目目录结构

test3

├── add

│?? ├── add.c

│?? ├── add.h

│?? └── CMakeLists.txt

├── build

├── CMakeLists.txt

├── config.h.in

├── example

│?? ├── CMakeLists.txt

│?? └── test.c

└── sub

├── CMakeLists.txt

├── sub.c

└── sub.h

很多开源项目都支持编译选项控制编译,用户可以根据编译选项定制需要的功能,典型例子如linux内核,用户可根据自身裁剪内核。

CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。

编译选项控制编译的核心思想:通过CMake生成config.h,config.h文件定义一些宏,项目代码包含config.h文件,通过这些宏控制代码模块。

2. 相关代码

2.1 add 模块

add.h

#ifndef _ADD_H

#define _ADD_H

int add(const int a,const int b);

#endif

add.c

#include "add.h"

int add(const int a,const int b)

{

return a+b;

}

CMakeLists.txt

# 递归获取目录下所有的C文件

file(GLOB_RECURSE c_files ./*.c)

# 递归获取目录下所有的h文件

file(GLOB_RECURSE h_files ./*.h)

#生成动态库和静态库

add_library(add_lib_shared SHARED ${c_files})

add_library(add_lib_static STATIC ${c_files})

#将动态库和静态库的名字设置为 add

set_target_properties(add_lib_shared PROPERTIES OUTPUT_NAME "add")

set_target_properties(add_lib_static PROPERTIES OUTPUT_NAME "add")

#设置动态库版本

set_target_properties(add_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)

#安装动态库和静态库

INSTALL(TARGETS add_lib_shared add_lib_static

LIBRARY DESTINATION lib

ARCHIVE DESTINATION lib)

#安装头文件

INSTALL(FILES ${h_files} DESTINATION include)

2.2 sub 模块

sub.h

#ifndef _SUB_H

#define _SUB_H

int sub(const int a,const int b);

#endif

sub.c

#include "sub.h"

int sub(const int a,const int b)

{

return a - b;

}

CMakeLists.txt

#递归获取目录下所有的C文件

file(GLOB_RECURSE c_files ./*.c)

# 递归获取目录下所有的h文件

file(GLOB_RECURSE h_files ./*.h)

#生成动态库和静态库

add_library(sub_lib_shared SHARED ${c_files})

add_library(sub_lib_static STATIC ${c_files})

#将动态库和静态库的名字设置为 sub

set_target_properties(sub_lib_shared PROPERTIES OUTPUT_NAME "sub")

set_target_properties(sub_lib_static PROPERTIES OUTPUT_NAME "sub")

#设置动态库版本

set_target_properties(sub_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)

#设置动态库版本

set_target_properties(sub_lib_shared PROPERTIES VERSION 1.0 SOVERSION 1)

#安装动态库和静态库

INSTALL(TARGETS sub_lib_shared sub_lib_static

LIBRARY DESTINATION lib

ARCHIVE DESTINATION lib)

#安装头文件

INSTALL(FILES ${h_files} DESTINATION include)

2.3 example 模块

test.c

#include "config.h"

#ifdef ENABLE_ADD

#include "add.h"

#endif

#ifdef ENABLE_SUB

#include "sub.h"

#endif

#include

int main(int argc,char **argv)

{

int a = 10;

int b = 8;

#ifdef ENABLE_ADD

printf("%d + %d = %d\n",a,b,add(a,b));

#endif

#ifdef ENABLE_SUB

printf("%d - %d = %d\n",sub(a,b));

#endif

return 0;

}

CMakeLists.txt

# 添加头文件路径

include_directories(${PROJECT_SOURCE_DIR}/add)

include_directories(${PROJECT_SOURCE_DIR}/sub)

include_directories(${PROJECT_SOURCE_DIR})

# 添加第三方库(add)头文件路径

link_directories(${PROJECT_SOURCE_DIR}/lib)

# 生成执行文件

add_executable(test_add_sub test.c)

# 链接库文件

if(ENABLE_ADD)

target_link_libraries(test_add_sub add)

endif(ENABLE_ADD)

if(ENABLE_SUB)

target_link_libraries(test_add_sub sub)

endif(ENABLE_SUB)

INSTALL(TARGETS test_add_sub

RUNTIME DESTINATION bin)

2.4 顶层 CMakeLists.txt

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

# 设置库文件输出目录

set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 设置执行文件输出目录

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

# 添加编译选项

option(ENABLE_ADD "enable add" ON)

option(ENABLE_SUB "enable sub" ON)

if(ENABLE_ADD)

add_subdirectory(add)

endif(ENABLE_ADD)

if(ENABLE_SUB)

add_subdirectory(sub)

endif(ENABLE_SUB)

# 加入一个头文件配置,让cmake对源码进行操作

configure_file(

"${PROJECT_SOURCE_DIR}/config.h.in"

"${PROJECT_SOURCE_DIR}/config.h"

)

add_subdirectory(example)

说明:

configure_file命令用于加入一个配置头文件config.h ,这个文件由CMake从config.h.in生成,通过这样的机制,将可以通过预定义一些参数和变量来控制代码的生成。

option命令添加了ENABLE_ADD 选项

和ENABLE_SUB选项,并且默认值为ON。

cmake 可以根据ENABLE_ADD 选项

和ENABLE_SUB选项的值来控制是否编译add模块和sub模块。

要想在config.h生成对应的宏,需要对config.h.in进行如下配置

config.h.in

#cmakedefine ENABLE_ADD

#cmakedefine ENABLE_SUB

3. 配置&编译

默认配置&编译

$ cd build

$ cmake ..

$ make

$ cd ..

$ tree bin lib

效果如下:

bin

└── test_add_sub

lib

├── libadd.a

├── libadd.so -> libadd.so.1

├── libadd.so.1 -> libadd.so.1.0

├── libadd.so.1.0

├── libsub.a

├── libsub.so -> libsub.so.1

├── libsub.so.1 -> libsub.so.1.0

└── libsub.so.1.0

从生成的lib库,可以看出,add模块和sub模块都生成了。

查看config.h

#define ENABLE_ADD

#define ENABLE_SUB

自定义配置&编译

$ cd build

$ cmake -DENABLE_ADD=OFF ..

$ make

$ cd ..

$ tree bin lib

效果如下:

bin

└── test_add_sub

lib

├── libsub.a

├── libsub.so -> libsub.so.1

├── libsub.so.1 -> libsub.so.1.0

└── libsub.so.1.0

从生成的lib库,可以看出,add模块并未生成了。

查看config.h

/* #undef ENABLE_ADD */

#define ENABLE_SUB

使用ccmake工具进行配置

当我们的项目很大且配置选项很多的时候,可以选择ccmake工具进行配置编译选项,这个是交互式配置工具,有点类似内核的menuconfigure的功能。

说明:

enter: 编辑选项

c: 配置

g:生成makefile

q:退出

h: 帮助

linux增加 编译选项,4. CMake 系列 - 项目添加编译选项相关推荐

  1. 【Linux系列】添加系统调用

    [Linux系列]添加系统调用最新教程 编译环境 修改任务 基础任务 进阶任务 修改准备 修改源码 添加系统调用号 修改系统调用头文件 修改系统调用函数定义 编译安装内核 编写主程序 进阶任务 总结 ...

  2. 【Webpack 性能优化系列(8) - PWA】使用渐进式网络应用程序为我们的项目添加离线体验

    webpack系列文章: [Webpack 性能优化系列(9) - 多进程打包]极大的提升项目打包构建速度!!! [Webpack 性能优化系列(7) - 懒加载和预加载] [Webpack 性能优化 ...

  3. linux比较厉害的运维项目,Linux运维项目实战系列

    ORACLE 博客文章目录(2015-05-27更新) 从接触ORACLE到深入学习,已有好几年了,虽然写的博客不多,质量也参差不齐,但是,它却是成长的历程的点点滴滴的一个见证,见证了我在这条路上的寻 ...

  4. vue3 +vite+ts实战项目添加 eslint + prettier + lint-staged 踩坑指南

    初始化项目 // 创建一个空的 vue3-ts 项目, yarn create vite my-vue-app --template vue-ts // 安装依赖 cd my-vue-app & ...

  5. Linux增加四个用户分别并命名,16、Linux用户和组管理命令演练和实战应用,,150R...

    一.内容回顾 bash  globing,*,?,[],[^] IO重定向及管道  >  ,   >>  ,  2>  ,   2>>   &>  , ...

  6. 大型分布式redis+solr+Linux+nginx+springmvc+mybatis电商项目-任亮-专题视频课程

    大型分布式redis+solr+Linux+nginx+springmvc+mybatis电商项目-45845人已学习 课程介绍         中国移动省级网上商城项目,用于建立网上终端.营销案和号 ...

  7. “轻松搞定CMake”系列之CMakeLists文件编写语法规则详解

    文章目录 基本语法规则 常见CMakeLists.txt中指令剖析 从VS项目配置过程理解CMakeLists内容 CMake中常用变量汇总 常用CMakeLists文件模板 基础模板 使用OpenC ...

  8. android如何在底部显示四个按钮,[Android系列—] 四. 添加操作栏(Action Bar)

    [Android系列-] 4. 添加操作栏(Action Bar) 前言 操作栏是最重要的设计元素之一,使用它来实现你的应用程序活动.通过提供多种用户界面功能, 使应用程序快速和其他的Andorid应 ...

  9. 向基于Linux的Oracle RAC 10g集群添加新节点

    在多数业务中,Oracle真正应用集群 (RAC) 配置的主要业务要求是整个系统中数据库层的可伸缩性 - 这样,当用户数增加时,可将额外实例添加到该集群来分发该负载.     在Oracle RAC ...

最新文章

  1. 这所211高校通知不放寒假!校园将实行封闭管理!
  2. “上拉电阻与下拉电阻”通俗解读
  3. python2 python3编码_Python2和Python3编码问题-从底层出发
  4. NYOJ 158 省赛来了
  5. Serval and Toy Bricks
  6. python求数组最大值_Python算法与数据结构--求所有子数组的和的最大值
  7. 【HDU - 5912】Fraction (模拟)
  8. k8s pod里访问不到外部ip_K8S容器网络如何实现通信?
  9. 图像处理中小波变换的学习笔记
  10. 前端开发者如何利用 CSS 实现酷炫的变色方案?
  11. jacob 详解 语音_JAVA 实现Jacob语音播报
  12. 智头条」十四五数字经济发展规划发布,工信部推动充电标准统一
  13. ArcGIS椭球面积计算Python代码
  14. 2019年中国锂电池产业竞争格局
  15. 白杨SEO:聊聊微信红包封面、微信8.0状态背景图片和视频素材背后的商机
  16. vue中数字转金额格式
  17. CenterNet: Keypoint Triplets for Object Detection论文详解
  18. LeCo-136. 只出现一次的数字
  19. python实验二序列_Python合集之Python序列(二)
  20. 一个很好用的计划管理软件——飞项

热门文章

  1. 用python写一个简单的爬虫_Python实现简易Web爬虫详解
  2. 电信 IPRAN 设备组网方案_国内首家5G核心网电信设备进网许可证;电信5G网络增强方案获认可;美国最大规模毫米波拍卖...
  3. 前端html继承的方式,好程序员web前端教程之JS继承实现方式解析
  4. 华为 mysql实例监控,华为云文档数据库服务DDS监控告警全新优化
  5. chromedp网络监听_动态爬虫三:监听网络事件 + 监听js事件
  6. ps怎么更改背景图层大小_PS软件零基础抠图教程,教你PS滤镜抠图技巧和方法
  7. 在人脸识别的时候,一定要穿上衣服啊!
  8. 皮一皮:看看地铁有多挤...
  9. 皮一皮:大哥!二弟!三弟!
  10. Netty 用起来够猛!