学习记录所用。
1、简单介绍
CMakeLists.txt文件的编写比MakeFile文件的编写更加简单和容易理解。
CMakeLists.txt通过cmake命令生成MakeFile文件。
2、一个简单的例子
先建立一个简单的.c文件,hello.c
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
}
在.c文件所在目录的终端处使用下面的命令,进行 CMakeLists.txt文件编写。
vim CMakeLists.txt
按i键进入插入模式,输入下面的内容。
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
该命令设置了滞后使用cmake命令时所需的最小cmake版本号。
若CMakeLists.txt文件中使用了高版本特有的命令,会提醒版本不够的用户至少将cmake升级到多少版本。
PROJECT(HELLO)
该命令设置了项目命名。
ADD_EXECUTABLE(hello hello.c)
添加生成可执行文件,将hello.c生成可执行文件hello。
按ESC退出插入模式,输入:wq保存并返回完成CMakeLists.txt文件的编写。
这样一个最基本的CMakeLists.txt文件就建好了。
下面建一个build文件夹,将编译的中间产物以及结果放在里面。
mkdir build
进入build文件夹。
cd build
使用下面的指令,其中. .代表上一级文件夹,也就是hello.c和CMakeLists.txt文件所在文件夹。如果提示找不到cmake命令,根据提示安装即可。
cmake ..
make
Makefile文件被穿件,同时可执行文件也编译好了。可以看见有许多的中间文件,这就是创建一个新的文件夹build的原因。
在中断中运行生成的hello文件。
./hello
结果如下:
3、将主函数及库函数一起编译
下面建立三个文件main.c hello.c hello.h,程序如下:
main.c
// main.c
#include <stdio.h>
#include "hello.h"
int main(void)
{
hello("Blank");
}
hello.c
// hello.c
#include "hello.h"
int hello(const char* string)
{
printf("Hello, %s!\n", string);
}
hello.h
#ifndef __HELLO_H
#define __HELLO_H
int hello(const char* string);
#endif
同上建立一个CMakeLists.txt文件,并开始插入。
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
PROJECT(HELLO)
set 将hello.c给变量名LIB,add_library将main.c使用到的库生成LIBHELLO。
SET(LIB hello.c)
ADD_LIBRARY(LIBHELLO ${LIB})
这一步就比上一章节多了个中间环节。
SET(APP main.c)
ADD_EXECUTABLE(hello ${APP})
最后不要忘了将库和课编译文件链接起来。
TARGET_LINK_LIBRARIES(hello LIBHELLO)
下面就是建立一个文件夹生成Makefile文件和可编译文件。
mkdir build
cd build
cmake ..
make
生成后运行效果如下:
4、带上外部库
如果程序中使用了外部库,需要加上地址。
假如我们使用的是modbus库,下面的程序是使用chatgpt生成的一个程序,不需要知道具体写了什么,只要知道使用了一个modbus的外部库就行。
main.c
// main.c
#include <stdio.h>
#include <modbus.h>
#define SERVER_ID 1
#define ADDR_START 0
#define NB_REGS 10
int main()
{
modbus_t *ctx;
uint16_t tab_reg[NB_REGS];
int rc;
const char errno;
// 创建 Modbus 连接句柄
ctx = modbus_new_tcp("localhost", 502);
if (ctx == NULL) {
fprintf(stderr, "Unable to create Modbus context\n");
return -1;
}
// 设置从站地址
modbus_set_slave(ctx, SERVER_ID);
// 建立 Modbus 连接
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Modbus connection failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
// 读取寄存器的值
rc = modbus_read_registers(ctx, ADDR_START, NB_REGS, tab_reg);
if (rc == -1) {
fprintf(stderr, "Error reading registers: %s\n", modbus_strerror(errno));
modbus_close(ctx);
modbus_free(ctx);
return -1;
}
// 输出寄存器的值
printf("Registers:\n");
for (int i = 0; i < NB_REGS; i++) {
printf(" reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
// 向寄存器写入一个值
uint16_t value = 0xABCD;
rc = modbus_write_register(ctx, ADDR_START, value);
if (rc == -1) {
fprintf(stderr, "Error writing register: %s\n", modbus_strerror(errno));
modbus_close(ctx);
modbus_free(ctx);
return -1;
}
// 关闭 Modbus 连接
modbus_close(ctx);
modbus_free(ctx);
return 0;
}
在CMakeList.txt文件中如下设置:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
PROJECT(MODBUS_TEST)
INCLUDE_DIRECTORIES(/usr/include/modbus)
SET(APP main.c)
ADD_EXECUTABLE(myexe ${APP})
TARGET_LINK_LIBRARIES(myexe modbus)
只需要加上INCLUDE_DIRECTORIES()
命令即可,括号内为外部程序的地址。
我使用sudo apt-install libmodbus-dev
下载的modbus默认在/usr/include/modbus
文件夹下,因此括号内就放这个地址。
建立build文件夹,进行编译后运行结果如下:由于没有modbus连接,所以输出的就是预设的错误信息。