引言
学习LearnOpenGL时配置自己的的CMakeLists真的泰坑辣!特做记录!
- 背景:在自己电脑上配过完整的环境并写了对应的CMakeLists,现在实习在师傅电脑的拷贝机上配环境,所以有部分环境是有的,有部分环境是没有的,于是。。。我走上了不归路!
- 坑1:用别人的环境时,一定要检查一下环境里的动态链接库的名称!它们可能并不会用常用的名称(毕竟老师傅懂这块,他们不会按教程一步步来)
- 坑2:咱也不懂cmake具体的语法,网上看博客都老长一段,你根本不知道哪些对自己有用,所以这时候文件的路径非常重要!!!!!!
Reference
can not find -lxxxx
can not find -lxxxx
一、LearnOpenGL的最简CMakeLists写法及讲解
cmake_minimum_required (VERSION 2.8)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
project(P1)
find_package(glfw3 REQUIRED)
file(GLOB project_file glad.c stb_image.cpp main.cpp)
add_executable(${PROJECT_NAME} ${project_file})
target_link_libraries(${PROJECT_NAME}
-lglfw
-lGL
-lm
-lXrandr
-lXi
-lX11
-lXxf86vm
-lpthread
-ldl
-lXinerama
-lXcursor
)
- cmake_minimum_required():其作用是指定当前项目所需的CMake的最低版本号,这个函数必须要放在CMakeLists.txt文件的开头,如果你系统中安装的版本低于这个版本号就会报错。
- set(CMAKE_C_STANDARD 11):指定了当前项目的C编译器应该遵循C11标准。通过这种方式设置C标准,可以确保代码能够在符合标准的环境下编译和运行,同时还能提高代码的可移植性。
- project():用于定义项目的名称
- find_package():用于查找和加载第三方库或工具的配置文件。在使用find_package函数时,需要指定要查找的库的名称,并通过变量将其引入到项目中。其中glfw3表示要查找的库,REQUIRED表示这个库是必须存在的,如果找不到就会停止make。
- file(GLOB):使用了file()命令和GLOB选项,用于匹配指定目录下的文件。具体来说,file(GLOB project_file glad.c stb_image.cpp main.cpp)会在当前目录下查找并将所有名为"glad.c"、"stb_image.cpp"和"main.cpp"的文件匹配到一个名为project_file的变量中。这个变量可以在后面的CMake命令中使用。需要注意的是,尽管使用GLOB可以方便地匹配多个文件,但也存在一些潜在的问题。因为GLOB只在CMake生成构建脚本时运行一次,所以如果在执行CMake之后添加或删除了匹配的文件,则可能导致构建失败。因此,在实际开发中,应该尽量避免使用GLOB。
- add_executable(${PROJECT_NAME} ${project_file}):该函数用于定义project的可执行文件。project_name是在前面使用project函数定义的项目名称。project_file是一个包含了所有需要编译的源文件的变量。因此这句代码实际上是将这些源文件编译成一个名为project_name的可执行文件。
- ==target_link_libraries()==这段代码用于将项目的可执行文件project_name与系统中的一些动态链接库进行链接。----->这个库和file()中添加的stb_image.cpp这种库有什么区别?file()直接把这个库加入到你的工程,是静态链接,快但是浪费内存。而动态链接就是只把调用路径加到你的工程里,你执行到这里的时候再根据链接来找源码,慢但节约内存。
二、如何根据自己的路径修改上面的文件(踩坑记录)
- 我们将CMakeLists放在了P1文件夹下,然后需要为其编译glad.c stb_image.cpp glfw3.h等。
- glad.c的坑:因为我们是file(glad.c)的方式,这句话的意思就是你要把file路径下 gald.c加入工程源码,所以glad.c要放在P1文件夹下(和CMakeLists文件处于同级目录)。否则会显示一堆undefine reference glad.xxxx(),这很好理解,没找到glad.c这个文件,编译时当然undefine了。
- stb_image.cpp的坑
因为stb_image.h是一个只有头文件的库,而我们在file()中需要将其cpp加入工程源码,此时需要在如图的同级目录下新建其相应的cpp文件,并定义相应的宏。这个宏名为STB_IMAGE_IMPLEMENTATION,它会在引用stb_image.h时启用stb_image的实现代码。(这个对纯粹头文件库是必须的,此类库的实现代码需要在一个单独的源文件中包含和编译(所以要新建一个)。通过定义该宏,可以将源文件中的实现代码加入到工程源码中)
- glfw的坑之你究竟是glfw3还是glfw? 这真的很坑!
先总结:答案是不重要,它头文件是啥,你就include啥,它动态链接库是啥,你就链接啥!接下来看看为什么具体叫什么不重要,相应位置对上了就行!如图是我目前机器(师傅拷贝机)的链接库:
为什么这么写?讲一下修改过程:
一开始我也是写的-lglfw3(因为之前在自己笔记本上配环境的时候就是这么写的,程序都能跑),但是报错can not find glfw3。遇到这个问题你去搜索,会千篇一律的给你一个答复:can not find -lxxx怎么解决?答案就是看看你本地有没有动态链接库?如果有看看路径对不对?如果没有就下载链接一个。这步看这篇看两篇引用博客就行。然而我试完了发现都不行。因为我本地是有这个链接库的(因为是我师傅机子的拷贝机,所以有部分配置好的环境)如图。
(文件前面的路径是/usr/lib,自己补全哈,任何和公司相关的东西都不能放)
所以你可以发现我们生成的动态链接库叫libglfw而不是libglfw3!破案了!你为一个库生成链接库的时候你可以写自己要的名字,而在CMakeLists中要写个.so对应的名字,这里没3所以你在cmake里写3它肯定找不到啊,改为-lglfw问题解决。