cmake 是一个跨平台、开源的构建系统。它是一个集软件构建、测试、打包于一身的软件。它使用与平台和编译器独立的配置文件来对软件编译过程进行控制。
CMakeLists.txt直接指定了程序的编译规则。
因为仅仅只是作为一个入门学习。我们的目标是
首先我们需要了解CMakeLists.txt中最常用的语句,注意,以下内容对于大小写并没有严格的要求,可以按照个人喜好修改:
cmake_minimum_required(VERSION 3.0.2)
project(YOYO)
set(EXECUTABLE_OUTPUT_PATH ${
PROJECT_BINARY_DIR}/bin)
aux_source_directory(
./src/shared/src SHARED_SRC
)
add_subdirectory(./src)
include_directories(
./include
)
add_executable( ${
PROJECT_NAME}
./src/main.cpp
)
link_directories(
/path/lib
)
target_link_libraries(${
PROJECT_NAME}
libname.a
libname.so
)
add_library(LIB_NAME SHARED ${
SHARED_SRC})
当我自己查资料学习的时候看了大量的语句说明,并不能很好地理解,其实在实例中逐步了解效果会好很多,所以这里我们尝试给出一些实例。
.
├── build
├── CMakeLists.txt
└── src
└── main.cpp
其中main.cpp文件是一个最简单的hello world程序。CMakeLists.txt内容如下
cmake_minimum_required(VERSION 3.0.2)
project(EXAMPLE)
set(EXECUTABLE_OUTPUT_PATH ${
PROJECT_BINARY_DIR}/bin)
add_executable(${
PROJECT_NAME}
${
PROJECT_SOURCE_DIR}/src/main.cpp
)
2 在指定了最小版本、项目名以后,我们先将可执行文件的输出路径指定成${PROJECT_BINARY_DIR}/bin
其中${PROJECT_BINARY_DIR}就是指的build文件夹
然后我们设定src目录下的main.cpp为可执行文件
使用以下命令进行编译
cd ./build
cmake ..
make
其实cmake命令后面的参数指的是CMakeLists.txt的路径,cmake将生成的文件保存在当前目录下
所以如果直接在工作空间下运行会显得很杂乱,习惯上都在build目录下执行cmake ..
grandpadzb $ ~/cpp/learn_cmake/build/bin ./EXAMPLE
hello world
.
├── build
├── CMakeLists.txt
├── include
│ └── yoyo.h
└── src
└── main.cpp
cmake_minimum_required(VERSION 3.0.2)
project(EXAMPLE)
set(EXECUTABLE_OUTPUT_PATH ${
PROJECT_BINARY_DIR}/bin)
include_directories(
${
PROJECT_SOURCE_DIR}/include
)
add_executable(${
PROJECT_NAME}
${
PROJECT_SOURCE_DIR}/src/main.cpp
)
.
├── build
├── CMakeLists.txt
└── src
├── shared
│ ├── CMakeLists.txt
│ ├── include
│ │ └── Pet.h
│ └── src
│ └── Pet.cpp
└── static
├── CMakeLists.txt
├── include
│ └── Pet.h
└── src
└── Pet.cpp
// Pet.h
#include
using namespace std;
#define CAT "miaomiao"
#define DOG "wangwang"
class Pet
{
private:
/* data */
public:
int type = 0;
void say();
Pet(int type = 0);
~Pet();
};
// Pet.cpp
#include "Pet.h"
Pet::Pet(int type){
if(type == 0){
this->type = 0;
}
else if(type == 1){
this->type = 1;
}
else{
this->type = -1;
}
}
Pet::~Pet(){
}
void Pet::say(){
switch (this->type)
{
case 0:{
cout << "Pet says: " << CAT << endl;
break;
}
case 1:{
cout << "Pet says: " << DOG << endl;
break;
}
default:
cout << "Pet says: %#&*%@@$#" << endl;
break;
}
}
cmake_minimum_required(VERSION 3.0.2)
SET(LIBRARY_OUTPUT_PATH ${
PROJECT_BINARY_DIR}/lib)
AUX_SOURCE_DIRECTORY(
${
PROJECT_SOURCE_DIR}/src/static/src STATIC_SRC
)
INCLUDE_DIRECTORIES(
${
PROJECT_SOURCE_DIR}/src/static/include
)
add_library(Pet_static STATIC ${
STATIC_SRC})
cmake_minimum_required(VERSION 3.0.1)
project(Pet)
ADD_SUBDIRECTORY(src/shared)
ADD_SUBDIRECTORY(src/static)
cmake_minimum_required(VERSION 3.0.2)
project(EXAMPLE)
set(EXECUTABLE_OUTPUT_PATH ${
PROJECT_BINARY_DIR}/bin)
link_libraries(
/home/username/cpp/Pet/build/lib
)
include_directories(
${
PROJECT_SOURCE_DIR}/include
/home/username/cpp/Pet/src/static/include
)
add_executable(${
PROJECT_NAME}
${
PROJECT_SOURCE_DIR}/src/main.cpp
)
target_link_libraries(${
PROJECT_NAME}
/home/username/cpp/Pet/build/lib/libPet_static.a
)
grandpadzb ~/cpp/learn_cmake/build/bin ./EXAMPLE
Pet says: %#&*%@@$#
如果每次建立工程文件或者库文件都要像这样不断新建文件夹,重写CMakeLists.txt实在是太麻烦啦。我就根据自己的偏好写了两个sh脚本,内容如下:
首先在~/下创建backups目录,新建文件build_lib.sh、build_ws.sh、CMakeLists.txt
#! /bin/sh
mkdir build
mkdir src
touch CMakeLists.txt
cat >>./CMakeLists.txt<(VERSION 3.0.1)
project(PROJECT_NAME)
#ADD_SUBDIRECTORY(src/shared)
#ADD_SUBDIRECTORY(src/static)
EOF
mkdir src/static
mkdir src/static/src
mkdir src/static/include
touch src/static/CMakeLists.txt
cat >> src/static/CMakeLists.txt << EOF
cmake_minimum_required(VERSION 3.0.2)
SET(LIBRARY_OUTPUT_PATH \${
PROJECT_BINARY_DIR}/lib)
AUX_SOURCE_DIRECTORY(
\${
PROJECT_SOURCE_DIR}/src/static/src STATIC_SRC
)
INCLUDE_DIRECTORIES(
\${
PROJECT_SOURCE_DIR}/src/static/include
)
add_library(LIB_NAME STATIC \${
STATIC_SRC})
EOF
mkdir src/shared
mkdir src/shared/src
mkdir src/shared/include
touch src/shared/CMakeLists.txt
cat >> src/shared/CMakeLists.txt << EOF
cmake_minimum_required(VERSION 3.0.2)
SET(LIBRARY_OUTPUT_PATH \${
PROJECT_BINARY_DIR}/lib)
AUX_SOURCE_DIRECTORY(
\${
PROJECT_SOURCE_DIR}/src/shared/src SHARED_SRC
)
INCLUDE_DIRECTORIES(
\${
PROJECT_SOURCE_DIR}/src/shared/include
)
add_library(LIB_NAME SHARED \${
SHARED_SRC})
EOF
touch readme.md
cat >> readme.md << EOF
当前目录下的CMakeLists.txt中注释了指定子目录的两条命令,根据需要创建静态库还是共享库来解注释使用,并修改PROJECT_NAME
SHARED或者STATIC文件夹下的CMakeLists.txt只需填写库名称
将函数头文件写在include文件夹中,函数实现写在src文件夹中
请在build目录下使用
cmake ..
make
EOF
tree
#! /bin/sh
mkdir build
mkdir include
mkdir src
cp ~/backups/CMakeLists.txt .
touch readme.md
cat >> ./readme.md << EOF
需在当前目录下CMakeLists.txt中补全
PROJECT_NAME
FILE_NAME (可执行文件名)
其他根据需求解注释使用
请在build目录下进行
cmake ..
make
生成的可执行文件在build/bin目录下
EOF
tree
cmake_minimum_required(VERSION 3.0.2)
# Create ${PROJECT_NAME} ${PROJECT_SOURCE_DIR}
project(PROJECT_NAME)
# Set executable output path
set(EXECUTABLE_OUTPUT_PATH ${
PROJECT_BINARY_DIR}/bin)
# Add child_dir if you need
#add_subdirectory(./src)
#add_subdirectory(./include)
# Set include path ( contains lib include path)
include_directories(
./include
)
# Set lib path
#link_directories({lib_path})
add_executable(${
PROJECT_NAME}
./src/FILE_NAME
)
# Set link libs if you need
#target_link_libraries(${PROJECT_NAME}
# libname.a
# libname.so
#)
具体含义就不过多介绍了,因为我写的并不好,仅仅是临时有了这个想法为了实现这个功能临时了解了几个相关的语法就动手了,所以它能够用,但是很丑。
只要运行这两个sh文件就能在当前目录下创建出上面例子里面使用的目录结构还有合适的CMakeLists.txt,根据readme.md里面的简要介绍去稍微改一下CMakeLists.txt就可以直接去编译了。
由于我使用的是zsh,所以还在.zshrc中添加了如下几行,用更简单的命令去创建简化。
alias cmkl='cp ~/backups/CMakeLists.txt .'
alias build_lib='cp ~/backups/build_lib.sh .'
alias build_ws='cp ~/backups/build_ws.sh .'
还有很难受的事,当我把这俩脚本写完了之后,惊喜地发现vscode完全具有相关拓展可以更漂亮地完成这些工作。但是最后由于我还是更习惯自己写的那种目录结构,所以暂时还是用着自己的那一套了。
如果你需要快速建立CMakeLists.txt目录,请直接去学习vscode的相关拓展!