一、首先介绍cmake实践中的做法
在/backup/cmake/目录中建立t6目录,并在其中建立cmake 目录用于存放我们自己定义的FindHELLO.cmake模块,同时建立src目录,用于存放我们的源文件。
1,定义 cmake/FindHELLO.cmake模块
1 FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello/usr/local/include/hello) 2 FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/lib/usr/local/lib) 3 IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY) 4 SET(HELLO_FOUND TRUE) 5 ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY) 6 IF (HELLO_FOUND) 7 IF (NOT HELLO_FIND_QUIETLY) 8 MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}") 9 ENDIF (NOT HELLO_FIND_QUIETLY) 10 ELSE (HELLO_FOUND) 11 IF (HELLO_FIND_REQUIRED) 12 MESSAGE(FATAL_ERROR "Could not find hello library") 13 ENDIF (HELLO_FIND_REQUIRED) 14 ENDIF (HELLO_FOUND)
以上代码为CMake Practice中的做法,1~2行首先查找之前的例子t3中安装的头文件和库文件,3~5行若查找结果为真,设置HELLO_FOUND的值为TRUE。6~14行则是根据查找结果输出是否查找到hello库文件的消息。
2,建立src/main.c和该文件夹下的CMakeLists.txt
src/main.c中的内容为
1 #include <hello.h> 2 int main() 3 { 4 HelloFunc(); 5 return 0; 6 }
建立src/CMakeLists.txt 文件,内容如下:
1 FIND_PACKAGE(HELLO) 2 IF(HELLO_FOUND) 3 ADD_EXECUTABLE(hello main.c) 4 INCLUDE_DIRECTORIES(${HELLO_INCLUDE_DIR}) 5 TARGET_LINK_LIBRARIES(hello ${HELLO_LIBRARY}) 6 ENDIF(HELLO_FOUND)
为了能够让工程找到FindHELLO.cmake模块(存放在工程中的 cmake目录),我们在主工程文件CMakeLists.txt 中加入:
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
3,使用自定义的FindHELLO 模块构建工程,仍然采用外部编译的方式,建立build 目录,进入目录运行:cmake ..
我们可以从输出中看到:Found Hello: /usr/lib/libhello.so
接下来就可以使用make命令构建工程,运行:
./src/hello可以得到输出:Hello World。
说明工程成功构建。
二、下面介绍我遇到的问题和解决方法
由于本人在t3的例子中安装路径为自定义的路径,因此我最初将1~2行中的路径改为了自定义的路径,然后构建工程,但是遇到了以下三个问题。
第1个问题:
CMake Warning at src/CMakeLists.txt:3 (find_package): By not providing "FindHELLO.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "HELLO", but CMake did not find one. Could not find a package configuration file provided by "HELLO" with any of the following names: HELLOConfig.cmake hello-config.cmake Add the installation prefix of "HELLO" to CMAKE_PREFIX_PATH or set "HELLO_DIR" to a directory containing one of the above files. If "HELLO" provides a separate development package or SDK, be sure it has been installed.
通过查阅网上的资料我找到了问题所在,这是由于主工程文件CMakeLists.txt 中SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)放在了add_subdirectory(src)位置的后面,导致src文件夹中的CMakeLists.txt文件查找HELLO时没有指定FindHELLO.cmake,因此将SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)放在add_subdirectory(src)之前即可。
第2个问题:
src/CMakeLists.txt 文件中的IF(HELLO_FOUND)始终没有成立,导致工程始终无法构建成功。如下图所示,首先cmake ..时没有提示“Found Hello: ${HELLO_LIBRARY}”或者"Could not find hello library",其次make时没有任何反应。
追溯到FindHELLO.cmake文件中,我认为是最开始查找路径没有成功,导致HELLO_FOUND变量没有设置为TRUE。经过一番周折,一个偶然的尝试我发现将cmake/FindHELLO.cmake模块中的1~2行修改为下面这两行的格式,其他的保持不变可以解决这个问题(其中的路径为自定义的头文件和库文件安装路径)。
1 FIND_PATH(HELLO_INCLUDE_DIR hello.h /home/lwl/cmakepractice/include/hello) 2 FIND_LIBRARY(HELLO_LIBRARY hello /home/lwl/cmakepractice/lib)
第3个问题:
当完成上述的内容后,我以为已经无误了,但是仍面临最后一个问题,这个问题是由于自定义安装位置引起的,在此前的CMake Practice案例中我也遇到过一次,因此仍有印象。
具体的问题表现为下图
这是由于src/CMakeLists.txt 文件中没有链接成功引起的,但如果按照作者的安装路径理论上没什么问题,由于我的安装路径为/home/lwl/cmakepractice/lib,属于非标准的共享库搜索路径,需要用到作者在t4中介绍的一个指令LINK_DIRECTORIES(directory1 directory2 ...)将该路径添加到src/CMakeLists.txt 文件中,因此修改后的此文件内容为
1 link_directories(/home/lwl/cmakepractice/lib) 2 find_package(HELLO) 3 if(HELLO_FOUND) 4 include_directories(${HELLO_INCLUDE_DIR}) 5 add_executable(main main.cpp) 6 target_link_libraries(main libhello.so) 7 message(STATUS "HELLO library has found") 8 endif(HELLO_FOUND)
删除掉之前编译的中间文件,再次进入到build文件夹进行cmake ..
可以看到提示Found Hello:/home/lwl/cmakepractice/lib/libhello.so。同时make成功,正确输出“Hello World!”。
至此问题全部解决。
学习cmake实践t6:自定义FindHELLO模块并使用这个模块构建工程时遇到的问题与解决方法
原文:https://www.cnblogs.com/54lwl/p/14444332.html