Cmake之CMakeLists.txt

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013896064/article/details/82874152

        我们知道makefile是在Linux编译c或者c++代码的时候的一种脚本文件,但是每一个功能都要写一个makefile文件,这样如果这个工程很大,而且相关性比较强的话,makefile的书写就会变得相对繁琐,更要命的是如果以后需要添加新的功能或者是新人需要修改功能的话,看起来就会特别麻烦;因为介于此,cmake的出现就是为了解决这样的问题,cmake的入门相当容易,而且管理也特别方便简单,那我们开始吧。

        cmake的所有语句都写在一个CMakeLists.txt的文件中,CMakeLists.txt文件确定后,直接使用cmake命令进行运行,但是这个命令要指向CMakeLists.txt所在的目录,cmake之后就会产生我们想要的makefile文件,然后再直接make就可以编译出我们需要的结果了。更简单的解释就是cmake是为了生成makefile而存在,这样我们就不需要再去写makefile了,只需要写简单的CMakeLists.txt即可。

cmake的执行流程很简单,我们的重点是如何编写CMakeLists.txt文件呢,我们通过例子来学习cmake的语法。

例子从这篇文章中学习http://blog.csdn.net/dbzhang800/article/details/6314073,大致如下:

1、一个单文件的简单的例子

文件名字为main.c 内容如下:

#include <stdio.h>
int main()
{
    printf("Hello World Test!\n");
    return 0;
}

CMakeLists.txt文件内容如下:

project(hello_jelly)
set(APP_SRC main.c)
add_executable(${PROJECT_NAME} main.c)

#print message
message(${PROJECT_SOURCE_DIR})

解释代码:

第一个行project不是强制性的,最好加上,这会引入两个变量:

HELLO_BINARY_DIR, HELLO_SOURCE_DIR

同时也会定义两个等价的变量:

PROJECT_BINARY_DIR, PROJECT_SOURCE_DIR

外部编译要时刻区分这两个变量对应的目录

可以通过message进行输出

message(${PROJECT_SOURCE_DIR})

set 命令用来设置变量

add_exectuable 告诉工程生成一个可执行文件。

add_library 则告诉生成一个库文件。

CMakeList.txt 文件中,命令名字是不区分大小写的,而参数和变量是大小写相关的。

然后将以上两个文件放在统一目录下面,注意编译产生时候分为两种,一种是直接在当前源码目录执行cmake命令#cmake ./,但是这样会在当前目录下产生很多临时文件和目录,另一种方式就是在当前目录新建一个build目录,然后我门进入到build目录,执行命令cmake ../,这样产生的所有临时文件都会生成在build目录下,而不影响源码目录的代码,此处我们采用第二种方法。我们进入到build目录,执行命令#cmake ../,然后在当前目录可以看到文件如下

drwxrwxr-x 3 zqq zqq 4096 9月  28 17:12 CMakeFiles
-rw-rw-r-- 1 zqq zqq  993 9月  28 17:12 cmake_install.cmake
-rw-rw-r-- 1 zqq zqq 5479 9月  28 17:12 Makefile

最后再在此目录执行make即可生成相应的可执行程序。

2、多个源文件的操作

hello.h头文件内容如下

#ifndef JELLYHELLO
#define JELLYHELLO
void hello(const char* name);
#endif

hello.c文件内容

#include <stdio.h>
#include "hello.h"

void hello(const char* name)
{
    printf("Hello my name is %s\n",name);
}

main.c文件内容如下

#include <stdio.h>
#include "hello.h"

int main()
{
    printf("Hello World Test!\n");
    hello("jelly");
    return 0;
}

然后是CMakeLists.txt文件

project(hello_jelly)
set(APP_SRC main.c hello.c)
add_executable(${PROJECT_NAME} ${SRC_LIST})

#print message
message(${PROJECT_SOURCE_DIR})

然后保存使用上面的方法进行cmake和make,就可以生成需要的可执行文件

3、将hello.c生成一个库来调用

如果将hello生成成一个库来调用的话只需要在2的基础上修改一下CMakeLists.txt文件再进行编译即可

修改的CMakeLists.txt如下:

project(hello_jelly)
set(LIB_SRC hello.c)
set(APP_SRC main.c)
add_library(hello ${LIB_SRC})
add_executable(${PROJECT_NAME} ${APP_SRC})
target_link_libraries(${PROJECT_NAME} hello)

