简单记录一下在windows环境下使用cmake构建工程
任务
- cmake一个工程
- 静态库和动态库的构建与安装
- 外部共享库和头文件的使用
前期准备
先找一个路径 [D:\DamonWS\STUDY\4-5-6-Linux\CMAKE] 建立如下code1
code2
code3
三个文件夹
D:\DamonWS\STUDY\4-5-6-Linux\CMAKE> tree
.
├── code1
├── code2
└── code3
CMake一个工程
代码工程在目录下的code1文件夹
1、步骤一,写好C代码
先在code1
下创建一个src
文件夹,随后创建fun.c
fun.h
main.c
文件
fun.c
中的内容
#include "stdio.h"
int add(int a,int b)
{
int c = a+b;
return (c);
}
fun.h
中的内容
#ifndef _FUN_H_
#define _FUN_H_
int add(int a,int b);
#endif
main.c
中的内容
#include "stdio.h"
#include <stdlib.h>
#include "fun.h"
int main(int argc, char* argv[])
{
printf("main >> hello world !\n");
if(argc < 3)
{
printf("Usage: %s input error\n", argv[0]);
return -1;
}
int a = atoi(argv[1]); //取传入参数1
int b = atoi(argv[2]); //取传入参数2
int c = add(a,b); //调用函数
printf("main >> c=%d\n",c);
return 0;
}
2、步骤二 写CMakeLists.txt
在code1/
下创建一个CMakeLists.txt
文件,里面的内容如下
cmake_minimum_required (VERSION 3.0)
project(DEMO)
ADD_SUBDIRECTORY(src bin) #将src子目录加入工程并指定编译输出(包含编译中间结果)路径为bin目录
在code1/src/
下也创建一个CMakeLists.txt
文件,里面的内容如下
cmake_minimum_required (VERSION 3.0) #设置cmake最小版本
project(DEMO) # 设置项目名称
message(STATUS "This is BINARY dir " ${DEMO_BINARY_DIR})
message(STATUS "This is SOURCE dir "${DEMO_SOURCE_DIR})
# 查找C编译器路径并设置
find_program(CMAKE_C_COMPILER NAMES gcc clang PATHS /usr/bin /usr/local/bin)
# 如果找不到C编译器,则报错并退出
if(NOT CMAKE_C_COMPILER)
message(FATAL_ERROR "Cannot find a C compiler. Please make sure it is installed or set the correct path.")
endif()
# 输出找到的C编译器路径
message(STATUS "C compiler: ${CMAKE_C_COMPILER}")
include_directories(./) # build中添加包含目录 ./表示当前目录
aux_source_directory(. DIR_SRCS) # 查找指定目录下的所有源文件,然后将结果存进指定变量名 . 表示当前目录
add_executable(Demo ${DIR_SRCS}) # 指定生成目标
创建好的文件树
D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code1> tree
.
├── CMakeLists.txt
└── src
├── CMakeLists.txt
├── fun.c
├── fun.h
└── main.c
步骤三 外部编译
cd D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code1> #进入工作目录
mkdir build #创建build文件夹,将编译生成的中间文件集中保存
cd build #进入build目录
cmake .. -G "Unix Makefiles" #..表示取去上级目录cmake(因为当前在build目录) -G "Unix Makefiles" 是为了在windows下可生成 类Unix 的makefile
make #编译
最终在bin/
目录生成了Demo.exe
的可执行程序
步骤4 执行可执行程序
D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code1\build> .\bin\Demo.exe 3 4
输出:
main >> hello world !
main >> c=7
静态库和动态库的构建与安装
代码工程在目录下的code2
文件夹下
任务:
1,建立一个静态库和动态库,提供DrvAdd()
函数供其他程序编程使用,实现加法计算
2,安装头文件与共享库。
静态库和动态库的区别
- 静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”。
- 静态库在编译时会直接整合到目标程序中,编译成功的可执行文件可独立运行
- 动态库在编译时不会放到连接的目标程序中,即可执行文件无法单独运行。
静态库和动态库的构建
切换到code2/
,准备如下文件
D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code2> tree
.
├── CMakeLists.txt
└── src
├── CMakeLists.txt
├── DrvFun.c
└── DrvFun.h
DrvFun.h
中的内容
#ifndef _DRVFUN_H_
#define _DRVFUN_H_
int DrvAdd(int a ,int b);
#endif
DrvFun.c
中的内容
#include "stdio.h"
int DrvAdd(int a,int b)
{
int c = a+b;
printf("DrvAdd > C=%d",c);
return c;
}
项目外层CMakeList.txt
内容
cmake_minimum_required(VERSION 3.0)
PROJECT(DRVFUN)
ADD_SUBDIRECTORY(src)
src/
中CMakeLists.txt
中的内容
SET(LIBDRVFUN_SRC DrvFun.c)
ADD_LIBRARY(DrvFun SHARED ${LIBDRVFUN_SRC}) #生成动态库
ADD_LIBRARY(DrvFun_static STATIC ${LIBDRVFUN_SRC}) #生成静态库
SET_TARGET_PROPERTIES(DrvFun_static PROPERTIES OUTPUT_NAME "DrvFun") #改名DrvFun
# 动态库版本号
SET_TARGET_PROPERTIES(DrvFun PROPERTIES VERSION 1.2 SOVERSION 1) #VERSION 指代动态库版本,SOVERSION 指代 API 版本。
安装共享库和头文件
将以下字段加入到上述的CMakeLists.txt
尾部
INSTALL(TARGETS DrvFun LIBRARY DESTINATION bin) #安装动态库到 bin/
INSTALL(TARGETS DrvFun_static ARCHIVE DESTINATION static) #安装静态库到 static/
INSTALL(FILES DrvFun.h DESTINATION include) #DrvFun.h文件移到include/
外部编译
cd D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code2\
mkdir build
cd build
#安装到指定路径 -DCMAKE_INSTALL_PREFIX
cmake -DCMAKE_INSTALL_PREFIX=D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code2\ .. -G "Unix Makefiles"
make
make install
完成后的目录树
.
├── bin
├── build
├── include
├── lib
├── src
├── static
└── CMakeLists.txt
外部共享库和头文件的使用
代码工程在目录下的code3/
文件夹下
任务:
1,编写一个程序使用我们上一节构建的共享库
2,确认上一节安装保存的头文件位置:code2/include
,库位置:静态库code2/static
动态库 code2/bin
工程文件准备
切换到code3/
,准备如下文件
tree
.
├── CMakeLists.txt
└── src
├── CMakeLists.txt
└── main.c
main.c
中的内容
#include "stdio.h"
#include "stdlib.h"
#include <DrvFun.h>
int main(int argc, char* argv[])
{
printf("\nmain >> hello world !");
if(argc < 3)
{
printf("Usage: %s input error\n", argv[0]);
return -1;
}
int a = atoi(argv[1]);
int b = atoi(argv[2]);
int c = DrvAdd(a,b);
printf("\nmain >> c=%d",c);
return 0;
}
项目外层CMakeList.txt
内容
cmake_minimum_required(VERSION 3.0)
PROJECT(USEDRV)
ADD_SUBDIRECTORY(src)
src/
中CMakeLists.txt
中的内容
CMAKE_MINIMUM_REQUIRED( VERSION 3.0 )
INCLUDE_DIRECTORIES(D:\\DamonWS\\STUDY\\4-5-6-Linux\\CMAKE\\code2\\include) #引入头文件 路径\\双斜杠写法防止 \d \s路径报错
LINK_DIRECTORIES(D:\\DamonWS\\STUDY\\4-5-6-Linux\\CMAKE\\code2\\static) #连接库文件
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main libDrvFun.a) #链接静态库
外部编译
cd D:\DamonWS\STUDY\4-5-6-Linux\CMAKE\code3\
mkdir build
cd build
cmake .. -G "Unix Makefiles"
make #编译
执行可执行文件
.\src\main.exe 3 4
输出:
main >> hello world !
main >> c=7
【感谢】CMake第一、二、三、四、五、课
【感谢】 set_target_properties 常见属性以及获取target 属性
【感谢】windows make 报错