CMake 完整入门教程(五)

news2024/11/20 12:23:57
CMake 使用实例
13.1 例子一
一个经典的 C 程序,如何用 cmake 来进行构建程序呢?
//main.c
#include <stdio.h>
int main()
{
printf("Hello World!/n");
return 0;
}
编写一个 CMakeList.txt 文件 ( 可看做 cmake 的工程文件 )
project(HELLO)
set(SRC_LIST main.c)
add_executable(hello ${SRC_LIST})
然后,建立一个任意目录(比如本目录下创建一个 build 子目录),在该 build 目录下调用
cmake
注意:为了简单起见,我们从一开始就采用 cmake out-of-source 方式来构建
(即生成中间产物与源代码分离),并始终坚持这种方法,这也就是此处为什么单
独创建一个目录,然后在该目录下执行 cmake 的原因
cmake .. -G "NMake Makefiles"
nmake
或者
cmake .. -G "MinGW Makefiles"
make
即可生成可执行程序 hello(.exe)
目录结构
+
| +--- main.c
+--- CMakeList.txt
|
/--+ build/
 |
 +--- hello.exe
cmake 真的不太好用哈,使用 cmake 的过程,本身也就是一个编程的过程,只有多练才
行。
我们先看看:前面提到的这些都是什么呢?
13.1.1 CMakeList.txt
第一行 project 不是强制性的,但最好始终都加上。这一行会引入两个变量
HELLO_BINARY_DIR HELLO_SOURCE_DIR
同时, cmake 自动定义了两个等价的变量
PROJECT_BINARY_DIR PROJECT_SOURCE_DIR
因为是 out-of-source 方式构建,所以我们要时刻区分这两个变量对应的目录
可以通过 message 来输出变量的值
message(${PROJECT_SOURCE_DIR})
set 命令用来设置变量
add_exectuable 告诉工程生成一个可执行文件。
add_library 则告诉生成一个库文件。
注意: CMakeList.txt 文件中,命令名字是不区分大小写的,而参数和变量是大小写
相关的。
13.1.2 cmake 命令
cmake 命令后跟一个路径 (..) ,用来指出 CMakeList.txt 所在的位置。
由于系统中可能有多套构建环境,我们可以通过 -G 来制定生成哪种工程文件,通
cmake -h 可得到详细信息。 要显示执行构建过程中详细的信息 ( 比如为了得到更详细的出错信息 ) ,可以在
CMakeList.txt 内加入:
SET( CMAKE_VERBOSE_MAKEFILE on )
或者执行 make
$ make VERBOSE=1
或者
$ export VERBOSE=1
$ make
13.2 例子二
一个源文件的例子一似乎没什么意思,拆成 3 个文件再试试看:
hello.h 头文件
#ifndef DBZHANG_HELLO_
#define DBZHANG_HELLO_
void hello(const char* name);
#endif //DBZHANG_HELLO_
hello.c
#include <stdio.h>
#include "hello.h"
void hello(const char * name)
{
printf ("Hello %s!/n", name);
}
main.c
#include "hello.h"
int main() {
hello("World");
return 0;
}
然后准备好 CMakeList.txt 文件
project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})
执行 cmake 的过程同上,目录结构
+
|
+--- main.c
+--- hello.h
+--- hello.c
+--- CMakeList.txt
|
/--+ build/
 |
 +--- hello.exe
