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欢迎大家指正. 本文介绍如何使用 ...
随机推荐
- 使用pt-ioprofile监控数据库io文件读写情况
我们在做IO密集型的应用程序的时候,比如MySQL数据库,通常系统的表现取决于workload的类型. 比如我们要调优,我们就必须非常清楚的知道数据的访问规律,收集到足够的数据,用来做调优的依据. 有 ...
- c/c++中的预编译指令总结
预处理指令提供按条件跳过源文件中的节.报告错误和警告条件,以及描绘源代码的不同区域的能力.使用术语“预处理指令”只是为了与 C 和 C++ 编程语言保持一致.在 C# 中没有单独的预处理步骤:预处理指 ...
- .Net并行编程系列之一:并行基础
现在普通PC平台上面多核处理器的普及,让我们领教了能够利用多核进行并行计算的软件的处理能力,同时继承更多地核心正是当前处理器发展的趋势. 但是作为一个.NET开发人员,是否有时候会发现你的程序占用了其 ...
- eclipse常用快捷键大全 (转)
Eclipse中10个最有用的快捷键组合 一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合.通过这些组合可以更加容易的浏览源代码,使得整体的开发效率和质量得到提升. ...
- poi复杂excel的实现
一:前言 最近帮一个朋友做excel的导出功能,对于我来说还是挺头疼,我看了下表格样式,对于我来说还是挺头疼的,想当年耗子刚刚出社会的时候做的第一份工作,第一份任务就是把把word转换为html,在这 ...
- 51nod 1171 大灾变
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1757 二分答案mid 避难所拆为mid个点 每个避难所的第一个点向第二个 ...
- Parencodings(模拟)
ZOJ Problem Set - 1016 Parencodings Time Limit: 2 Seconds Memory Limit: 65536 KB Let S = s1 s2 ...
- 【CodeForces】713 C. Sonya and Problem Wihtout a Legend
[题目]C. Sonya and Problem Wihtout a Legend [题意]给定n个数字,每次操作可以对一个数字±1,求最少操作次数使数列递增.n<=10^5. [算法]动态规划 ...
- 20155117王震宇 实验三 敏捷开发与XP实践 实验报告
实验内容 XP基础 XP核心实践 相关工具 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 2.完成实验.撰写实验报告,实 ...
- CodeForces - 996B
Allen wants to enter a fan zone that occupies a round square and has nn entrances. There already is ...