转自:http://blog.csdn.net/dbzhang800/article/details/6314073

新工作中使用到了cmake,所以找点资料学习一下,这篇讲的确实不错,转过来保存一下,另外这一篇页不错的:http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/

看来不学习一下cmake是不行了,一点一点来吧,找个最简单的C程序,慢慢复杂化,试试看:

例子一

单个源文件 main.c

例子二

==>分解成多个 main.c hello.h hello.c

例子三

==>先生成一个静态库,链接该库

例子四

==>将源文件放置到不同的目录

例子五

==>控制生成的程序和库所在的目录

例子六

==>使用动态库而不是静态库

例子一

一个经典的C程序,如何用cmake来进行构建程序呢?

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

编写一个 CMakeList.txt 文件(可看做cmake的工程文件):

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

然后,建立一个任意目录(比如本目录下创建一个build子目录),在该build目录下调用cmake

  • 注意:为了简单起见,我们从一开始就采用cmake的 out-of-source 方式来构建(即生成中间产物与源代码分离),并始终坚持这种方法,这也就是此处为什么单独创建一个目录,然后在该目录下执行 cmake 的原因
cmake .. -G"NMake Makefiles"
nmake

或者

cmake .. -G"MinGW Makefiles"
make

即可生成可执行程序 hello(.exe)

目录结构

+
|
+--- main.c
+--- CMakeList.txt
|
/--+ build/
|
+--- hello.exe

cmake 真的不太好用哈,使用cmake的过程,本身也就是一个编程的过程,只有多练才行。

我们先看看:前面提到的这些都是什么呢?

CMakeList.txt

第一行 project 不是强制性的,但最好始终都加上。这一行会引入两个变量

  • HELLO_BINARY_DIR 和 HELLO_SOURCE_DIR

同时,cmake自动定义了两个等价的变量

  • PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR

因为是out-of-source方式构建,所以我们要时刻区分这两个变量对应的目录

可以通过message来输出变量的值

message(${PROJECT_SOURCE_DIR})

set 命令用来设置变量

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

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

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

cmake命令

cmake 命令后跟一个路径(..),用来指出 CMakeList.txt 所在的位置。

由于系统中可能有多套构建环境,我们可以通过-G来制定生成哪种工程文件,通过 cmake -h 可得到详细信息。

要显示执行构建过程中详细的信息(比如为了得到更详细的出错信息),可以在CMakeList.txt内加入:

  • SET( CMAKE_VERBOSE_MAKEFILE on )

或者执行make时

  • $ make VERBOSE=1

或者

  • $ export VERBOSE=1
  • $ make

例子二

一个源文件的例子一似乎没什么意思,拆成3个文件再试试看:

  • hello.h 头文件
#ifndef DBZHANG_HELLO_
#define DBZHANG_HELLO_
void hello(const char* name);
#endif //DBZHANG_HELLO_
  • 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;
}
  • 然后准备好CMakeList.txt 文件
project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})

执行cmake的过程同上,目录结构

+
|
+--- main.c
+--- hello.h
+--- hello.c
+--- CMakeList.txt
|
/--+ build/
|
+--- hello.exe

例子很简单,没什么可说的。

例子三

接前面的例子,我们将 hello.c 生成一个库,然后再使用会怎么样?

改写一下前面的CMakeList.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_libraries(hello libhello)

和前面相比,我们添加了一个新的目标 libhello,并将其链接进hello程序

然后想前面一样,运行cmake,得到

+
|
+--- main.c
+--- hello.h
+--- hello.c
+--- CMakeList.txt
|
/--+ build/
|
+--- hello.exe
+--- libhello.lib

里面有一点不爽,对不?

  • 因为我的可执行程序(add_executable)占据了 hello 这个名字,所以 add_library 就不能使用这个名字了
  • 然后,我们去了个libhello 的名字,这将导致生成的库为 libhello.lib(或 liblibhello.a),很不爽
  • 想生成 hello.lib(或libhello.a) 怎么办?

添加一行

set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

就可以了

例子四

在前面,我们成功地使用了库,可是源代码放在同一个路径下,还是不太正规,怎么办呢?分开放呗

我们期待是这样一种结构

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

哇,现在需要3个CMakeList.txt 文件了,每个源文件目录都需要一个,还好,每一个都不是太复杂

  • 顶层的CMakeList.txt 文件
project(HELLO)
add_subdirectory(src)
add_subdirectory(libhello)
  • src 中的 CMakeList.txt 文件
include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(APP_SRC main.c)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
  • libhello 中的 CMakeList.txt 文件
set(LIB_SRC hello.c)
add_library(libhello ${LIB_SRC})
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

恩,和前面一样,建立一个build目录,在其内运行cmake,然后可以得到

  • build/src/hello.exe
  • build/libhello/hello.lib

回头看看,这次多了点什么,顶层的 CMakeList.txt 文件中使用 add_subdirectory 告诉cmake去子目录寻找新的CMakeList.txt 子文件

在 src 的 CMakeList.txt 文件中,新增加了include_directories,用来指明头文件所在的路径。

例子五

前面还是有一点不爽:如果想让可执行文件在 bin 目录,库文件在 lib 目录怎么办?

就像下面显示的一样:

   + build/
|
+--+ bin/
| |
| /--- hello.exe
|
/--+ lib/
|
/--- hello.lib
  • 一种办法:修改顶级的 CMakeList.txt 文件
project(HELLO)
add_subdirectory(src bin)
add_subdirectory(libhello lib)

不是build中的目录默认和源代码中结构一样么,我们可以指定其对应的目录在build中的名字。

这样一来:build/src 就成了 build/bin 了,可是除了 hello.exe,中间产物也进来了。还不是我们最想要的。

  • 另一种方法:不修改顶级的文件,修改其他两个文件

