cmake安装:Download | CMake。
在这之前,我们介绍一下cmake。虽然Make和Makefile简化了手动构建的过程,但是编写Makefile文件仍然是一个麻烦的工作,因此就有了CMake工具。CMake工具用于生成Makefile文件,而如何生成Makefile文件,则由CMakeLists.txt文件指定。它们直接的关系如下图:
使用cmake生成Makefile并编译的流程如下:
特别注意的是,指定编译器的语句需要放在CMakeLists.txt文件最前面。
在Linux系统下,gcc一般在/user/bin
目录下。在里面可以看gcc的版本。
zhudk@vm1:/usr/bin$ cd
zhudk@vm1:~$ cd /usr/bin
zhudk@vm1:/usr/bin$ ls |grep gcc
c89-gcc
c99-gcc
gcc
gcc-7
gcc-ar
gcc-ar-7
gcc-nm
gcc-nm-7
gcc-ranlib
gcc-ranlib-7
x86_64-linux-gnu-gcc
x86_64-linux-gnu-gcc-7
x86_64-linux-gnu-gcc-ar
x86_64-linux-gnu-gcc-ar-7
x86_64-linux-gnu-gcc-nm
x86_64-linux-gnu-gcc-nm-7
x86_64-linux-gnu-gcc-ranlib
x86_64-linux-gnu-gcc-ranlib-7
如果没有指定编译器的话,默认使用的就是gcc编译器。如果系统中有多个版本gcc,需要指定gcc的版本,可以在环境变量中设置:
export CC=gcc-7
设置完成后,我们执行cmake
命令,会发现如下打印:
zhudk@vm1:/expand/zhudk/demo$ cmake .
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /expand/zhudk/demo
使用结对路径:
set(CROSS_COMPILER_PATH "/expand/zhudk/toolchain/opt/FriendlyARM/toolchain/6.4-aarch64/bin/aarch64-linux-gcc")
set(CMAKE_C_COMPILER ${CROSS_COMPILER_PATH})
或者直接使用编译器名称:
set(CMAKE_C_COMPILER "aarch64-linux-gcc")
cmake_minimum_required (VERSION 3.10)
project (Main)
# 或
project ("Main")
project (Main LANGUAGES CXX VERSION 1.0.0)
方式1
set(CMAKE_CXX_FLAGS "-no-pie")
set(CMAKE_C_FLAGS "-no-pie") # 命令行方式传入:-DCMAKE_C_FLAGS=-no-pie
方式2
add_compile_options (
头文件
include_directories (inc)
库文件
link_directories (lib)
Note:target_link_libraries
需要放于add_executable
之后
静态库
target_link_libraries(project_name mxnet) #添加libmxnet.a
动态库
target_link_libraries(project_name -lmxnet) #添加libmxnet.so
add_subdirectory (lib)
为当前路径以及下层路径的目标加入编译器命令行定义,相当于在**C/C++**程序中使用#define
对全部生成目标而言
add_definitions (-DFOO -DBAR ...)
对单个生成目标而言
target_compile_definitions(
[items1...]
[ [items2...] ...]
)
必须放在project的前面
add_executable (Main main.cpp)
Note:默认生成静态库,除非特意指定生成库的类型
add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)
add_library(archive SHARED archive.cpp zip.cpp lzma.cpp)
# set(CROSS_COMPILER_PATH "/expand/zhudk/toolchain/opt/FriendlyARM/toolchain/6.4-aarch64/bin/aarch64-linux-gcc")
# set(CMAKE_C_COMPILER ${CROSS_COMPILER_PATH})
set(CMAKE_C_COMPILER "aarch64-linux-gcc")
project(haha)
cmake_minimum_required(VERSION 3.10)
set(CMAKE_C_FLAGS "-g -Wall -O2")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
aux_source_directory(. SRC)
aux_source_directory(./aaa SRC)
aux_source_directory(./bbb SRC)
aux_source_directory(./ccc SRC)
add_executable(${PROJECT_NAME} ${SRC})
上述项目结构是一个不同目录下多个源文件的情况,根据代码功能不同放在不同的目录下。
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
是设置生成的可执行文件的路径,PROJECT_SOURCE_DIR
:工程的根目录。
aux_source_directory(dir var)
是把指定目录下所有源文件存储在一个变量中(追加在这个变量中)。
add_executable(${PROJECT_NAME} ${SRC})
生成可执行文件。
关于头文件的引用,在aaa.c
文件中:
#include "aaa.h"
#include "../bbb/bbb.h"
#include "../ccc/ccc.h"
算是手动引用的。如果不想在include
的时候手动引用,则可以在CMakeLists.txt中提前添加头文件搜索目录。
include_directories(./bbb)
现在我们来运行cmake。注意,因为运行cmake的时候会生成很多附带文件,如果直接在根目录下运行cmake的话,会对程序目录造成污染,所以,建议在./build
目录下运行cmake,然后可执行文件存放在./build/bin
。
zhudk@vm1:/expand/zhudk/demo/build$ cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /expand/zhudk/demo/build
zhudk@vm1:/expand/zhudk/demo/build$ make
Scanning dependencies of target haha
[ 20%] Building C object CMakeFiles/haha.dir/main.c.o
[ 40%] Building C object CMakeFiles/haha.dir/aaa/aaa.c.o
[ 60%] Building C object CMakeFiles/haha.dir/bbb/bbb.c.o
[ 80%] Building C object CMakeFiles/haha.dir/ccc/ccc.c.o
[100%] Linking C executable bin/haha
[100%] Built target haha
aux_source_directory(. libsrc)
#设置库输出路径
set(LIBRARY_OUTPUT_PATH ../lib)
#生成静态库 最后的库名称会为libhello.a
#add_library(hello STATIC ${libsrc})
#生成动态库 最后的库名称会为libhello.so
#add_library(hello SHARED ${libsrc})
#只是连续2次使用add_library指定库名称时(第一个参数),这个名称不能相同
#所以上述写法 不会生成动态库。可以先不使用相同的名称,再修改库的名称
add_library(hello_static STATIC ${libsrc})
add_library(hello_shared SHARED ${libsrc})
set_target_properties(hello_static PROPERTIES OUTPUT_NAME hello)
set_target_properties(hello_shared PROPERTIES OUTPUT_NAME hello)
还是上述的库文件。
project(haha)
cmake_minimum_required(VERSION 3.10)
set(CMAKE_C_FLAGS "-g -Wall -O2")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/build/bin)
aux_source_directory(. SRC)
aux_source_directory(./aaa SRC)
aux_source_directory(./bbb SRC)
aux_source_directory(./ccc SRC)
include_directories(./include)
find_library(lib libhello.a HINTS ${PROJECT_SOURCE_DIR}/lib)
add_executable(${PROJECT_NAME} ${SRC})
target_link_libraries(${PROJECT_NAME} ${lib})
使用find_library的好处是在执行cmake ..
时就会去查找库是否存在,这样可以提前发现错误,不用等到链接时。
option(debug "a debug option" off) #0或者OFF 1或者ON
if(debug)
message("debug is ${debug}")
else()
message("debug is ${debug}")
endif()
加入想在CMakeLists.txt文件中控制一些语句,可以使用option定义变量。
option命令,其第一个参数是这个option的名字,第二个参数是字符串,用来描述这个option是来干嘛的,第三个是option的值,ON或OFF,也可以不写,不写就是默认OFF
。
在执行cmake命令的时候,可以设置其值。cmake .. -Ddebug=1
。
在CMakeLists.txt中定义宏,可以直接在源码中使用。
add_definitions(-Ddebug)
#include
#include "./aaa/aaa.h"
#include "./bbb/bbb.h"
#include "./ccc/ccc.h"
#include "hello.h"
int main(void)
{
printf("Hello World!\n");
aaa();
bbb();
ccc();
hello();
#ifdef debug
printf("debug\n");
#endif
return 0;
}
可以直接在源码中使用,会打印debug
。
在CMakeLists.txt中定义宏,可以直接在源码中使用。
add_definitions(-Ddebug)
#include
#include "./aaa/aaa.h"
#include "./bbb/bbb.h"
#include "./ccc/ccc.h"
#include "hello.h"
int main(void)
{
printf("Hello World!\n");
aaa();
bbb();
ccc();
hello();
#ifdef debug
printf("debug\n");
#endif
return 0;
}
可以直接在源码中使用,会打印debug
。
仔细想了一下,如果真的需要修改宏的时候,还不如直接修改源码,修改后直接make就可以了,如果修改了CMakeLists.txt文件,那么还重新cmake。