4. CMake 系列 - 项目添加编译选项
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 <stdio.h>
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", a, b, 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: 帮助
4. CMake 系列 - 项目添加编译选项的更多相关文章
- VisualGDB系列8:使用VS创建CMake Linux项目
根据VisualGDB官网(https://visualgdb.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指正. 本文介绍如何使用VS来创建.构建.调试一 ...
- CMAKE为项目输出名添加后缀
概述 本文将介绍cmake配置动态库和可执行程序两种,使用cmake为其添加Debug和Release配置下的后缀 动态库 下面将介绍使用CMAKE_DEBUG_POSTFIX和CMAKE_RELEA ...
- CMake入门-04-自定义编译选项
工作环境 系统:macOS Mojave 10.14.6 CMake: Version 3.15.0-rc4 Hello,World! - 自定义编译选项 CMake 允许为项目增加编译选项,从而可以 ...
- 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现
本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...
- 学习ASP.NET Core Razor 编程系列二——添加一个实体
在Razor页面应用程序中添加一个实体 在本篇文章中,学习添加用于管理数据库中的书籍的实体类.通过实体框架(EF Core)使用这些类来处理数据库.EF Core是一个对象关系映射(ORM)框架,它简 ...
- 学习ASP.NET Core Razor 编程系列十——添加新字段
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- CMake 构建项目教程-简介
CMake 构建项目教程-简介 Linux 平台构建项目,选择了CLion作为C++的IDE,而CLion默认就是使用CMake构建项目,所以这里记录了CMake在构建项目过程的一些小知识. 1. 项 ...
- Android Studio向项目添加C/C++原生代码教程
说明:本文相当于官方文档的个人重新实现,官方文档链接:https://developer.android.com/studio/projects/add-native-code 向项目添加C/C++代 ...
- VisualGDB:使用VS创建CMake Linux项目
转载地址:点击打开链接 根据VisualGDB官网(https://visualgdb.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指正. 本文介绍如何使用 ...
随机推荐
- python的复制,深拷贝和浅拷贝的区别(转)
在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 一般有三种方法, alist=[1,2,3,[& ...
- Holm–Bonferroni method
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录视频) https://study.163.com/course/introduction.htm?courseId=1005269003&u ...
- Ubuntu 14.04.3 window10双系统情遇到'Disconnected: You are now offline'问题
笔电是win10系统,单独开除50G做了一个Ubuntu系统,安装的是14.04.03版本,安装成功后,发现wifi连接不上,选择wifi并输入密码后提示:“Disconnected: You are ...
- 用shell获取目录/文件夹/文件的时间戳
命令: date +%s -r 目录名/文件名 输出内容形如: 1276225332
- 树链剖分处理+线段树解决问题 HDU 5029
http://acm.split.hdu.edu.cn/showproblem.php?pid=5029 题意:n个点的树,m次操作.每次操作输入L,R,V,表示在[L,R]这个区间加上V这个数字.比 ...
- 【BZOJ】3262: 陌上花开
[题意]三维偏序,给定n个点(x,y,z),求每个点和(0,0,0)组成空间中的点数,有重点.1<=x,y,z<=2*10^5,1<=n<=10^5. [算法]CDQ分治+树状 ...
- PHP做文件限速下载
<?php include("DBDA.class.php"); $db = new DBDA(); $bs = $_SERVER["QUERY_STRING&qu ...
- https://segmentfault.com/bookmark/1230000008276077
https://segmentfault.com/bookmark/1230000008276077
- docker使用现有容器生成新的镜像
/*运行docker run后 --则进入该容器里了 我们做一些变更,比如安装一些东西 ,然后针对这个容器进行创建新的镜像 */ 基本形式: docker commit -m "change ...
- Coursera在线学习---第四节.过拟合问题
一.解决过拟合问题方法 1)减少特征数量 --人为筛选 --靠模型筛选 2)正则化(Regularization) 原理:可以降低参数Θ的数量级,使一些Θ值变得非常之小.这样的目的既能保证足够的特征变 ...