src/CMakeList.txt 文件

include_directories(${PROJECT_SOURCE_DIR}/libhello)
#link_directories(${PROJECT_BINARY_DIR}/lib)
set(APP_SRC main.c)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)

libhello/CMakeList.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")

例子六

在例子三至五中,我们始终用的静态库,那么用动态库应该更酷一点吧。 试着写一下

如果不考虑windows下,这个例子应该是很简单的,只需要在上个例子的 libhello/CMakeList.txt 文件中的add_library命令中加入一个SHARED参数:

add_library(libhello SHARED ${LIB_SRC})

可是,我们既然用cmake了,还是兼顾不同的平台吧,于是,事情有点复杂:

  • 修改 hello.h 文件
#ifndef DBZHANG_HELLO_
#define DBZHANG_HELLO_
#if defined _WIN32
#if LIBHELLO_BUILD
#define LIBHELLO_API __declspec(dllexport)
#else
#define LIBHELLO_API __declspec(dllimport)
#endif
#else
#define LIBHELLO_API
#endif
LIBHELLO_API void hello(const char* name);
#endif //DBZHANG_HELLO_
  • 修改 libhello/CMakeList.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用法(转)的更多相关文章

  1. Cmake用法

    目录 1,Cmake introduce 1.1 常用的目录结构 2,CMakeLists.txt文件的写法 Cmake 常用命令 Scripting Commands set include Pro ...

  2. CMake 用法导览

    Preface : 本文是CMake官方文档CMake Tutorial (http://www.cmake.org/cmake/help/cmake_tutorial.html) 的翻译.通过一个样 ...

  3. cmake用法及常用命令总结(全)

    CMakeLists.txt 的语法比较简单,由命令.注释和空格组成,其中命令是不区分大小写的.指令是大小写无关的,参数和变量是大小写相关的.但推荐全部使用大写指令.符号 # 后面的内容被认为是注释. ...

  4. 自己常用的CMake用法总结

    欢迎指正 CMake : A.download : https://cmake.org/download/ B.tutorial: https://cmake.org/cmake-tutorial/ ...

  5. cmake用法及常用命令总结

    CMakeLists.txt 的语法比较简单,由命令.注释和空格组成,其中命令是不区分大小写的.指令是大小写无关的,参数和变量是大小写相关的.但推荐全部使用大写指令.符号 # 后面的内容被认为是注释. ...

  6. CMake入门实战

    本文用来记录基本的Cmake用法,以一个实例,讲解如何通过cmake构建一个一个基本的工程,文件的目录如下: 说明: bin文件夹下的debug和release分别存放编译输出的文件和相关依赖的动态库 ...

  7. VS2015--win32project配置的一些想法之cmake

    近期两天都在配置一个win32项目.为了实现跨平台,写底层代码的人仅仅build了安卓和ios的工程,没有build win32项目. 因为对一些库不是非常了解.配置起来非常困难,心力交瘁. 为了实现 ...

  8. cmake 的简单使用示例

    https://www.zybuluo.com/khan-lau/note/254724 CMake 用法导览 Preface : 本文是CMake官方文档CMake Tutorial (http:/ ...

  9. CMake技术总结

    在做算法部署的过程中,我们一般都是用C++开发,主要原因是C++的高效性,而构建维护一个大型C++工程的过程中,如何管理不同子模块之间的依赖.外部依赖库.头文件和源文件如何隔离.编译的时候又该如何相互 ...

随机推荐

  1. Effective C++ 6.继承与面向对象设计

    //条款32:确定你的public继承塑模出is-a关系 // 1.public继承意味着is-a的关系,适用在基类上的方法都能用于派生类上. //条款33:避免遮掩继承而来的名称 // 1.在pub ...

  2. (转)json+flexgrid+jbox组合运用页面刷新<jsp>

    插件效果 1.JSP页面 1 <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  3. override与final

    override 强调该函数是重写的父类的函数 final 指定该函数不能被重写 两者都是针对virtual 函数

  4. LED流水灯(二)

    记住看汇编的时候是红在上面 黑色在下面 startup.s 程序 ; MDK跑马灯实验; PRESERVE8               // 字节对齐关键词 ,汇编有8位对齐的要求,要添加 AREA ...

  5. linux tomcat 配置

    http://www.cnblogs.com/xdp-gacl/p/4097608.html

  6. Android异步任务AsyncTask

    package com.example.asynctask; import java.net.MalformedURLException; import java.net.URL; import an ...

  7. 夺命雷公狗---DEDECMS----3快速入门之隐藏

    如果我们在工作的时候遇到上操蛋的老板,本来公司是做医疗器械的,但是老板突然老了句我们不做医疗了,我们该做电影网,那么我们可以先将原本的栏目进行修改成隐藏栏目, 主要是预防变态老板突然来句“电影网更不好 ...

  8. 【GDI+】 线段 文字 定位的问题

    遇到一个看起来很简单的问题: 给定两个点,和一组文字,希望文字显示在线的附近并且居中显示.期望像这样的效果 进一步的抽象是: 1.根据文字的长度和高度,以及两个点,来获得文字的定位点(左上角点)的 2 ...

  9. OpenStack 界面开发中的排序问题

    Contents [hide] 1 需求 2 调研 3 排序的办法 4 解决代码 需求 获取主机列表的时候,希望能够对主机列表能分组显示,比如网络,一组网络段希望在一起显示 调研 openstack的 ...

  10. linux网站目录及Apache权限的设置

    apache服务器访问权限设置禁止所有访问:Options Indexes FollowSymLinks 改为 Option None   Apache单个或多个目录禁止访问方法   这种方法通常用来 ...