cmake 入门
构建hello项目
查看cmake 版本
$ cmake -version
cmake version 3.16.3
CMake suite maintained and supported by Kitware (kitware.com/cmake).
项目以及内容如下
文件目录
hello
├── CMakeLists.txt
├── hello.cpp
└── Makefile
hello.cpp
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << "hello cmake " << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(hello)
add_executable(hello hello.cpp)
构建、编译与运行
$ cmake .
$ make
$ ./hello
- 生成以下文件:
CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt hello hello.cpp Makefile
- cmake 生成的文件以及最终的可执行文件 hello 与工程的源码文件 hello.cpp 混在了一起;并且清理 cmake 产生的文件时也变得麻烦;因此,需要将构建过程生成的文件与源文件分离,这就是 out-of-source build(内部构建和外部构建)。
清理后,再次构建、编译与运行(out-of-source)
$ mkdir build && cd build
$ cmake .. && make
$ ./hello
文件结构如下:
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── hello
│ └── Makefile
├── CMakeLists.txt
├── hello.cpp
└── Makefile
还有一点不方便,就是可执行文件和cmake生成文件混在一起。
继续优化,修改cmake
cmake_minimum_required(VERSION 3.15)
project(hello)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)
add_executable(hello hello.cpp)
编译后,文件目录如下:
hello
├── CMakeCache.txt
├── CMakeFiles
├── cmake_install.cmake
├── hello
└── Makefile
清理后,继续构建、编译与运行
$ mkdir build && cd build && cmake .. && make && ./hello
编译后文件结构如下:
hello
├── bin
│ └── hello
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ └── Makefile
├── CMakeLists.txt
├── hello.cpp
└── Makefile
构建hello_v2项目
项目以及内容如下
文件目录
hello_v2
├── CMakeLists.txt
├── inc
│ └── hello.hpp
├── main.cpp
└── src
└── hello.cpp
main.cpp
#include <iostream>
#include "hello.hpp"
int main(int argc, char* argv[])
{
hello();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(hello_v2)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)
file(GLOB SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
include_directories( $(CMAKE_CURRENT_SOURCE_DIR)/inc)
add_executable(${PROJECT_NAME} main.cpp ${SOURCE_DIR})
src/hello.cpp
#include <iostream>
void hello()
{
std::cout << "hello cmake " << std::endl;
}
inc/hello.hpp
void hello();
构建、编译与运行
$ mkdir build && cd build && cmake .. && make && ../bin/hello_v2
构建hello_v3项目
项目以及内容如下
文件目录
hello_v3
├── CMakeLists.txt
├── example
│ ├── CMakeLists.txt
│ └── main.cpp
├── inc
│ └── hello.hpp
└── src
├── CMakeLists.txt
└── hello.cpp
example/main.cpp
#include <iostream>
#include "hello.hpp"
int main(int argc, char* argv[])
{
hello();
return 0;
}
inc/hello.hpp
void hello();
src/hello.cpp
#include <iostream>
void hello()
{
std::cout << "hello cmake " << std::endl;
}
example/CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(hello_v3_example)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../bin)
file(GLOB SOURCE_FLIE "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
./*.cpp)
link_libraries(${CMAKE_CURRENT_SOURCE_DIR}/../lib)
add_executable(${PROJECT_NAME} ${SOURCE_FLIE})
target_link_libraries(${PROJECT_NAME} hello)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../inc)
src/CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
# 设置so库生成路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 定义了SRC_LIST变量,包含当前目录下所有的源文件
aux_source_directory(. SRC_LIST)
# 编译动态库
add_library(hello SHARED ${SRC_LIST})
# 配置头文件信息
include_directories(${PROJECT_SOURCE_DIR}/inc)
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(hello_v3)
add_subdirectory(example)
add_subdirectory(src)
构建、编译与运行
$ mkdir build && cd build && cmake .. && make && ../bin/hello_v3_example
编译后目录
├── bin
│ └── hello_v3_example
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── example
│ ├── Makefile
│ └── src
├── CMakeLists.txt
├── example
│ ├── CMakeLists.txt
│ └── main.cpp
├── inc
│ └── hello.hpp
├── lib
│ └── libhello.so
└── src
├── CMakeLists.txt
└── hello.cpp
设置编译选项
设置CMAKE_CXX_FLAGS
C++编译器参数选项,只在当前CMakeLists.txt中生效;多个CMakeLists.txt中,则每个CMakeLists.txt都需要单独指定
# -fno-exceptions 禁用运行时类型信息
# -fno-rtti 禁用异常机制
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -Wall -fno-exceptions -fno-rtti")
-
add_comile_options 全局有效
add_compile_options(-std=c++11 -Wall -Werror)
debug 和 release
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
endif()
if(CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
endif()
指定编译器路径
SET(CMAKE_C_COMPILER "/usr/bin/gcc")
SET(CMAKE_CXX_COMPILER "/usr/bin/g++")
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
SET(CMAKE_C_COMPILER "/usr/bin/gcc")
SET(CMAKE_CXX_COMPILER "/usr/bin/g++")
project(hello)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
endif()
if(CMAKE_BUILD_TYPE AND (CMAKE_BUILD_TYPE STREQUAL "Debug"))
message("Debug mode:${CMAKE_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
else()
# -fno-exceptions 禁用运行时类型信息
# -fno-rtti 禁用异常机制
message("Release mode:${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -Wall -fno-exceptions -fno-rtti")
endif()
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)
add_executable(hello hello.cpp)
- 清理后,继续构建、编译与运行
$ mkdir build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug .. && make
$ ./hello
编译后文件结构如下:
├── bin
│ └── hello
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ └── Makefile
├── CMakeLists.txt
├── hello.cpp
└── Makefile