Linux工具癖程序员

CMake 教程

2017-07-02  本文已影响2192人  LGmark

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模块

#ifndef  HELLO_H
#define  HELLO_H

void Hello_Print(void);

#endif
#include "hello.h"

#include <stdio.h>

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

aux_source_directory(. DIR_HELLO_SRC)

add_library(hello_lib ${DIR_HELLO_SRC})

3.编写world模块

#ifndef  WORLD_H
#define  WORLD_H

void World_Print(void);

#endif
#include "world.h"

#include <stdio.h>

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

aux_source_directory(. DIR_WORLD_SRC)

add_library(world_lib ${DIR_WORLD_SRC})

4.编写主模块

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

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

    return 0
}
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:指定文件链接库文件

上一篇下一篇

猜你喜欢

热点阅读