CMake 是一个开源、跨平台的管理源代码构建的工具。CMake 广泛用于 C 和 C++ 语言,但它也可以用于构建其他语言的源代码。makefile通常依赖于你当前的编译平台,使用CMake 可以产生自动化生成makefile,达到可以移植跨平台的目的。
项目主目录存在一个CMakeLists.txt文件
CMakeLists.txt
cmake PATH
生成Makefile(PATH是顶层CMakeLists.txt所在的目录)make
进行编译cmake_minimum_required
:指定CMake最小版本要求
语法:cmake_minimum_required(VERSION versionnumber [FATAL_ERROR])
#设置CMake最低版本为2.5
cmake_minimum_required(VERSION 2.5)
project
:定义工程名称,并且可指定工程支持的语言
语法:project(projectname [CXX] [C] [Java])
#设置工程名为HELLO
project(HELLO)
set
:显示定义变量
语法:set(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]))
#定义变量MYFRIEND_SRC,其值为include/myfriend.h src/myfriend.cpp
set(MYFRIEND_SRC include/myfriend.h src/myfriend.cpp)
include_directories
:向工程添加多个特定的头文件搜索路径
语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
#将目录/usr/include/myincludefolder ./include添加进头文件搜索路径
include_directories(/usr/include/myincludefolder ./include)
link_directories
:向工程添加多个特定库文件的搜索路径
语法:link_directories(dir1 dir2 …)
#将目录/usr/lib/mylibfolder ./lib添加进库文件搜索路径
link_directories(/usr/lib/mylibfolder ./lib)
add_library
:生成库文件
语法:add_library(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
#通过变量SRC生成libhello.so共享库
add_library(hello SHARED ${SRC})
add_compile_options
:添加编译参数
语法:add_compile_options(option1 option2 …)
#添加编译参数-g -o2 -std=c++11(相当于g++ -g -o2 -std=c++11)
add_compile_options(-g -o2 -std=c++11)
add_executable
:生成可执行文件
语法:add_executable(exename souce1 source2 …)
#生成可执行文件main_cmake,源文件为main.cpp、src/myfriend.cpp
#相当于 g++ main.cpp src/myfriend.cpp -Iinclude -o main
add_executable(main_cmake main.cpp src/myfriend.cpp)
target_link_libraries
:为target添加需要链接的共享库(相当于g++编译时的-I参数)
语法:target_link_libraries(target library
#将MYFRINED_SHARED动态库文件链接到可执行文件main_cmake
target_link_libraries(main_cmake MYFRINED_SHARED)
add_subdirectories
:向当前工程添加存放源文件的子目录,并且可以指定中间二进制和目标二进制文件的存放位置
语法:add_subdirectories(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
#添加src子目录,src需要有一个CMakeLists.txt文件
add_subdirectories(src)
aux_source_directory
:发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来构建源文件列表
语法:aux_source_directory(dir VARIABLE)
#定义SRC变量,其值为当前目录(.)下所有的源代码文件
aux_source_directory(. SRC)
#编译SRC变量所代表的所有源代码文件,生成main可执行文件
add_executable(main ${SRC})
CMAKE_C_FLAGS
:gcc编译选项CMAKE_CXX_FLAGS
:g++编译选项CMAKE_BUILD_TYPE
:编译类型(Debug、Release)CMAKE_BINARY_DIR
、PROJECT_BINARY_DIR
、_BINARY_DIR
:如果为in source build,指工程顶层目录;如果是out of source,指工程编译发生的目录CMAKE_SOURCE_DIR
、PROJECT_SOURCE_DIR
、_SOURCE_DIR
:无论采用何种编译方式都指工程顶层目录CMAKE_C_COMPILER
:指定C编译器CMAKE_CXX_COMPILER
:指定C++编译器EXECUTABLE_OUTPUT_PATH
:可执行文件输出的存放路径LIBRARY_OUTPUT_PATH
:库文件输出的存放路径库分为静态库(Static Library)和共享库(Shared library)两类。静态库文件的扩展名是.a,共享库文件的扩展名是.so(在CYGWIN环境下,分别叫做.o和.dll)。
静态库:可重定位目标文件以一种特定的方式打包成一个单独的文件,并且在链接生成可执行文件时,从这个单独的文件中“拷贝”它自己需要的内容到最终的可执行文件中。这个单独的文件,称为静态库。linux中通常以.a(archive)为后缀
CMakeLists.txt:
#设置CMake最低版本为2.5
cmake_minimum_required(VERSION 2.5)
#设置工程名为HELLO
project(HELLO)
#通过hello.cpp生成静态库文件libhello.a
add_library(hello hello.cpp)
[vvvcxjvvv@localhost hello]$ cd build
[vvvcxjvvv@localhost build]$ cmake ../
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vvvcxjvvv/Desktop/cxj_data/mycode/hello/build
[vvvcxjvvv@localhost build]$ make
Scanning dependencies of target hello
[100%] Building CXX object CMakeFiles/hello.dir/hello.o
Linking CXX static library libhello.a
[100%] Built target hello
[vvvcxjvvv@localhost build]$
动态库:动态库和静态库类似,但是它并不在链接时将需要的二进制代码都“拷贝”到可执行文件中,而是仅仅“拷贝”一些重定位和符号表信息,这些信息可以在程序运行时完成真正的链接过程。linux中通常以.so(shared object)作为后缀。
CMakeLists.txt编写:
#设置最低cmake版本
cmake_minimum_required(VERSION 2.5)
#设置项目名称为MYFRIEND
project(MYFRIEND)
#定义变量MYFRIEND_SRC为include/myfriend.h src/myfriend.cpp
set(MYFRIEND_SRC include/myfriend.h src/myfriend.cpp)
#将include目录添加进头文件搜索路径(重要!!!否则找不到include/myfriend.h)
include_directories(include)
#通过变量MYFRIEND_SRC生成libMYFRINED_SHARED.so共享库
add_library(MYFRINED_SHARED SHARED ${MYFRIEND_SRC})
[vvvcxjvvv@localhost temp3]$ cd build
[vvvcxjvvv@localhost build]$ cmake ../
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
[vvvcxjvvv@localhost build]$ cmake ../
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vvvcxjvvv/Desktop/cxj_data/mycode/temp3/build
[vvvcxjvvv@localhost build]$ make
Scanning dependencies of target MYFRINED_SHARED
[100%] Building CXX object CMakeFiles/MYFRINED_SHARED.dir/src/myfriend.o
Linking CXX shared library libMYFRINED_SHARED.so
[100%] Built target MYFRINED_SHARED
[vvvcxjvvv@localhost build]$
CMakeLists.txt编写:
#设置CMake最低版本为2.5
cmake_minimum_required(VERSION 2.5)
#设置工程名为HELLO
project(HELLO)
#生成可执行文件hello_cmake(源文件为hello.cpp)
add_executable(hello_cmake hello.cpp)
初始文件目录:
[vvvcxjvvv@localhost hello]$ tree .
.
├── CMakeLists.txt
└── hello.cpp
0 directories, 2 files
执行cmake .
——进行内部构建
[vvvcxjvvv@localhost hello]$ cmake .
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vvvcxjvvv/Desktop/cxj_data/mycode/hello
[vvvcxjvvv@localhost hello]$ tree .
.
├── CMakeCache.txt
├── CMakeFiles
│ ├── 2.8.12.2
│ │ ├── CMakeCCompiler.cmake
│ │ ├── CMakeCXXCompiler.cmake
│ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ ├── CMakeSystem.cmake
│ │ ├── CompilerIdC
│ │ │ ├── a.out
│ │ │ └── CMakeCCompilerId.c
│ │ └── CompilerIdCXX
│ │ ├── a.out
│ │ └── CMakeCXXCompilerId.cpp
│ ├── cmake.check_cache
│ ├── CMakeDirectoryInformation.cmake
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── hello_cmake.dir
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── DependInfo.cmake
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── link.txt
│ │ └── progress.make
│ ├── Makefile2
│ ├── Makefile.cmake
│ ├── progress.marks
│ └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── hello.cpp
└── Makefile
6 directories, 28 files
执行make
进行编译:
[vvvcxjvvv@localhost hello]$ make
Scanning dependencies of target hello_cmake
[100%] Building CXX object CMakeFiles/hello_cmake.dir/hello.o
Linking CXX executable hello_cmake
[100%] Built target hello_cmake
[vvvcxjvvv@localhost hello]$ tree .
.
├── CMakeCache.txt
├── CMakeFiles
│ ├── 2.8.12.2
│ │ ├── CMakeCCompiler.cmake
│ │ ├── CMakeCXXCompiler.cmake
│ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ ├── CMakeSystem.cmake
│ │ ├── CompilerIdC
│ │ │ ├── a.out
│ │ │ └── CMakeCCompilerId.c
│ │ └── CompilerIdCXX
│ │ ├── a.out
│ │ └── CMakeCXXCompilerId.cpp
│ ├── cmake.check_cache
│ ├── CMakeDirectoryInformation.cmake
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── hello_cmake.dir
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── CXX.includecache
│ │ ├── DependInfo.cmake
│ │ ├── depend.internal
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── hello.o
│ │ ├── link.txt
│ │ └── progress.make
│ ├── Makefile2
│ ├── Makefile.cmake
│ ├── progress.marks
│ └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── hello_cmake
├── hello.cpp
└── Makefile
6 directories, 32 files
[vvvcxjvvv@localhost hello]$ ./hello_cmake
Hello World!
[vvvcxjvvv@localhost hello]$
CMakeLists.txt编写:
#设置最低的cmake版本为2.5
cmake_minimum_required(VERSION 2.5)
#设置项目名称为MYFRIEND
Project(MYFRIEND)
#把源文件目录include添加到工程的头文件搜索路径
include_directories(include)
#生成可执行文件main_cmake,源文件为main.cpp、src/myfriend.cpp
#相当于 g++ main.cpp src/myfriend.cpp -Iinclude -o main
add_executable(main_cmake main.cpp src/myfriend.cpp)
初始目录结构:
[vvvcxjvvv@localhost temp1]$ tree .
.
├── CMakeLists.txt
├── include
│ └── myfriend.h
├── main.cpp
└── src
└── myfriend.cpp
2 directories, 4 files
创建build文件夹存放输出文件——外部构建
[vvvcxjvvv@localhost temp1]$ mkdir build
[vvvcxjvvv@localhost temp1]$ cd build
使用cmake ../
找到顶层目录下的CMakeLists.txt
[vvvcxjvvv@localhost build]$ cmake ../
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vvvcxjvvv/Desktop/cxj_data/mycode/temp1/build
使用make
进行编译,产生的可执行文件在build目录下
[vvvcxjvvv@localhost build]$ make
Scanning dependencies of target main_cmake
[ 50%] Building CXX object CMakeFiles/main_cmake.dir/main.o
[100%] Building CXX object CMakeFiles/main_cmake.dir/src/myfriend.o
Linking CXX executable main_cmake
[100%] Built target main_cmake
[vvvcxjvvv@localhost build]$ cd ../
[vvvcxjvvv@localhost temp1]$ tree .
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├── 2.8.12.2
│ │ │ ├── CMakeCCompiler.cmake
│ │ │ ├── CMakeCXXCompiler.cmake
│ │ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ │ ├── CMakeSystem.cmake
│ │ │ ├── CompilerIdC
│ │ │ │ ├── a.out
│ │ │ │ └── CMakeCCompilerId.c
│ │ │ └── CompilerIdCXX
│ │ │ ├── a.out
│ │ │ └── CMakeCXXCompilerId.cpp
│ │ ├── cmake.check_cache
│ │ ├── CMakeDirectoryInformation.cmake
│ │ ├── CMakeOutput.log
│ │ ├── CMakeTmp
│ │ ├── main_cmake.dir
│ │ │ ├── build.make
│ │ │ ├── cmake_clean.cmake
│ │ │ ├── CXX.includecache
│ │ │ ├── DependInfo.cmake
│ │ │ ├── depend.internal
│ │ │ ├── depend.make
│ │ │ ├── flags.make
│ │ │ ├── link.txt
│ │ │ ├── main.o
│ │ │ ├── progress.make
│ │ │ └── src
│ │ │ └── myfriend.o
│ │ ├── Makefile2
│ │ ├── Makefile.cmake
│ │ ├── progress.marks
│ │ └── TargetDirectories.txt
│ ├── cmake_install.cmake
│ ├── main_cmake
│ └── Makefile
├── CMakeLists.txt
├── include
│ └── myfriend.h
├── main.cpp
└── src
└── myfriend.cpp
10 directories, 35 files
[vvvcxjvvv@localhost temp1]$ cd build
[vvvcxjvvv@localhost build]$ ./main_cmake
Hello Chandler
CMakelists.txt编写:
#设置最低cmake版本
cmake_minimum_required(VERSION 2.5)
#设置项目名称为MYFRIEND
project(MYFRIEND)
#添加编译参数-g -o2 -std=c++11
add_compile_options(-g -o2 -std=c++11)
#定义变量MYFRIEND_SRC为include/myfriend.h src/myfriend.cpp
set(MYFRIEND_SRC include/myfriend.h src/myfriend.cpp)
#将include目录添加进头文件搜索路径(重要!!!否则找不到include/myfriend.h)
include_directories(include)
#通过变量MYFRIEND_SRC生成libMYFRINED_SHARED.so共享库
add_library(MYFRINED_SHARED SHARED ${MYFRIEND_SRC})
#生成可执行文件main_cmake,源文件为main.cpp
add_executable(main_cmake main.cpp)
#将MYFRINED_SHARED动态库文件链接到可执行文件main_cmake
target_link_libraries(main_cmake MYFRINED_SHARED)
创建build文件夹以把输出文件放入build中
进入build文件夹后执行cmake ../
——外部构建
[vvvcxjvvv@localhost temp2]$ mkdir build
[vvvcxjvvv@localhost temp2]$ cd build
[vvvcxjvvv@localhost build]$ cmake ../
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vvvcxjvvv/Desktop/cxj_data/mycode/temp2/build
执行make
进行编译(libMYFRINED_SHARED.so、main_cmake都在build目录下)
[vvvcxjvvv@localhost build]$ make
Scanning dependencies of target MYFRINED_SHARED
[ 50%] Building CXX object CMakeFiles/MYFRINED_SHARED.dir/src/myfriend.o
Linking CXX shared library libMYFRINED_SHARED.so
[ 50%] Built target MYFRINED_SHARED
Scanning dependencies of target main_cmake
[100%] Building CXX object CMakeFiles/main_cmake.dir/main.o
Linking CXX executable main_cmake
[100%] Built target main_cmake
[vvvcxjvvv@localhost build]$ ./main_cmake
Hello Chandler
本文整理了在Linux环境下使用CMake编译C/C++工程文件的一些知识点,整理了CMake编译规则,常用指令以及常用变量,如何使用CMake生成静态库以及共享库。并列举了一些例子展示了如何进行内部构建和外部构建,以及如何对多源文件进行直接编译以及生成库编译。