例子很简单,没什么可说的。
13.3 例子三
接前面的例子,我们将 hello.c 生成一个库,然后再使用会怎么样?
改写一下前面的 CMakeList.txt 文件试试:
project(HELLO)
set(LIB_SRC hello.c)
set(APP_SRC main.c)
add_library(libhello ${LIB_SRC})
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
和前面相比,我们添加了一个新的目标 libhello ,并将其链接进 hello 程序
然后像前面一样,运行 cmake
得到
+
|
+--- main.c
+--- hello.h
+--- hello.c
+--- CMakeList.txt
|
/--+ build/
|
+--- hello.exe
+--- libhello.lib
里面有一点不爽,对不?
因为我的可执行程序 (add_executable) 占据了 hello 这个名字,所以 add_library 就不
能使用这个名字了
然后,我们取了个 libhello 的名字,这将导致生成的库为 libhello.lib(
liblibhello.a) ,很不爽
想生成 hello.lib( libhello.a) 怎么办 ?
添加一行
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
就可以了
13.4 例子四
在前面,我们成功地使用了库,可是源代码放在同一个路径下,还是不太正规,怎么办
呢?分开放呗
我们期待是这样一种结构 +
|
+--- CMakeList.txt
+--+ src/
| |
| +--- main.c
| /--- CMakeList.txt
|
+--+ libhello/
| |
| +--- hello.h
| +--- hello.c
| /--- CMakeList.txt
|
/--+ build/
哇,现在需要 3 CMakeList.txt 文件了,每个源文件目录都需要一个,还好,每一个都不
是太复杂
顶层的 CMakeList.txt 文件
project(HELLO)
add_subdirectory(src)
add_subdirectory(libhello)
src 中的 CMakeList.txt 文件
include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(APP_SRC main.c)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
libhello 中的 CMakeList.txt 文件
set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
恩,和前面一样,建立一个 build 目录,在其内运行 cmake
然后可以得到
build/src/hello.exe
build/libhello/hello.lib
回头看看,这次多了点什么,顶层的 CMakeList.txt 文件中使用 add_subdirectory 告诉
cmake 去子目录寻找新的 CMakeList.txt 子文件
src CMakeList.txt 文件中,新增加了 include_directories ,用来指明头文件所在的路
径。
13.5 例子五
前面还是有一点不爽:如果想让可执行文件在 bin 目录,库文件在 lib 目录怎么办?
就像下面显示的一样:
+ build/
|
+--+ bin/
| |
| /--- hello.exe
|
/--+ lib/
|
/--- hello.lib
一种办法:修改顶级的 CMakeList.txt 文件
project(HELLO)
add_subdirectory(src bin)
add_subdirectory(libhello lib)
不是 build 中的目录默认和源代码中结构一样么,我们可以指定其对应的目录在 build 中的
名字。
这样一来: build/src 就成了 build/bin 了,可是除了 hello.exe ,中间产物也进来了。还不是
我们最想要的。
另一种方法:不修改顶级的文件,修改其他两个文件
src/CMakeList.txt 文件
include_directories(${PROJECT_SOURCE_DIR}/libhello)
#link_directories(${PROJECT_BINARY_DIR}/lib)
set(APP_SRC main.c)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
libhello/CMakeList.txt 文件
set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
13.6 例子六
在例子三至五中,我们始终用的静态库,那么用动态库应该更酷一点吧。 试着写一下
如果不考虑 windows 下,这个例子应该是很简单的,只需要在上个例子的
libhello/CMakeList.txt 文件中的 add_library 命令中加入一个 SHARED 参数:
add_library(libhello SHARED ${LIB_SRC})
可是,我们既然用 cmake 了,还是兼顾不同的平台吧,于是,事情有点复杂:
修改 hello.h 文件
#ifndef DBZHANG_HELLO_
#define DBZHANG_HELLO_
#if defined _WIN32
#if LIBHELLO_BUILD
#define LIBHELLO_API __declspec(dllexport)
#else
#define LIBHELLO_API __declspec(dllimport) #endif
#else
#define LIBHELLO_API
#endif
LIBHELLO_API void hello(const char* name);
#endif //DBZHANG_HELLO_
修改 libhello/CMakeList.txt 文件
set(LIB_SRC hello.c)
add_definitions("-DLIBHELLO_BUILD")
add_library(libhello SHARED ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
恩,剩下来的工作就和原来一样了。
14 CMake 的局限性
世界上没有完美的东西。 CMake 也有其局限性:
- CMake 并不遵守 GNU 规则。这使得 CMake 对一些开源软件的支持不够。例如,
CMake 生成出的工程在 Linux 下不支持 make uninstall
- CMake 和其他编译系统会打架。处理起来不容易。例如,如果不用 Qt 自带的
QMake ,而是用 CMake 去编译 Qt 工程,那是一件费时费力的事情。
- CMake 不会认识开发者在 IDE 中新增加的文件。必须通过修改 CMakeLists.txt ,才
能让 CMake 知道有新的文件。
15 常用网络资源
15.1 CMake 文档
http://www.cmake.org/cmake/help/v2.8.8/cmake.html
15.2 CMake Wiki
http://www.cmake.org/Wiki/CMake 15.3 CMake 入门
http://zh.wikibooks.org/wiki/CMake_%E5%85%A5%E9%96%80
16 附录
引用资源列表如下。时间仓促,难免有遗漏。如果您发现我引用了你的文章请告知。如果
您不希望您的文章被引用也请告知。可以到我的博客留言
http://blog.csdn.net/dbzhang800/article/details/6314073
http://tzc.is-programmer.com/show/476.html
http://blog.csdn.net/vagrxie/article/details/4743484
http://www.cs.swarthmore.edu/~adanner/tips/cmake.php
http://www.cnblogs.com/doujiu/archive/2009/11/04/1596155.html
http://blog.csdn.net/onion_autotest/article/details/7222954
http://www.cnblogs.com/coderfenghc/archive/2013/01/20/2846621.html
http://blog.csdn.net/gubenpeiyuan/article/details/8667279
http://name5566.com/1795.html
http://blog.sina.com.cn/s/blog_9ce5a1b501015avz.html
http://nullget.sourceforge.net/?q=node/94
http://blog.csdn.net/gubenpeiyuan/article/details/8667035
http://blogs.gnome.org/swilmet/2012/09/05/switch-from-cmake-to-autotools/
http://tech.uc.cn/?p=914

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1417033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营29期|day32 任务以及具体安排

第八章 贪心算法 part02 122.买卖股票的最佳时机II // 贪心思路 class Solution {public int maxProfit(int[] prices) {int result 0;for (int i 1; i < prices.length; i) {result Math.max(prices[i] - prices[i - 1], 0);}return result;} } 思路&#xff1a;将股票问…

美赛注意事项

2024年1月27日 &#xff1a; 赖维杰 同学分享 1、最后的展现必须要漂亮&#xff08;绘图、呈现&#xff09; 李维情 西北建模王 论文位&#xff08;核心&#xff09;必须清楚建模位、编程位知道做了些什么 常见模型&#xff1a; 1、看真题&#xff0c;读往年论文&#xff0c;选…

一、对人工智能大模型了解与认知

黑8说 月黑风高&#xff0c;乌云密布&#xff0c;树木低垂&#xff0c;黯淡沉闷。这黎明前的风暴&#xff0c;预示着新时代的变革即将到来。 在一个8线小城市的办公室中 黑8对主任说&#xff1a; 世界上有男人、女人、人妖&#xff0c;米国有1/3男&#xff0c;2/3女…&#xff…

100天精通鸿蒙从入门到跳槽——第16天:ArkTS条件渲染使用教程

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通Golang》 — Go语言学习之旅!《100天精通鸿蒙》 — 从Web/安卓到鸿蒙大师!100天…

基于springboot游戏分享网站源码和论文

网络的广泛应用给生活带来了十分的便利。所以把游戏分享管理与现在网络相结合&#xff0c;利用java技术建设游戏分享网站&#xff0c;实现游戏分享的信息化。则对于进一步提高游戏分享管理发展&#xff0c;丰富游戏分享管理经验能起到不少的促进作用。 游戏分享网站能够通过互…

csp----寻宝!大冒险!

题目描述&#xff1a; AC代码如下&#xff1a; /*思路&#xff1a; 把A变成小块 因为B是A里的一部分 通过把A变成小块 去寻找B这样速度更快 如果AB,BA&#xff0c;说明找到了。 */#include <iostream> #include <cstring> #include <algorithm> #include …

从零开始做题:逆向 ret2shellcode orw

1.题目信息 BUUCTF在线评测 下载orw时防病毒要关闭 2.题目分析 orw是open、read、write的简写。有时候binary会通过prctl、seccomp进行沙箱保护&#xff0c;并不能getshell。只能通过orw的方式拿到flag。 fdopen&#xff08;‘./flag’); # 打开flag文件&#xff0c;得到fd…

从零开始做题:逆向 ret2libc warmup

1.题目信息 warmup.c //gcc -fno-stack-protector -no-pie -z execstack warmup.c -o warmup #include <stdio.h>void init_proc(){setbuf(stdout, NULL);setbuf(stdin, NULL);setbuf(stderr, NULL); }int main(void) {char buf[0x100];init_proc();puts("Hello C…

burp靶场--CSRF

burp靶场–CSRF https://portswigger.net/web-security/csrf#what-is-csrf ### 什么是 CSRF&#xff1f; 跨站请求伪造&#xff08;也称为 CSRF&#xff09;是一种 Web 安全漏洞&#xff0c;允许攻击者诱导用户执行他们不打算执行的操作。它允许攻击者部分规避同源策略&#…

基于STM32的SDIO读写SD卡的设计与实现

基于STM32微控制器的SDIO&#xff08;Secure Digital Input Output&#xff09;读写SD卡的设计和实现&#xff0c;可以分为硬件设计和软件实现两个部分。下面将对这两个部分进行详细说明。 ✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术同步精进 ❤欢迎…

模拟量两线制4-20mA隔离变送器全家桶

定义&#xff1a;是指输入与输出的两根线的模拟量测量信号的设备&#xff0c;该设备的优点是无需要工作电源&#xff0c;产品在安装过程中节约了现场布线的成本&#xff0c;用电量成本 模拟量两线制4-20mA隔离变送器全家桶 小体积模拟量两线制4-20mA隔离变送器系列型号&#xf…

Linux篇:线程

一、线程概念&#xff1a;是进程内的一个执行分支&#xff0c;线程的执行粒度要比进程要细。 1、Linux中线程该如何理解&#xff1a; ①在Linux中&#xff0c;线程在进程“内部”执行&#xff0c;线程在进程的地址空间中进行。任何执行流要执行&#xff0c;都要有资源&#xf…

【MQ02】基础简单消息队列应用

基础简单消息队列应用 在上一课中&#xff0c;我们已经学习到了什么是消息队列&#xff0c;有哪些消息队列&#xff0c;以及我们会用到哪个消息队列。今天&#xff0c;就直接进入主题&#xff0c;学习第一种&#xff0c;最简单&#xff0c;但也是最常用&#xff0c;最好用的消息…

【书籍分享 • 第一期】基于GPT-3、ChatGPT、GPT-4等Transformer架构的自然语言处理

文章目录 一、内容简介二、前言2.1 Transformer 模型标志着AI 新时代的开始2.2 Transformer 架构具有革命性和颠覆性2.3 Google BERT 和OpenAI GPT-3 等Transformer 模型将AI 提升到另一个层次2.4 本书将带给你的“芝士”2.5 本书面向的读者 三、本书内容简介3.1 第一章3.2 第二…

看了《如果奔跑是我的人生》,你有感触么?

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 亲爱的&#xff0c;你知道吗&#xff1f;今年的国产剧市场好像…

[SpingBoot] 3个扩展点

初始化器ApplicationContextInitializer监听器ApplicationListenerRunner: Runner的一般应用场景就是资源释放清理或者做注册中心, 因为执行到Runner的时候项目已经启动完毕了, 这个时候可以注册进注册中心。 文章目录 1.初始化器ApplicationContextInitializer2.监听器Applica…

JVM-字节码文件的组成

Java虚拟机的组成 Java虚拟机主要分为以下几个组成部分&#xff1a; 类加载子系统&#xff1a;核心组件类加载器&#xff0c;负责将字节码文件中的内容加载到内存中。 运行时数据区&#xff1a;JVM管理的内存&#xff0c;创建出来的对象、类的信息等等内容都会放在这块区域中。…

面了中邮消金算法岗、开水团数据挖掘岗,做个系统性总结

最近技术群的同学&#xff0c;分享了面试数据挖掘/算法岗(实习)的经验。 今天整理后分享给大家&#xff0c;如果你对这块面试感兴趣&#xff0c;可以文末加入我们的面试、技术群 1、中邮消费金融AI算法工程师 面试官是nlp方向的&#xff0c;主要是问nlp相关 首先自我介绍 …

设计模式:简介及基本原则

简介 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问&#xff0c;设计模式于己于他人于系统都是多赢的&#xff0c;设计模式使代码编制真正工程化&#xff…

基于springboot校园台球厅人员与设备管理系统源码和论文

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括校园台球厅人员与设备管理系统的网络应用&#xff0c;在外国管理系统已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。校园台球厅人员与设备管理系统具…