执行cmake可生成makefile文件和一些中间文件,cmake有内部构建和外部构建两种操作,建议进行外部构建,保持代码整洁,项目目录结构清晰。
cmake .表示根据当前目录中的文件CMakeLists.txt里制定的规则构建系统并在当前目录下生成Makefile文件。【属于内部构建】
cmake ..表示根据上一级目录中的文件CMakeLists.txt里制定的规则构建系统并在当前目录下生成Makefile文件。
cmake [参数] [指定进行编译的目录或存放Makefile文件的目录] [指定CMakeLists.txt文件所在的目录] 【属于外部构建】
一、开胃菜
hello目录下的文件结构:
1
2
3
4
|
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c
|
C代码见下节。
最简单的cmake配置文件:
1
2
3
|
project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})
|
如果要编译成gdb可调试的debug版本,则在配置文件中加入:
1
|
set(CMAKE_BUILD_TYPE Debug)
|
如果要编译成可用gprof分析的版本,则在配置文件中加入:
1
2
|
set(CMAKE_BUILD_TYPE Profile)
set(CMAKE_CXX_FLAGS_PROFILE
"-pg"
)
|
最简单的编译过程(在hello目录中编译):
1
2
|
cmake .
make
|
这样就会在hello目录中生成可执行文件hello和其他cmake相关的配置文件。
为了让代码整洁,可以使用所谓的out-of-source编译方式:
1
2
3
4
|
mkdir
build
cd
build
cmake ..
make
|
这样编译产生的所有文件都在build中了。
二、一个小工程hello示范
本例主要包含独立库文件、可执行文件的编译和安装过程中涉及的相关问题。
hello目录中的文件结构:
1
2
3
4
5
6
7
8
|
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
├── CMakeLists.txt
└── main.c
|
文件内容如下:
1
2
3
4
5
|
project(HELLO)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_INSTALL_PREFIX /tmp/hello)
add_subdirectory(libhello)
add_subdirectory(src)
|
set(CMAKE_INSTALL_PREFIX:设置程序的安装目录,优先级比cmake命令参数设置高。
1
2
3
4
5
6
7
8
9
10
|
set(LIB_SRC hello.c)
add_definitions(
"-DLIBHELLO_BUILD"
)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
add_library(libhello SHARED ${LIB_SRC})
add_library(hello_static STATIC ${LIB_SRC})
install(TARGETS libhello LIBRARY DESTINATION lib)
install(TARGETS hello_static ARCHIVE DESTINATION lib)
install(FILES hello.h DESTINATION include)
set_target_properties(libhello PROPERTIES OUTPUT_NAME
"hello"
)
set_target_properties(hello_static PROPERTIES OUTPUT_NAME
"hello"
)
|
(1)add_library:生成库文件,SHARED表示动态链接库;
(2)set(LIBRARY_OUTPUT_PATH:生成的库文件路径,PROJECT_BINARY_DIR和CMAKE_BINARY_DIR、<projectname>_BINARY_DIR都是指进行编译的目录;
(3)install:安装头文件和库文件到相应的目录;
(4)set_target_properties(libhello:生成的库文件名为libhello.so,若没有这一行,库文件名就是liblibhello.so。
1
2
3
4
5
6
7
8
|
include_directories(${PROJECT_SOURCE_DIR}/libhello)
link_directories(${CMAKE_INSTALL_PREFIX}/lib)
aux_source_directory(. APP_SRC)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello ${APP_SRC})
target_link_libraries(hello libhello)
install(TARGETS hello RUNTIME DESTINATION bin)
set_property(TARGET hello PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
(1)include_directories:指定头文件路径;
(2)link_directories:指定库文件路径;
(3)aux_source_directory:将当前目录(.)中的所有文件名赋值给APP_SRC;
(4)set(EXECUTABLE_OUTPUT_PATH:生成的可执行文件的路径,PROJECT_BINARY_DIR和CMAKE_BINARY_DIR、<projectname>_BINARY_DIR都是指进行编译的目录;
(5)add_executable:生成可执行文件,PROJECT_SOURCE_DIR和CMAKE_SOURCE_DIR、<projectname>_SOURCE_DIR都是工程的顶级目录;
(6)target_link_libraries:libhello要和./libhello/CMakeLists.txt中的libhello对应;
(7)install(TARGETS:安装程序到${CMAKE_INSTALL_PREFIX}/bin目录;
(8)set_property:设定安装的可执行文件所需的库文件路径,如果没有该项设置,会出错:cannot open shared object file: No such file or directory。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#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_
|
1
2
3
4
5
6
7
|
#include <stdio.h>
#include "hello.h"
void
hello(
const
char
*name)
{
printf
(
"Hello %s!\n"
, name);
}
|
1
2
3
4
5
6
7
|
#include "hello.h"
int
main(
int
argc,
char
*argv[])
{
hello(
"World"
);
return
0;
}
|
在hello目录下编译程序:
1
2
3
4
5
|
mkdir
build
cd
build
cmake .. -DCMAKE_INSTALL_PREFIX=
/tmp
make
make
install
|
(1)-DCMAKE_INSTALL_PREFIX=/tmp让程序的安装目录变为/tmp/bin,默认情况CMAKE_INSTALL_PREFIX=/usr/local;
(2)若在CMakeLists.txt中设置了set(CMAKE_INSTALL_PREFIX /tmp/hello),此处的设置无效。
编译之后,hello目录中主要文件结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
├── build
│ ├── bin
│ │ └── hello
│ ├── lib
│ │ ├── libhello.so
│ │ └── libhello.a
│ ├── libhello
│ └── src
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
├── CMakeLists.txt
└── main.c
|
build目录中有4个子目录,libhello和src目录中是源文件对应目录在cmake过程中生成的中间文件。
安装后,/tmp/hello目录内的结构:
1
2
3
4
5
6
7
|
├── bin
│ └── hello
├── include
│ └── hello.h
└── lib
├── libhello.a
└── libhello.so
|
参考资料:
http://blog.csdn.net/dbzhang800/article/details/6314073
http://blog.csdn.net/dbzhang800/article/details/6329068
http://www.cmake.org/Wiki/CMake_RPATH_handling
Cmake实践(by Cjacker)