CMake 教程

1. 编译单目录工程

1.创建工程文件夹

mkdir hello #工程目录
cd hello
mkdir src   # 存放源代码的目录
mkdir build # 存放编译中间代码和目标代码的目录

2.进入src目录,编写一个main.c文件

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("hello world\n");
    return 0;
}

3.编写工程顶层目录的CMakeLists.txt

cmake_minumum_required(VERSION 2.6)

#指定项目名
project(hello)

#指定子目录
add_subdirectory(src)

4.编写子目录srcCMakeLists.txt

aux_source_directory(. SRC_LIST)

add_executable(hello ${SRC_LIST})

5.编译工程

1.进入build 目录
2.执行命令cmake ..创建Makefile
3.执行命令make编译工程
4.在build的子目录src生成了执行文件

2. 编译多目录工程

1.创建工程目录

mkdir hello # 工程目录
cd hello
mkdir src   # 存放源码目录
mkdir build # 存放编译产生的中间文件
cd src      
mkdir hello # 存放hello 模块
mkdir world # 存放world 模块

2.编写hello模块

  • 进入hello目录
  • 编写hello.h文件
#ifndef  HELLO_H
#define  HELLO_H

void Hello_Print(void);

#endif
  • 编写hello.c文件
#include "hello.h"

#include <stdio.h>

void Hello_Print(void)
{
    printf("hello ");
}

  • 编写CMakeLists.txt 文件
aux_source_directory(. DIR_HELLO_SRC)

add_library(hello_lib ${DIR_HELLO_SRC})

3.编写world模块

  • 进入world目录
  • 编写world.h文件
#ifndef  WORLD_H
#define  WORLD_H

void World_Print(void);

#endif
  • 编写world.c文件
#include "world.h"

#include <stdio.h>

void World_Print(void)
{
    printf("world");
}

  • 编写CMakeLists.txt 文件
aux_source_directory(. DIR_WORLD_SRC)

add_library(world_lib ${DIR_WORLD_SRC})

4.编写主模块

  • 进入src目录
  • 编写main.c 文件
#include "hello/hello.h"
#include "world/world.h"

int main(int argc, char **argv)
{
    Hello_Print();
    World_Print();

    return 0
}
  • 编写CMakeLists.txt 文件
add_source_directory(. DIR_SRC)

# 添加子目录
add_subdirectory(hello)
add_subdirectory(world)

# 执行文件
add_executable(hello_prj ${DIR_SRC})
target_link_libraries(hello_prj ello_lib world_lib)

5.编写顶层目录的CMakeLists.txt文件

cmake_minumum_required(VERSION 2.6)

project(hello_prj)

add_subdirectory(src)

3. 动态库和静态库的构建和使用

1.使用一个hello world工程来展开说明
项目结构

|-- CMakeLists.txt
|-- build
|-- include
|   |-- hello
|   |   `-- hello.h
|   `-- world
|       `-- world.h
|-- src
|   |-- CMakeLists.txt
|   |-- hello
|   |   `-- hello.c
|   `-- world
|       `-- world.c
`-- test
    |-- CMakeLists.txt
        `-- mytest.c

