CMake 实践指南

CMake

一、单个源文件的编译

//main.c
#incldue<stdio.h>
int main()
{
    printf("Hello World!/n");
    return 0;
}

在main.c相同目录下再编写一个CMakeLists.txt文件,内容如下:

project(HELLO)
set(SRC_LIST main.c)
add_executable(hello ${SRC_LIST})

同时,在相同目录下创建一个build子文件夹,用来进行外部编译(为什么这么做?兄弟,看后面就知道了)
进入build文件夹,调用cmake:

$ cmake ..
$ make

执行完编译命令之后,会在build文件中生成一系列文件,其中最重要的是一个名叫hello的可执行文件。

$ ./hello

继续调用该文件即可看到hello world!
当前的目录结构:

+-- main.c
+-- CMakeLists.txt
+-- /build
    +--hello.exe

现在来看一下之前CMakeLists.txt中的内容:

project(HELLO)
set(SRC_LIST main.c)
add_executable(hello ${SRC_LIST})

第一行的project不是强制性的,但是最好始终都加上。

同时,cmake会自动定义两个变量:
PROJECT_BINARY_DIR
PROJECT_SOURCE_DIR
如果不做特殊声明,则这两个变量是相等的。可以通过语句:
message(“This is source dir :” ${PROJECT_SOURCE_DIR})
来显示PROJECT_SOURCE_DIR的默认目录。
使用
使用命令用来设置变量。
使用xecutable**则告诉cmake生成一个可执行文使用

二、多文件编译

通常来说,一个大型项目不会只有一个main.c文件,还会包含各种头文件,以及库文件。
现在将原来的main.c拆分成三个文件

//hello.h 头文件
void hello(const char * name);
//hello.c
#include<stdio.h>
#include"hello.h"
void hello(const char * name)
{   
    printf("Hello %s!\n",name);
}
//main.c
#include"hello.h"
int main()
{
    hello("World!");
    return 0;
}

然后准备CMakeLists.txt文件

project(HELLO)
set(SRC_LIST main.c)
message("This is PROJECT_BINARY_DIR :"  ${PROJECT_BINARY_DIR})
message("This is PROJECT_SOURCE_DIR :"  ${PROJECT_SOURCE_DIR})
add_executable(hello ${SRC_LIST})

按照之前的编译命令,同样在build中调用cmake。很简单,没什么特别的。
这时整个工程的目录结构变成了:

+-- main.c
+-- hello.h
+-- hello.c
+-- /build
    +-- 中间产物
    +-- hello.exe

想象一下,如果没有创建build子文件夹,直接在根部目下进行内部编译,编译之后生成的各种奇奇怪怪的文件将会淹没自己的源代码。

扫描二维码关注公众号,回复: 3233759 查看本文章

三、生成一个静态库,链接该库

现在将hello.c生成一个静态库。
修改CMakeLists.txt文件如下:

project(HELLO)
set(LIB_SRC hello.c)
set(APP_SRC main.c)
add_library(libhello ${LIB_SRC})
add_executable(hello ${APP_SRC})
target_link_libraties(hello libhello)

相比之前,添加了一个新的目标libhello,并将其链接到hello.exe
同样在build目录中进行编译
现在的目录结构变为

+-- main.c
+-- hello.h
+-- hello.c
+-- CMakeLists.txt
+-- /build    
    +-- 中间产物
    +-- hello.exe
    +-- libhello.lib

四、将源文件、库文件、头文件放在不同的文件夹中

现在为根目录下的源文件、头文件以及库文件建立文件夹,使之看起来更像一个工程。这时需要为每一个文件夹都配置一个CMakeLists.txt文件。

为各个源代码创建文件夹之后的工程目录如下:

+-- CMakeLists.txt
+-- /src
    +-- main.c
    +-- CMakeLists.txt
+-- /libhello
    +-- hello.c
    +-- hello.h
    +-- CMakeLists.txt
+-- /build

根目录下的CMakeLists.txt文件修改为:

project(HELLO)
add_subdirectory(src bin)
add_subdirectory(libhello lib)

src中的CMakeLists.txt

include_directories(${PROJECT_SOURCE_DIR/libhello})
set(APP_SRC main.c)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)

libhello中的CMakeLists.txt

set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set_target_propeties(libhello PROPERTIES OUTPUT_NAME "hello")

在build目录中调用cmake,可以得到:

+-- /build
    +-- /binhttps://blog.csdn.net/uxyheaven/article/details/49253757
        +-- hello.exe
        +-- 中间产物
    +-- /lib
        +-- hello.lib
        +-- 中间产物

为了让bin、lib目录中只有.exe与.lib文件,进行如下修改:
src文件夹下的CMakeLists.txt:

include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(APP_SRC main.c)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}\bin)
add_executable(hello ${APP_SRC})

hellolib下的CMakeLists.txt

set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}\lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

五、使用动态库

修改头文件为:

对_
对_
#if defined _WIN32
#if LIBHELLO_BUILD
#define LIBHELLO_API_declspec(dllexport)
#else
#define LIBHELLO_API_declspec(dllimport)
#endif
#else
#define LIBHELLO_API
#endif对
LI对d hello(const char * name);
#endif对

修改libhello下的CMakeLists.txt文件为:

set(LIB_SRC hello.c)
add_definitions("-DLIBHELLO_BUILD")
add_library(libhello SHARED ${LIB_SRC})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

CMake基本语法与命令

通过以上例子可以了解cmake的基本使用。下面讲解一下语法和常用命令。

简单语法

  • 注释
  • 命令语法
    command(arg1 arg2 …)
  • 控制流结构
  • 正则表达式

部分常用命令

INCLUDE_DIRECTORIES(“dir1” “dir2”…)
头文件路径

LINK_DIRECTORIES(“dir1” “dir2”)
库文件路径

ADD_LIBRARY( [name] [STATIC|SHARED|MODULE] [source1] [source2 …])

变量

工程路径:

工程的顶层目录

CMAKE_SOURCE_DIR
PROJECT_SOURCE_DIR
projectname_SOURCE_DIR

工程编译发生的目录

CMAKE_BINARY_DIR
PROJECT_BINARY_DIR
projectname——BINARY_DIR
如果是in source编译,则与工程的顶级目录相同,如果是out of source编译,则指得是工程编译发生的目录

猜你喜欢

转载自blog.csdn.net/weixin_42749767/article/details/82413951