CMakeLists.txt 学习笔记
内部构建(in source build)
编写源代码main.c
#include <stdio.h>void main()
{printf("hello\n");
}
编写CMakeLists.txt
project(hello)
message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}")
message(STATUS "hello_SOURCE_DIR: ${hello_SOURCE_DIR}")
message(STATUS "hello_BINARY_DIR: ${hello_BINARY_DIR}")set(src_list main.c)
message(STATUS "src_list: ${src_list}")
add_executable(hello ${src_list})
目录结构如下
t1
├── CMakeLists.txt
└── main.c
执行命令
cd t1 && cmake .
打印内容如下
PROJECT_SOURCE_DIR: /home/Jack/backup/cmake/t1
PROJECT_BINARY_DIR: /home/Jack/backup/cmake/t1
hello_SOURCE_DIR: /home/Jack/backup/cmake/t1
hello_BINARY_DIR: /home/Jack/backup/cmake/t1
src_list: main.c
此时,目录结构如下
t1
├── CMakeCache.txt
├── CMakeFiles
├── CMakeLists.txt
├── Makefile
├── cmake_install.cmake
└── main.c
执行命令
cd t1 && make
此时,目录结构如下
t1
├── CMakeCache.txt
├── CMakeFiles
├── CMakeLists.txt
├── Makefile
├── cmake_install.cmake
├── hello
└── main.c
运行程序
cd t1 && ./hello
结果如下
hello
外部构建(out of source build)
新建名为 t2 的文件夹,将 t1 中的 main.c 和 CMakeLists.txt 拷贝到 t2 中,目录结构如下
t2
├── CMakeLists.txt
└── main.c
在 t2 中新建 build 文件夹
cd t2 && mkdir build
在 build 文件夹中执行 cmake 命令
cd t2/build && cmake ..
打印内容如下
PROJECT_SOURCE_DIR: /home/Jack/backup/cmake/t2
PROJECT_BINARY_DIR: /home/Jack/backup/cmake/t2/build
hello_SOURCE_DIR: /home/Jack/backup/cmake/t2
hello_BINARY_DIR: /home/Jack/backup/cmake/t2/build
此时,目录结构如下
t2
├── CMakeLists.txt
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── Makefile
│ └── cmake_install.cmake
└── main.c
执行命令
cd t2/build && make
此时,目录结构如下
t2
├── CMakeLists.txt
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── Makefile
│ ├── cmake_install.cmake
│ └── hello
└── main.c
运行程序
cd t2/build && ./hello
结果如下
hello
更好一点的 hello 工程
将 t2 的 main.c 拷贝到 t3 的 src 中,目录结构如下
t3
├── CMakeLists.txt
├── LICENSE
├── README.md
├── build
├── doc
│ └── hello.txt
├── runhello.sh
└── src├── CMakeLists.txt└── main.c
编写第1个CMakeLists.txt
project(hello)
add_subdirectory(src bin)
set(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR}/install)
install(FILES LICENSE README.md DESTINATION doc)
install(DIRECTORY doc/ DESTINATION doc)
install(PROGRAMS runhello.sh DESTINATION bin)
编写第2个CMakeLists.txt
add_executable(hello main.c)
执行命令
cd t3/build && cmake .. && make install
此时,目录结构如下
t3
├── CMakeLists.txt
├── LICENSE
├── README.md
├── build
│ ├── bin
│ │ └── hello
│ └── install
│ ├── bin
│ │ └── runhello.sh
│ └── doc
│ ├── LICENSE
│ ├── README.md
│ └── hello.txt
├── doc
│ └── hello.txt
├── runhello.sh
└── src├── CMakeLists.txt└── main.c
构建动态库与静态库
目录结构如下
t4
├── CMakeLists.txt
├── build
└── lib├── CMakeLists.txt├── hello.c└── hello.h
编写第1个CMakeLists.txt
project(hellolib)
add_subdirectory(lib)
set(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR}/install)
编写第2个CMakeLists.txt
set(LIBHELLOSRC hello.c)
add_library(hello SHARED ${LIBHELLOSRC})
add_library(hello_static STATIC ${LIBHELLOSRC})
set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")
install(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
install(FILES hello.h DESTINATION include/hello)
编写hello.h
#ifndef HELLO_H
#define HELLO_H#include <stdio.h>
void HelloFunc();#endif
编写hello.c
#include "hello.h"void HelloFunc()
{printf("hello\n");
}
执行命令
cd t4/build && cmake .. && make install
此时,目录结构如下
t4
├── CMakeLists.txt
├── build
│ ├── install
│ │ ├── include
│ │ │ └── hello
│ │ │ └── hello.h
│ │ └── lib
│ │ ├── libhello.a
│ │ └── libhello.so
│ └── lib
│ ├── libhello.a
│ └── libhello.so
└── lib├── CMakeLists.txt├── hello.c└── hello.h
如何使用外部共享库和头文件
将 t4 的头文件、库文件拷贝到 t5 的 3rdparty 中,目录结构如下
t5
├── 3rdparty
│ └── hello
│ ├── include
│ │ └── hello
│ │ └── hello.h
│ └── lib
│ ├── libhello.a
│ └── libhello.so
├── CMakeLists.txt
├── build
└── src├── CMakeLists.txt└── main.c
编写第1个CMakeLists.txt
project(newhello)
add_subdirectory(src)
编写第2个CMakeLists.txt
include_directories(${PROJECT_SOURCE_DIR}/3rdparty/hello/include/hello)
add_executable(main main.c)
target_link_libraries(main ${PROJECT_SOURCE_DIR}/3rdparty/hello/lib/libhello.so)
编写main.c
#include "hello.h"int main()
{HelloFunc();return 0;
}
执行命令
cd t5/build && cmake .. && make
此时,目录结构如下
t5
├── 3rdparty
│ └── hello
│ ├── include
│ │ └── hello
│ │ └── hello.h
│ └── lib
│ ├── libhello.a
│ └── libhello.so
├── CMakeLists.txt
├── build
│ └── src
│ └── main
└── src├── CMakeLists.txt└── main.c
运行程序
cd t5/build/src && ./main
结果如下
hello
常用指令
可以使用如下命令查看 set 指令的解释
cmake --help-command set
set - Set a variable to a given value.
set(<variable> <value>)
message - Display a message to the user.
message([<mode>] "message to display")
add_executable - Add an executable to the project using the specified source files.
add_executable(<name> source1 [source2 ...])
project - Set a name for the entire project.
project(<PROJECT-NAME>)
PROJECT_SOURCE_DIR - 工程路径,和 hello_SOURCE_DIR 等价,hello 是 project name
PROJECT_BINARY_DIR - 编译路径,和 hello_BINARY_DIR 等价,hello 是 project name
add_subdirectory - Add a subdirectory to the build.
add_subdirectory(source_dir [binary_dir])
install - Specify rules to run at install time.
// Installing Files
install(<FILES|PROGRAMS> files... DESTINATION <dir>)// Installing Directories
install(DIRECTORY dirs... DESTINATION <dir>)
add_library - Add a library to the project using the specified source files.
add_library(<name> [STATIC | SHARED | MODULE] source1 [source2 ...])
include_directories - Add the given directories to those the compiler uses to search for include files.
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])