此文章参考:CMAKE 编写 FindXXX.cmake_cmake find-CSDN博客
先看main中的CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(main VERSION 1.0.0)
set(hello_DIR "${PROJECT_SOURCE_DIR}/../hello/")
find_package(hello REQUIRED)
set(CMAKE_CXX_STANDARD 11)
include_directories(${hello_INCLUDE_DIRS})
link_libraries(${hello_LIBRARIES})
add_executable(${PROJECT_NAME} main.cpp)
# target_link_libraries(${PROJECT_NAME} ${hello_LIBRARIES} )
第一句:cmake_minimum_required(VERSION 3.10)指明了cmake的需要的版本,向下兼容。
第二句:project的第一个参数定义了这个项目的名称。
第三句:是设置变量。这里设置了hello这个依赖库的搜索目录,下一句的find_package(hello REQUIRED)会去到hello_DIR这个变量指引的路径去寻找对应的helloConfig.cmake文件。helloConfig.cmake文件里面定义了hello_INCLUDE_DIRS变量所对应的路径和hello_LIBS变量所对应的路径。
第四句:fing_package所做的事情就是根据xxx_DIR路径找到xxxConfig.cmake文件,然后执行该文件得到xxx_INCLUDE_DIRS和xxx_LIBS变量,前者存放了所需要的头文件路径,后者指向了所需要用到的库路径。
include_directories()用来告诉编译器头文件都需要去哪里找。
link_libraries()用来告诉编译器所需要链接的库需要去哪找。
target_link_libraries()和link_libraries()的区别是后者作用在全局,而前者作用在此函数的第一个参数。
add_executable()表示需要生成可执行文件。
可以看出main执行文件的生成需要依赖hello这个库,再来看看hello的CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(hello VERSION 1.0.0)
set(world_DIR "${PROJECT_SOURCE_DIR}/../world/")
find_package(world REQUIRED)
set(CMAKE_CXX_STANDARD 11)
include_directories(${world_INCLUDE_DIRS})
link_libraries(${world_LIBRARIES})
add_library(${PROJECT_NAME} SHARED hello.cpp hello.h) #生成动态库
因为是生成动态库,这里用的是add_library()函数。
PROJECT_SOURCE_DIR是cmake默认生成的变量,表示的是CMakeLists.txt所在的路径。
再来看world的CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(world VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 11)
add_library(${PROJECT_NAME} SHARED world.cpp world.h) #生成动态库
可以看出main执行文件的生成依赖于hello库,hello动态库的生成又依赖于world库。
main中的CMakeLists.txt通过find_package()函数去找到hello_DIR路径下helloConfig.cmake,从而得到hello_INCLUDE_DIRS,hello_LIBS两个变量值。可以看下helloConfig.cmake里面的写法
set(hello_FOUND TRUE) # auto
set(hello_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}")
find_path(hello_INCLUDE_DIR NAMES hello.h PATHS "${hello_ROOT_DIR}")
find_library(hello_LIBRARY NAMES libhello.dylib PATHS "${hello_ROOT_DIR}/build")
set(world_DIR "${CMAKE_CURRENT_LIST_DIR}/../world/")
find_package(world REQUIRED)
if (world_FOUND)
set(hello_INCLUDE_DIRS ${hello_INCLUDE_DIR} ${world_INCLUDE_DIRS})
set(hello_LIBRARIES ${hello_LIBRARY} ${world_LIBRARIES})
endif()
message( "hello-config.cmake " ${hello_ROOT_DIR})
第一句:设置了一个bool变量,用来判断是否找成功。
第二句:CMAKE_CURRENT_LIST_DIR是cmake的内置变量,表示当前文件所在的路径。
find_path()用来查找头文件,第一个参数用来存放查找出来的存放头文件路径,NAME后面接需要查找的头文件的文件名,PATH后面接路径,告诉这个函数去这些路径下面找这些头文件。
find_library()则用来找库,用法与find_path()类似。
后面则用来找world库中的相关变量。
helloConfig.cmake又会去执行worldConfig.cmake,再来看一下worldConfig.cmake
set(world_FOUND TRUE) # auto
set(world_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}")
find_path(world_INCLUDE_DIR NAMES world.h PATHS "${world_ROOT_DIR}")
find_library(world_LIBRARY NAMES libworld.dylib PATHS "${world_ROOT_DIR}/build")
set(world_INCLUDE_DIRS ${world_INCLUDE_DIR} )
set(world_LIBRARIES ${world_LIBRARY} )
message( "world-config.cmake " ${world_ROOT_DIR})
其它:可以用message()函数打印出变量值
message(WARNING "======================hello_INCLUDE_DIRS=${hello_INCLUDE_DIRS}")