00 hello-cmake
cmake_minimum_required(VERSION 3.5)
project (hello_cmake)
add_executable(hello_cmake main.cpp)
add_executable命令详解
01 hello-headers
cmake_minimum_required(VERSION 3.5)
project(hello-headers)
set(SOURCES
src/hello.cpp
src/main.cpp
)
add_executable(hello-headers ${SOURCES})
target_include_directories(hello_headers
PRIVATE
${PROJEC_SOURCE_DIR}/include
)
target_include_directorices命令详解
关于target_include_directories中作用域的解释:
测试工程目录结构:
cmake-test/ 工程主目录,main.c 调用 libhello-world.so
├── CMakeLists.txt
├── hello-world 生成 libhello-world.so,调用 libhello.so 和 libworld.so
│ ├── CMakeLists.txt
│ ├── hello 生成 libhello.so
│ │ ├── CMakeLists.txt
│ │ ├── hello.c
│ │ └── hello.h libhello.so 对外的头文件
│ ├── hello_world.c
│ ├── hello_world.h libhello-world.so 对外的头文件
│ └── world 生成 libworld.so
│ ├── CMakeLists.txt
│ ├── world.c
│ └── world.h libworld.so 对外的头文件
└── main.c
调用关系:
├────libhello.so
可执行文件────libhello-world.so
├────libworld.so
关键字用法说明:
PRIVATE:私有的。生成 libhello-world.so时,只在 hello_world.c 中包含了 hello.h,libhello-world.so 对外的头文件——hello_world.h 中不包含 hello.h。而且 main.c 不会调用 hello.c 中的函数,或者说 main.c 不知道 hello.c 的存在,那么在 hello-world/CMakeLists.txt 中应该写入:
target_link_libraries(hello-world PRIVATE hello)
target_include_directories(hello-world PRIVATE hello)
INTERFACE:接口。生成 libhello-world.so 时,只在libhello-world.so 对外的头文件——hello_world.h 中包含 了 hello.h, hello_world.c 中不包含 hello.h,即 libhello-world.so 不使用 libhello.so 提供的功能,只使用 hello.h 中的某些信息,比如结构体。但是 main.c 需要使用 libhello.so 中的功能。那么在 hello-world/CMakeLists.txt 中应该写入:
target_link_libraries(hello-world INTERFACE hello)
target_include_directories(hello-world INTERFACE hello)
PUBLIC:公开的。PUBLIC = PRIVATE + INTERFACE。生成 libhello-world.so 时,在 hello_world.c 和 hello_world.h 中都包含了 hello.h。并且 main.c 中也需要使用 libhello.so 提供的功能。那么在 hello-world/CMakeLists.txt 中应该写入:
target_link_libraries(hello-world PUBLIC hello)
target_include_directories(hello-world PUBLIC hello)
实际上,这三个关键字指定的是目标文件依赖项的使用范围(scope)或者一种传递(propagate)。官方说明
可执行文件依赖 libhello-world.so, libhello-world.so 依赖 libhello.so 和 libworld.so。
main.c 不使用 libhello.so 的任何功能,因此 libhello-world.so 不需要将其依赖—— libhello.so 传递给 main.c,hello-world/CMakeLists.txt 中使用 PRIVATE 关键字;
main.c 使用 libhello.so 的功能,但是libhello-world.so 不使用,hello-world/CMakeLists.txt 中使用 INTERFACE 关键字;
main.c 和 libhello-world.so 都使用 libhello.so 的功能,hello-world/CMakeLists.txt 中使用 PUBLIC 关键字;
总结:
target_include_directories里面的关键字控制头文件目录传递。
target_link_libraries里的关键字控制头文件目录以及链接库传递。
PUBLIC:对内对外都公开,可将头文件目录以及链接库传递给连接者。
PRIVATE:对内公开,对外不公开,不可传递头文件目录以及链接库。
INTERFACE:对外公开,对内不公开,可传递头文件目录以及链接库,但内部不可使用头文件及连接库,只能接口传递。
02 hello-library (静态库)
cmake_minimum_required(VERSION 3.5)
project(hello_library)
#调用该命令将指定的路径源文件生成静态库
add_library(hello_library STATIC src/Hello.cpp)
#为静态库指定头文件目录,此处以作用域指定为PUBLIC,则任何引用该静态库的目标都可以寻找到此头文件;如果使用PRIVATE,则其它引用该静态库的目标无法找到其头文件;
target_include_directories(hello_library PUBLIC ${PROJECT_SOURCE_DIR}/include)
add_executable(hello_binary src/main.cpp)
target_link_libraries(hello_binary PRIVATE hello_library)
03 hello-library(动态库)
cmake_minimum_required(VERSION 3.5)
project(hello_library)
add_library(hello_library SHARED src/hello.cpp)
#为该动态库添加别名
add_library(hello::library ALIAS hello_library)
#为该动态库指定头文件目录
target_include_directories(hello_library PUBLIC ${PROJECT_SOURCE_DIR}/include)
#生成可执行文件
add_executable(hello_binary src/main.cpp)
#为可执行文件链接库
target_link_libraries(hello_binary PRIVATE hello::library)