#print message
message(${PROJECT_NAME})

相比之下,我们只是添加了一个新的目标hello库,并将其链接到我们的demo程序

然后同样的方法进行cmake和make进行编译

4、工程分类文件夹编译

在前面,我们成功的使用了库,但是源代码都是在同一个路径下面,这样如果到时候代码量比较大的话,可能就会分类,形成多个文件夹,这样我们需要把代码分开放,此时我们需要些三个CMakeLists.txt文件,目录结构如下

drwxrwxr-x 2 zqq zqq 4096 9月  28 17:32 app
drwxrwxr-x 5 zqq zqq 4096 9月  28 17:12 build
-rw-rw-r-- 1 zqq zqq  487 9月  27 14:42 CMakeLists.txt
drwxrwxr-x 2 zqq zqq 4096 9月  28 17:19 libso

我们将main.c程序放在app目录下面,hello.c hello.h放在libso文件夹下面,然后该文件夹有一个CMakeLists.txt文件,app和libso文件夹下面也有CMakeLists.txt文件,这样就有三个CMakeLists.txt文件了,那么我们接下来来编辑这个三个文件吧。

首先是app文件夹的CMakeLists.txt

project(hello_jelly)
include_directories(${PROJECT_SOURCE_DIR}/../libso)

set(APP_SRC main.c)
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} helloso)

message(${PROJECT_SOURCE_DIR})

然后是libso文件夹的CMakeLists.txt,其中SHARED 表示是生成的动态库,如果把SHARED去掉的话就是生成静态库

project(helloso)

set(LIB_SRC hello.c)
add_library(${PROJECT_NAME} SHARED ${LIB_SRC})

最后是外面那个和app在同一目录下的CMakeLists.txt

cmake_minimum_required (VERSION 3.2)
project(jelly_cmake)

add_subdirectory(./app)
add_subdirectory(./libso)

其表示我们要到./app和./libso文件夹下面去寻找Cmake文件然后进行编译

最后我们在build目录下面去执行上面的命令编译即可编译出我们需要的可执行文件。

#cmake ../
#make

5、Cmake的install简单使用

我的理解cmake中的install其实就是一个将编译好的可执行文件或者是生成的库文件将它放到系统对应的位置,比如说可执行文件直接要放到bin目录下面,so库文件要放在对应的lib目录下面,我在上面的例子的基础上修改CMakeLists.txt文件,编辑完成后编译的步骤如下,就是多了个install步骤,这样我们就可以在Linux上面使用该执行文件,执行文件会去调用so库。

#cmake ../
#make
#make install

app目录修改的CMakeLists.txt如下:只是在之前的基础上加了最后install一行

project(hello_jelly)
include_directories(${PROJECT_SOURCE_DIR}/../libso)

set(APP_SRC main.c)
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME} helloso)

message(${PROJECT_SOURCE_DIR})

install(TARGETS ${PROJECT_NAME} DESTINATION bin)

libso目录修改的CMakeLists.txt如下:只是在之前的基础上加了最后install一行

project(helloso)

set(LIB_SRC hello.c)
add_library(${PROJECT_NAME} SHARED ${LIB_SRC})

install(TARGETS ${PROJECT_NAME} DESTINATION ../lib)

在此需要解释下这个路径问题,install(TARGETS ${PROJECT_NAME} DESTINATION bin)这句话的意思是安装TARGERS hello_jelly这个可执行文件到${CMAKE_INSTALL_PREFIX}/bin目录下面,我测试打印我的${CMAKE_INSTALL_PREFIX}路径是/usr/local路径,bin前面不能有/,否则会是绝对路径,它不再会去获取${CMAKE_INSTALL_PREFIX}路径,

综上所述,可执行文件安装的路径是:

/usr/local/bin/

so库文件的安装路径是:

/usr/local/../lib/

最后执行那三个命令就完了,此时你可以在你的Linux系统里面的任何目录执行./hello_jelly

注:如果执行make install的时候出现错误,可以加上sudo再次执行试试!!!

相应的源码参考链接如下:

源码demo下载地址

如果后续还有其他的理解,我再在此更新!!!

猜你喜欢

转载自blog.csdn.net/u013896064/article/details/82874152