2.顶层目录CMakeLists.txt

 cmake_minimum_required(VERSION 2.6)
 
 project(helloworld)
 
 #设置库文件存放路径
 set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/lib)
 
 #设置执行文件存放路径
 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
 
 #获取当前目录及子目录(递归获取),添加到头文件搜索路径
 function(include_sub_directories_recursively root_dir)
     if (IS_DIRECTORY ${root_dir})               # 当前路径是一个目录吗,是的话就加入到包含目录
         message("include dir: " ${root_dir})
         include_directories(${root_dir})
     endif()
 
     file(GLOB ALL_SUB RELATIVE ${root_dir} ${root_dir}/*) # 获得当前目录下的所有文件,让如ALL_SUB列表中
     foreach(sub ${ALL_SUB})
         if (IS_DIRECTORY ${root_dir}/${sub})
             include_sub_directories_recursively(${root_dir}/${sub}) # 对子目录递归调用,包含
         endif()
     endforeach()
 endfunction()
 
 #项目的所有目录都为头文件搜索路径
 include_sub_directories_recursively(${PROJECT_SOURCE_DIR})
 
 #添加库文件搜索路径
 link_directories(
     ${PROJECT_SOURCE_DIR}/build/lib
     )

 #添加子目录
 add_subdirectory(src)
 add_subdirectory(test)

 #设置安装目录
 set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)


3.helloworld库的源代码
hello.h文件

#ifndef  HELLO_H
#define  HELLO_H

void Hello_Print(void);

#endif

hello.c文件

#include "hello/hello.h"

#include <stdio.h>

void Hello_Print(void)
{
    printf("hello ");
}

world.h文件

#ifndef  WORLD_H
#define  WORLD_H

void World_Print(void);

#endif

world.c文件

#include "world/world.h"

#include <stdio.h>

void World_Print(void)
{
    printf("world");
}

4.子目录src下的CMakeLists.txt

 #递归获取当前目录及子目录下的所有c文件
 file(GLOB_RECURSE c_files "*.c")
 
 #生成动态库和静态库
 add_library(helloworld_lib_shared  SHARED ${c_files})
 add_library(helloworld_lib_static STATIC ${c_files})
 
 #将动态库和静态库的名字设置为一致
 set_target_properties(helloworld_lib_shared PROPERTIES OUTPUT_NAME "helloworld")
 set_target_properties(helloworld_lib_static PROPERTIES OUTPUT_NAME "helloworld")
 
 #设置动态库版本
 set_target_properties(helloworld_lib_shared PROPERTIES VERSION 1.2 SOVERSION 1)
 
 #安装动态库和静态库
 INSTALL(TARGETS helloworld_lib_shared helloworld_lib_static
     LIBRARY DESTINATION lib
     ARCHIVE DESTINATION lib)
 
 #安装头文件
 INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)

5.mytest.c文件测试生成的库文件
mytest.c文件

#include "hello/hello.h"
#include "world/world.h"

#include <stdio.h>

int main(int argc, char **argv)
{
    Hello_Print();
    World_Print();

    printf("\n");
    return 0;
}

CMakeLists.txt文件

#递归获取所有当前目录及子目录下的C文件
file(GLOB_RECURSE c_files ./*.c)
  
#生成执行文件
add_executable(mytest ${c_files})
     
#链接外部库
target_link_libraries(mytest libhelloworld.so)

6.构建工程

1.进入目录build
2.执行命令: cmake ..
3.执行命令: make
4.执行命令: make install

4. 指定编译器和编译选项

1.CMAKE_C_COMPILER: 指定C编译器
2.CMAKE_CXX_COMPILTER:指定C++编译器
3.CMAKE_C_FLAGS: 指定C编译选项
4.CMAKE_CXX_FLAGS:指定C++编译选项
5.EXECUTABLE_OUTPUT_PATH: 指定执行文件存放目录
6.LIBRARY_OUTPUT_PATH: 指定库文件存放目录
7.CMAKE_BUILD_TYPE:指定build类型[Debug|Release]
8.BUILD_SHARED_LIBS: 指定默认库编译方式[OFF|ON]

上述内部变量使用说明:
1.CMakeLists.txt文件上使用set命令
2.cmake 命令中指定,如: cmake -DCMAKE_C_COMPILER=gcc

add_definitions:添加编译参数

5. 配置编译模块

6. CMake 常用变量和语句

1.include_directories:指定头文件搜索路径
2.link_directories:指定库文件搜索路径
3.add_subdirectory:添加子目录
4.target_link_libraries:指定文件链接库文件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • CMake学习 本篇分享一下有关CMake的一些学习心得以及相关使用。 本文目录如下: [1、CMake介绍] [...
    AlphaGL阅读 12,204评论 11 79
  • 注:首发地址 1. 前言 当在做 Android NDK 开发时,如果不熟悉用 CMake 来构建,读不懂 CMa...
    cfanr阅读 24,136评论 1 53
  • 1.安装 $sudo apt-get install cmake 2.示例:简单的文件目录 sample |—...
    荷包蛋酱阅读 29,604评论 0 15
  • cmake只是生层,能够生层.o之类文件语句的程序,而最终生成.o的还是make 爽一爽 (下面我将cmake生成...
    Myth52125阅读 6,443评论 0 2
  • 清晨 阳光穿过薄雾透过玻璃 散落在我的脸颊上 我的睫毛轻颤 听见你的拖箱轮与地面摩擦发出的声音 我迫不及待的起了身...
    长相厮阅读 674评论 0 0