CMake第四课--编写程序使用上一节安装的库和头文件
CMake第四课 编写程序使用上一节安装的库和头文件
一.完整过程
手把手教你学CMake,上一节我们将自己写的头文件和共享库安装到了电脑上 。这一节,我们将编写程序,应用上一节安装的头文件和库文件。
===================================================================================
绝对路径:/home/guo/cmake_practice/4(工程目录)
---------------------------------------------------------------------------------------------------------------------------------------------------
目标:编写一个程序使用我们上一节构建的共享库
安装的头文件在/home/guo/cmake_practice/3/include/hello下
安装的库在 /home/guo/cmake_practice/3/include/lib下
---------------------------------------------------------------------------------------------------------------------------------------------------
工程目录结构(按照下面结构添加文件夹和文件):
1.编写工程主文件(/home/guo/cmake_practice/4) CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) # 声明要求的 cmake 最低版本 PROJECT(NEWHELLO) # 声明一个 cmake 工程 ADD_SUBDIRECTORY(src)
2.建立 src 目录(/home/guo/cmake_practice/4/src),编写源文件 main.cpp和CMakeLists.txt。
src/main.cpp内容如下:
#include <hello.h> int main() { HelloFunc(); return 0; }
src/CMakeLists.txt内容如下:
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) # 声明要求的 cmake 最低版本 INCLUDE_DIRECTORIES(/home/guo/cmake_practice/3/include/hello) LINK_DIRECTORIES(/home/guo/cmake_practice/3/include/lib) ADD_EXECUTABLE(main main.cpp) TARGET_LINK_LIBRARIES(main libhello.so) #TARGET_LINK_LIBRARIES(main libhello.a)
---------------------------------------------------------------------------------------------------------------------------------------------------
外部编译
cd /home/guo/cmake_practice/4
mkdir build (新建build文件夹)
cd build
cmake ..
make
执行二进制可执行文件
cd /home/guo/cmake_practice/4/build/src
./main
编译完之后我们就可以进入build/src文件夹,运行二进制程序。
====================================================================================
二.详细解释
1.由于hello.h 位于/home/guo/ cmake_practice/3/include/hello 目录中,并没有位于系统标准的头文件路径(/usr/include, /usr/local/include 等),为了让我们的工程能够找到 hello.h 头文件,我们需要引入一个新的指令INCLUDE_DIRECTORIES,它的语法规则是:
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径中包含了空格,可以使用双引号将它括起来。默认的行为是追加到当前的头文件搜索路径的后面,你可以通过两种方式来进行控制搜索路径添加的方式:
- 第一种方式,CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过 SET 这个 cmake 变量为 on,可以将添加的头文件搜索路径放在已有路径的前面。
- 第二种方式,通过 AFTER 或者 BEFORE 参数,也可以控制是追加还是置前。
2.虽然我们引用好了头文件,但我们还需要将目标文件链接到 libhello,不然就会报HelloFunc 未定义错误。这里我们需要引入两个新的指令LINK_DIRECTORIES 和 TARGET_LINK_LIBRARIES。
- LINK_DIRECTORIES 的全部语法是: LINK_DIRECTORIES(directory1 directory2 ...) 添加非标准的共享库搜索路径,比如,在工程内部同时存在共享库和可执行二进制,在编译时就需要指定一下这些共享库的路径。
- TARGET_LINK_LIBRARIES 的全部语法是: TARGET_LINK_LIBRARIES(target library1
<debug | optimized> library24 ...)
这个指令可以用来为 target 添加需要链接的共享库。
3.从build文件夹中打开终端,输入ldd src/main,检查一下 main 的链接情况。
4.如何链接到静态库呢?
将 TARGET_LINK_LIBRRARIES 指令修改为: TARGET_LINK_LIBRARIES(main libhello.a)
---------------------------------------------------------------------------------------------------------------------------------------------------
三. 介绍两个特殊的环境变量 CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH
注意:这两个是环境变量而不是 cmake 变量!使用方法是: 在.bashrc中用 export CMAKE_INCLUDE_PATH=/home/include/cmake ..
如果头文件没有存放在常规路径(/usr/include, /usr/local/include 等),则可以通过这些变量进行弥补。我们以本例中的 hello.h 为例,它存放在/home/guo/ cmake_practice/3/include/hello目录,所以直接查找肯定是找不到的。前面我们直接使用了绝对路径 INCLUDE_DIRECTORIES(/home/guo/ cmake_practice/3/include/hello)告诉工程这个头文件目录。
①.为了将程序更智能一点,我们可以使用 CMAKE_INCLUDE_PATH 来进行,使用 bash 的方法如下:
- 开终端输入:gedit ~/.bashrc
- 打开.bashrc后,写入
export CMAKE_INCLUDE_PATH=/home/guo/cmake_practice/3/include/hello
- 再输入:source ~/.bashrc
②.然后在src/CMakeLists.txt文件中将 INCLUDE_DIRECTORIES(/home/guo/ cmake_practice/3/include/hello)替换为:
FIND_PATH(myHeader hello.h) #名字myHeader随便取,不影响
IF(myHeader)
INCLUDE_DIRECTORIES(${myHeader})
ENDIF(myHeader)
- 这里简单说明一下,FIND_PATH 用来在指定路径中搜索文件名,比如: FIND_PATH(myHeader NAMES hello.h PATHS /home/guo/ cmake_practice/3/include/hello)。这里我们没有指定路径,但是,cmake 仍然可以帮我们找到 hello.h 存放的路径,就是因为我们设置了环境变量 CMAKE_INCLUDE_PATH。
- 如果你不使用FIND_PATH命令 ,CMAKE_INCLUDE_PATH 变量的设置对编译器是没有作用的,你不能指望它会直接为编译器命令添加参数<CMAKE_INCLUDE_PATH>。
- 以此为例,CMAKE_LIBRARY_PATH 可以用在 FIND_LIBRARY 中。同样,因为这些变量直接为 FIND_指令所使用,所以所有使用 FIND_指令的 cmake 模块都会受益。