一。cmake简介
CMake是一个跨平台的编译、安装、测试以及打包工具;CMake不直接编译软件,而是结合原生构建系统来构建软件。
CMake配置文件是CMakeList.txt文件(每个源码文件夹下都要有一个),CMake根据配置文件再生成Unix的Makefile或VS的solution文件等。
Cmake旨在通过一个配置来解决不同平台编写不同编译配置文件的方法 cmake仅仅帮我们生成编译工程文件,最终编译靠
各自编译器
图解:
1》 cmake安装
yum -y install cmake
查看版本
[root@localhost rule]# cmake --version
cmake version 2.8.12.2
cmake官方向导 https://cmake.org/cmake-tutorial/
官方文档:https://cmake.org/documentation 老版本在最下面
最简单的配置文件
添加一个hello.c的源码
#include <stdio.h>
void main(){
printf("hello\n");
}
在当前目录下新建CMakeList.txt文件内容
#CMake最低版本号要求
cmake_minimum_required (VERSION 2.8)
#项目信息
project (demo)
#指定生成目标 参数1表示生成目标文件的名称 参数2表示源文件
add_executable(demo hello.c)
执行 (cmake 有cmakelist.txt文件的目录)
cmake .
执行完成后 发现当前目录下 生成了Makefile文件 使用make 命令就可以编译了
[root@localhost helloworld]# cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /root/vc/helloworld
[root@localhost helloworld]# make && ./demo
[100%] Built target demo
hello
二。cmake多目录实战
假设项目的目录结构为:
inc目录下为头文件a.h:
#include <stdio.h>
#include <stdlib.h>
int add(int p1,int p2);
void syso(char* c);
math目录下为 add方法的实现c文件 mmath.c 因为头文件不在同一个目录 所以gcc 指定 -I
#include "a.h"
int add(int p1,int p2){
return p1+p2;
}
utils目录包含了syso方法的实现syso.c
#include "a.h"
void syso(char* c){
printf(c);
}
根目录下有个 main.c 添加应用的入口main方法
#include "a.h"
void main(){
int number=add(111,333);
char str[25];
sprintf(str, "%d", number);
syso(str);
}
假设这里分别 将 mmath.c编译成动态库.so syso.c编程静态库 .a
math目录下添加一个 CMakeLists.txt文件
#设置输出的链接库的位置 PROJECT_BINARY_DIR是 cmake执行的目录 PROJECT_SOURCE_DIR是有
# CMakeLists.txt的目录 比如cmake .. 当前目录就是 PROJECT_BINARY_DIR 上一级目录就是
# PROJECT_SOURCE_DIR
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
include_directories (${PROJECT_SOURCE_DIR}/../inc)
#将某个文件编译成动态库
add_library(mmath SHARED mmath.c)
utils目录下添加一个 CMakeLists.txt文件
#设置输出的链接库的位置
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
include_directories (${PROJECT_SOURCE_DIR}/../inc)
#将某个文件编译成静态库
add_library(syso STATIC syso.c)
根目录下添加一个CMakeLists.txt文件 要求运行根目录自动调用子目录的
#CMake最低版本号要求
cmake_minimum_required (VERSION 2.8)
#项目信息
project (mydemo)
#定义编译时 包含头文件位置
include_directories (inc)
#生成时打印出消息
MESSAGE(STATUS "开始生成子目录math")
#cmake调用子目录 执行子目录的 CmakeLists.txt
add_subdirectory (math)
MESSAGE(STATUS "开始生成子目录utils")
add_subdirectory (utils)
#指定链接目标文件的目录
link_directories(${PROJECT_BINARY_DIR})
#定义一个变量 ALL_C 使用 ${变量名引用}
set(ALL_C main.c)
MESSAGE(STATUS "开始生成程序")
#指定生成目标
add_executable(mydemo ${ALL_C})
#指定 mydeo这个可执行文件依赖 syso和mmath两个动态链接库
target_link_libraries(mydemo syso)
target_link_libraries(mydemo mmath)
#-----------------------------
# 下面的代码仅用于学习命令
#-----------------------------
#-----执行命令 拿到系统版本 指定uname -r 将结果写入MY_HOST_SYSTEM_NAME变量
EXEC_PROGRAM(uname ARGS -s OUTPUT_VARIABLE MY_HOST_SYSTEM_NAME)
if(MY_HOST_SYSTEM_NAME STREQUAL "Linux")
message(STATUS "系统是:${MY_HOST_SYSTEM_NAME}")
endif()
#-----给INSTALL_STATIC_LIBRARIES定义个默认值 如果cmake ../ -DINSTALL_STATIC_LIBRARIES=OFF 没有带这个参数默认值就是ON 带了就是带了的值
OPTION(INSTALL_STATIC_LIBRARIES "Install static libraries",ON)
message(STATUS "输出是:${INSTALL_STATIC_LIBRARIES}")
#-----循环输出 0-5 步数是1
foreach(loop_var RANGE 0 5 1)
message(STATUS "循环输出是:${loop_var}")
endforeach(loop_var)
foreach(loop_var "zs" "ls")
message(STATUS "循环输出是:${loop_var}")
endforeach(loop_var)
#包含一个包含cmake语法的txt文件
include(a.txt)
#-----获取环境变量
set(MPATH $ENV{PATH})
message(STATUS "包含获取变量:${a} 环境变量 ${MPATH}")
#-----定义宏
MACRO(testMacro age)
set(age 11) #宏修改参数是无效的
message(STATUS "这是一个宏定义 参数是 ${age}")
endmacro(testMacro)
#调用宏
set(age 10)
testMacro(${age})
#-----定义函数
function(myage age])
set(age 11 PARENT_SCOPE) #函数内修改参数是无效的 调用方的值还是之前的值 必须加上PARENT_SCOPE才能修改
message(STATUS "这是一个函数定义 参数是 ${age}")
endfunction(myage)
set(age 10)
myage(${age})
#注意函数内部修改的值对外部无效 除非使用了引用修改值 PARENT_SCOPE
message(STATUS "age值: ${age}")
#-----get_filename_component 得到一个完整文件名中的特定部分。
GET_FILENAME_COMPONENT(MYDIR "c:/a/a.txt" DIRECTORY) #获取目录 结果 c:/a
message(${MYDIR})
GET_FILENAME_COMPONENT(MYDIR "c:/a/a.txt" EXT) #EXT获取后缀 txt路径(PATH),文件名(NAME),文件扩展名(EXT),去掉扩展名的文件名(NAME_WE),完整路径(ABSOLUTE),或者所有符号链接被解析出的完整路径(REALPATH)
message(${MYDIR})
因为运行cmake 会生成很多的临时文件为了 怕污染源代码 我们进入bin目录执行
[root@localhost bin]# cmake ../
CMake Warning (dev) in CMakeLists.txt:
Syntax Warning in cmake code at
/root/vc/cmake/CMakeLists.txt:33:59
Argument not separated from preceding token by whitespace.
This warning is for project developers. Use -Wno-dev to suppress it.
-- 开始生成子目录math
-- 开始生成子目录utils
-- 开始生成程序
-- 系统是:Linux
-- 输出是:OFF
-- 循环输出是:0
-- 循环输出是:1
-- 循环输出是:2
-- 循环输出是:3
-- 循环输出是:4
-- 循环输出是:5
-- 循环输出是:zs
-- 循环输出是:ls
-- 包含获取变量:1 环境变量 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
-- 这是一个宏定义 参数是 10
-- 这是一个函数定义 参数是 10
-- age值: 11
c:/a
.txt
-- Configuring done
-- Generating done
-- Build files have been written to: /root/vc/cmake/bin
[root@localhost bin]# make
Scanning dependencies of target mmath
[ 33%] Building C object math/CMakeFiles/mmath.dir/mmath.c.o
Linking C shared library ../libmmath.so
[ 33%] Built target mmath
Scanning dependencies of target syso
[ 66%] Building C object utils/CMakeFiles/syso.dir/syso.c.o
Linking C static library ../libsyso.a
[ 66%] Built target syso
Scanning dependencies of target mydemo
[100%] Building C object CMakeFiles/mydemo.dir/main.c.o
Linking C executable mydemo
[100%] Built target mydemo
[root@localhost bin]# ./mydemo