工厂 电商网站建设,wordpress博客申请,建新网站开发流程图,注册微商店铺如何注册最大的Qt4程序群(KDE4)采用cmake作为构建系统Qt4的python绑定(pyside)采用了cmake作为构建系统开源的图像处理库 opencv 采用cmake 作为构建系统...
看来不学习一下cmake是不行了#xff0c;一点一点来吧#xff0c;找个最简单的C程序#xff0c;慢慢复杂化#xff0c;试试…最大的Qt4程序群(KDE4)采用cmake作为构建系统Qt4的python绑定(pyside)采用了cmake作为构建系统开源的图像处理库 opencv 采用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 .. -GNMake Makefiles
nmake
或者
cmake .. -GMinGW 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 VERBOSE1
或者
$ export VERBOSE1$ 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.hvoid 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.exebuild/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)
恩剩下来的工作就和原来一样了。