如何正确链接库与 cmake?

2021-12-19 00:00:00 opengl cmake c++ undefined-reference

我无法将正在使用的其他库正确链接到我的项目中.

我正在使用 CLion,它使用 cmake 来构建它的项目.我正在尝试将几个库与 OpenGL 结合使用来对某些对象进行纹理处理.我最初在 Visual Studio 中构建它,因为我无法弄清楚如何让 cmake 与 Clion 一起工作.但是,既然代码都可以运行(无论如何在 Visual Studio 中),我希望能够使用 CLion,因为这是我的首选 IDE.

我还是 cmake 的新手,我不明白我的 CMakeLists.txt 做错了什么.这是我所拥有的:

cmake_minimum_required(VERSION 3.3)项目(纹理映射)find_package(需要OpenGL)链接目录(${OPENGL_gl_LIBRARY})设置(CMAKE_CXX_FLAGS${CMAKE_CXX_FLAGS} -std=c++11")设置(SOURCE_FILES main.cpp camera.h display.h display.cpp mesh.cpp mesh.h obj_loader.cpp obj_loader.h shader.cpp shader.h stb_image.c stb_image.h texture.cpp texture.h transform.h)链接目录(纹理映射${PROJECT_SOURCE_DIR}/lib)添加可执行文件(纹理映射${SOURCE_FILES})target_include_directories(texture_mapping PUBLIC ${PROJECT_SOURCE_DIR}/include)target_link_libraries(texture_mapping SDL2 SDL2main SDL2test glew32 glew32s ${OPENGL_gl_LIBRARY})

我对其进行了调整,直到它在 CLion 中不再给我任何错误为止,但是我的代码中仍然无法识别头文件.

这是我的项目结构:

所以,我把我需要的所有库都放进去了,但它似乎没有在代码中识别它们.Clion 在项目中识别它们(它们不会因错误而显示为红色),但是在构建时(当我尝试在 CLion 中运行它时),我收到以下错误:

CMakeFiles	exture_mapping.dir/objects.a(mesh.cpp.obj):在函数`ZN4MeshD2Ev'中:...纹理映射/mesh.cpp:30: 未定义对`_imp____glewDeleteVertexArrays'的引用CMakeFiles	exture_mapping.dir/objects.a(mesh.cpp.obj):在函数`ZN4Mesh8InitMeshERK12IndexedModel'中:...纹理映射/mesh.cpp:36: 未定义对`_imp____glewGenVertexArrays'的引用...纹理映射/mesh.cpp:37: 未定义对`_imp____glewBindVertexArray'的引用...texture-mapping/mesh.cpp:39: 对`_imp____glewGenBuffers' 的未定义引用...texture-mapping/mesh.cpp:40: 对`_imp____glewBindBuffer' 的未定义引用...纹理映射/mesh.cpp:41: 未定义对`_imp____glewBufferData'的引用...纹理映射/mesh.cpp:43:未定义对`_imp____glewEnableVertexAttribArray'的引用...纹理映射/mesh.cpp:44:未定义对`_imp____glewVertexAttribPointer'的引用...纹理映射/mesh.cpp:46: 未定义对`_imp____glewBindBuffer'的引用...纹理映射/mesh.cpp:47: 未定义对`_imp____glewBufferData'的引用...纹理映射/mesh.cpp:49:未定义对`_imp____glewEnableVertexAttribArray'的引用...纹理映射/mesh.cpp:50:未定义对`_imp____glewVertexAttribPointer'的引用...纹理映射/mesh.cpp:52: 未定义对`_imp____glewBindBuffer'的引用...纹理映射/mesh.cpp:53: 未定义对`_imp____glewBufferData'的引用...纹理映射/mesh.cpp:55: 未定义对`_imp____glewBindVertexArray'的引用...纹理映射/mesh.cpp:56:未定义对`_imp____glewBindVertexArray'的引用CMakeFiles	exture_mapping.dir/objects.a(mesh.cpp.obj):在函数`ZN4Mesh4DrawEv'中:...纹理映射/mesh.cpp:61: 未定义对`_imp____glewBindVertexArray'的引用...纹理映射/mesh.cpp:65: 未定义对`_imp____glewBindVertexArray'的引用CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj):在函数‘ZN6ShaderC2ERKSs’中:...纹理映射/着色器.cpp:5:对`_imp____glewCreateProgram'的未定义引用...texture-mapping/shader.cpp:11: 未定义对`_imp____glewAttachShader'的引用...texture-mapping/shader.cpp:14: 未定义对`_imp____glewBindAttribLocation'的引用...texture-mapping/shader.cpp:15: 对`_imp____glewBindAttribLocation' 的未定义引用...texture-mapping/shader.cpp:17: 未定义对`_imp____glewLinkProgram'的引用...texture-mapping/shader.cpp:20: 对`_imp____glewValidateProgram' 的未定义引用...纹理映射/shader.cpp:23:对`_imp____glewGetUniformLocation'的未定义引用CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj):在函数`ZN6Shader4BindEv'中:...texture-mapping/shader.cpp:28: 未定义对`_imp____glewUseProgram'的引用CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj):在函数`ZN6Shader6UpdateERK9TransformRK6Camera'中:...texture-mapping/shader.cpp:35: 未定义对`_imp____glewUniformMatrix4fv'的引用CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj):在函数‘ZN6ShaderD2Ev’中:...texture-mapping/shader.cpp:42: 未定义对`_imp____glewDetachShader'的引用...texture-mapping/shader.cpp:43: 对`_imp____glewDeleteShader' 的未定义引用...texture-mapping/shader.cpp:46: 对`_imp____glewDeleteProgram' 的未定义引用CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj):在函数`ZN6Shader16CheckShaderErrorEjjbRKSs'中:...texture-mapping/shader.cpp:79: 对`_imp____glewGetProgramiv' 的未定义引用...texture-mapping/shader.cpp:81: 未定义对`_imp____glewGetShaderiv'的引用...texture-mapping/shader.cpp:86: 未定义对`_imp____glewGetProgramInfoLog'的引用...texture-mapping/shader.cpp:88: 未定义对`_imp____glewGetShaderInfoLog'的引用CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj):在函数`ZN6Shader12CreateShaderERKSsj'中:...texture-mapping/shader.cpp:96: 未定义对`_imp____glewCreateShader'的引用...texture-mapping/shader.cpp:109: 未定义对`_imp____glewShaderSource'的引用...texture-mapping/shader.cpp:110: 未定义对`_imp____glewCompileShader'的引用CMakeFiles	exture_mapping.dir/objects.a(texture.cpp.obj):在函数‘ZN7Texture4BindEj’中:...texture-mapping/texture.cpp:36: 未定义对`_imp____glewActiveTexture'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x24): 未定义对`SDL_SetMainReady'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x55): 对`SDL_malloc'的未定义引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x84): 未定义对`SDL_wcslen'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0xa5):对`SDL_iconv_string'的未定义引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0xcf): 未定义对`SDL_free'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0xf4): 未定义对`SDL_wcslen'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x10f): 未定义对`SDL_iconv_string'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x143): 未定义对`SDL_malloc'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x17f): 对‘SDL_free’的未定义引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x18b): 未定义对`SDL_free'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x1d6):对`SDL_isspace'的未定义引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x295): 未定义对`SDL_isspace'的引用...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x3a2):对`SDL_ShowSimpleMessageBox'的未定义引用

基本上,每次使用 SDL 和 glew 都会出错,但不是 glm,这很奇怪.

我的 CMakeLists.txt 有什么问题?

解决方案

我的建议是从简单开始,然后进一步复杂化您的项目.

让我试着解释一下 CMake 中的链接是如何工作的.这个想法是你在 CMake 中构建模块,并将它们链接在一起.让我们暂时忽略头文件,因为它们都可以包含在您的源文件中.

假设您有 file1.cpp、file2.cpp、main.cpp.您可以通过以下方式将它们添加到您的项目中:

ADD_LIBRARY(LibsModule文件1.cpp文件2.cpp)

现在您将它们添加到名为 LibsModule 的模块中.记住这一点.假设您想链接到 pthread 例如,它已经在系统中.您可以使用以下命令将其与 LibsModule 结合使用:

target_link_libraries(LibsModule -lpthread)

如果你也想链接一个静态库,你可以这样做:

target_link_libraries(LibsModule liblapack.a)

如果您想添加任何这些库所在的目录,请执行以下操作:

target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)

现在您添加一个可执行文件,并将其与您的主文件链接:

ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)

(我添加了 BlaBla 只是为了表明名称是自定义的).然后你将 LibsModule 与你的可执行模块 MyProgramExecBlaBla

链接起来

target_link_libraries(MyProgramExecBlaBla LibsModule)

这就行了.

我在你的 CMake 文件中看到的是很多冗余.例如,为什么您有 texture_mapping,它是包含目录中的一个可执行模块?所以你需要清理它并遵循我解释的简单逻辑.希望它有效.

<小时>

总而言之,它看起来像这样:

project (MyProgramExecBlaBla) #不确定这是否应该是可执行文件的同名,但我总是看到约定"cmake_minimum_required(版本 2.8)ADD_LIBRARY(库模块文件1.cpp文件2.cpp)目标链接库(LibsModule -lpthread)target_link_libraries(LibsModule liblapack.a)target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)目标链接库(MyProgramExecBlaBla LibsModule)

要理解的最重要的事情是模块结构,您可以在其中创建模块并将它们与可执行文件链接在一起.一旦成功,您可以通过更多细节进一步复杂化您的项目.祝你好运!

<小时>

注意:请记住,这是使用 CMake 的简单方法.更好的跨平台方式是使用 find_package,它定位一个包/库,并提供库和包含在 CMake 变量中,以便您可以将您的程序链接到它们.例如,这里是如何为 boost 执行此操作.>

I can't get the additional libraries I am working with to link into my project properly.

I am using CLion, which uses cmake to build it's projects. I am trying to use several libraries in conjunction with OpenGL to texture some objects. I initially built it in Visual Studio, because I couldn't ever figure out how to get cmake to work with Clion. However, now that the code is all working (in Visual Studio, anyways), I want to be able to use CLion for it, because that is my preferred IDE.

I am still new to cmake, and I don't understand what I am doing wrong with my CMakeLists.txt. Here is what I have:

cmake_minimum_required(VERSION 3.3)
project(texture_mapping)
find_package(OpenGL REQUIRED)
link_directories(${OPENGL_gl_LIBRARY})

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES main.cpp camera.h display.h display.cpp mesh.cpp mesh.h obj_loader.cpp obj_loader.h shader.cpp shader.h stb_image.c stb_image.h texture.cpp texture.h transform.h)

link_directories(texture_mapping ${PROJECT_SOURCE_DIR}/lib)

add_executable(texture_mapping ${SOURCE_FILES})

target_include_directories(texture_mapping PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(texture_mapping SDL2 SDL2main SDL2test glew32 glew32s ${OPENGL_gl_LIBRARY})

I tweaked it until it didn't give me any more errors in CLion, but the header files are still not recognized in my code.

Here is the structure of my project:

So, I put all of the libraries I needed, but it doesn't appear to be recognizing them in the code. Clion recognizes them in the project (they aren't appearing red with errors), but when it is built (when I attempt to run it in CLion), I get these errors:

CMakeFiles	exture_mapping.dir/objects.a(mesh.cpp.obj): In function `ZN4MeshD2Ev':
...texture-mapping/mesh.cpp:30: undefined reference to `_imp____glewDeleteVertexArrays'
CMakeFiles	exture_mapping.dir/objects.a(mesh.cpp.obj): In function `ZN4Mesh8InitMeshERK12IndexedModel':
...texture-mapping/mesh.cpp:36: undefined reference to `_imp____glewGenVertexArrays'
...texture-mapping/mesh.cpp:37: undefined reference to `_imp____glewBindVertexArray'
...texture-mapping/mesh.cpp:39: undefined reference to `_imp____glewGenBuffers'
...texture-mapping/mesh.cpp:40: undefined reference to `_imp____glewBindBuffer'
...texture-mapping/mesh.cpp:41: undefined reference to `_imp____glewBufferData'
...texture-mapping/mesh.cpp:43: undefined reference to `_imp____glewEnableVertexAttribArray'
...texture-mapping/mesh.cpp:44: undefined reference to `_imp____glewVertexAttribPointer'
...texture-mapping/mesh.cpp:46: undefined reference to `_imp____glewBindBuffer'
...texture-mapping/mesh.cpp:47: undefined reference to `_imp____glewBufferData'
...texture-mapping/mesh.cpp:49: undefined reference to `_imp____glewEnableVertexAttribArray'
...texture-mapping/mesh.cpp:50: undefined reference to `_imp____glewVertexAttribPointer'
...texture-mapping/mesh.cpp:52: undefined reference to `_imp____glewBindBuffer'
...texture-mapping/mesh.cpp:53: undefined reference to `_imp____glewBufferData'
...texture-mapping/mesh.cpp:55: undefined reference to `_imp____glewBindVertexArray'
...texture-mapping/mesh.cpp:56: undefined reference to `_imp____glewBindVertexArray'
CMakeFiles	exture_mapping.dir/objects.a(mesh.cpp.obj): In function `ZN4Mesh4DrawEv':
...texture-mapping/mesh.cpp:61: undefined reference to `_imp____glewBindVertexArray'
...texture-mapping/mesh.cpp:65: undefined reference to `_imp____glewBindVertexArray'
CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6ShaderC2ERKSs':
...texture-mapping/shader.cpp:5: undefined reference to `_imp____glewCreateProgram'
...texture-mapping/shader.cpp:11: undefined reference to `_imp____glewAttachShader'
...texture-mapping/shader.cpp:14: undefined reference to `_imp____glewBindAttribLocation'
...texture-mapping/shader.cpp:15: undefined reference to `_imp____glewBindAttribLocation'
...texture-mapping/shader.cpp:17: undefined reference to `_imp____glewLinkProgram'
...texture-mapping/shader.cpp:20: undefined reference to `_imp____glewValidateProgram'
...texture-mapping/shader.cpp:23: undefined reference to `_imp____glewGetUniformLocation'
CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6Shader4BindEv':
...texture-mapping/shader.cpp:28: undefined reference to `_imp____glewUseProgram'
CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6Shader6UpdateERK9TransformRK6Camera':
...texture-mapping/shader.cpp:35: undefined reference to `_imp____glewUniformMatrix4fv'
CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6ShaderD2Ev':
...texture-mapping/shader.cpp:42: undefined reference to `_imp____glewDetachShader'
...texture-mapping/shader.cpp:43: undefined reference to `_imp____glewDeleteShader'
...texture-mapping/shader.cpp:46: undefined reference to `_imp____glewDeleteProgram'
CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6Shader16CheckShaderErrorEjjbRKSs':
...texture-mapping/shader.cpp:79: undefined reference to `_imp____glewGetProgramiv'
...texture-mapping/shader.cpp:81: undefined reference to `_imp____glewGetShaderiv'
...texture-mapping/shader.cpp:86: undefined reference to `_imp____glewGetProgramInfoLog'
...texture-mapping/shader.cpp:88: undefined reference to `_imp____glewGetShaderInfoLog'
CMakeFiles	exture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6Shader12CreateShaderERKSsj':
...texture-mapping/shader.cpp:96: undefined reference to `_imp____glewCreateShader'
...texture-mapping/shader.cpp:109: undefined reference to `_imp____glewShaderSource'
...texture-mapping/shader.cpp:110: undefined reference to `_imp____glewCompileShader'
CMakeFiles	exture_mapping.dir/objects.a(texture.cpp.obj): In function `ZN7Texture4BindEj':
...texture-mapping/texture.cpp:36: undefined reference to `_imp____glewActiveTexture'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x24): undefined reference to `SDL_SetMainReady'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x55): undefined reference to `SDL_malloc'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x84): undefined reference to `SDL_wcslen'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0xa5): undefined reference to `SDL_iconv_string'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0xcf): undefined reference to `SDL_free'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0xf4): undefined reference to `SDL_wcslen'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x10f): undefined reference to `SDL_iconv_string'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x143): undefined reference to `SDL_malloc'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x17f): undefined reference to `SDL_free'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x18b): undefined reference to `SDL_free'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x1d6): undefined reference to `SDL_isspace'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x295): undefined reference to `SDL_isspace'
...texture-mapping/lib/SDL2main.lib(./Win32/Release/SDL_windows_main.obj):(.text+0x3a2): undefined reference to `SDL_ShowSimpleMessageBox'

Basically, errors with every usage of SDL and glew, but not glm, which is strange.

What am I doing wrong with my CMakeLists.txt?

解决方案

My recommendation is to start simple, and then complicate your project further.

Let me try to explain how linking works in CMake. The idea is that you build modules in CMake, and link them together. Let's ignore header files for now, as they can be all included in your source files.

Say you have file1.cpp, file2.cpp, main.cpp. You add them to your project with:

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

Now you added them to a module called LibsModule. Keep that in mind. Say you want to link to pthread for example that's already in the system. You can combine it with LibsModule using the command:

target_link_libraries(LibsModule -lpthread)

And if you want to link a static library to that too, you do this:

target_link_libraries(LibsModule liblapack.a)

And if you want to add a directory where any of these libraries are located, you do this:

target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)

Now you add an executable, and you link it with your main file:

ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)

(I added BlaBla just to make it clear that the name is custom). And then you link LibsModule with your executable module MyProgramExecBlaBla

target_link_libraries(MyProgramExecBlaBla LibsModule)

And this will do it.

What I see in your CMake file is a lot of redundancy. For example, why do you have texture_mapping, which is an executable module in your include directories? So you need to clean this up and follow the simple logic I explained. Hopefully it works.


In summary, it looks like this:

project (MyProgramExecBlaBla)  #not sure whether this should be the same name of the executable, but I always see that "convention"
cmake_minimum_required(VERSION 2.8)

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule liblapack.a)
target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)
ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)
target_link_libraries(MyProgramExecBlaBla LibsModule)

The most important thing to understand is the module structure, where you create modules and link them all together with your executable. Once this works, you can complicate your project further with more details. Good luck!


Note: Keep in mind that this is the simple way to use CMake. The better cross-platform way would be using find_package, which locates a package/library, and provides the libraries and includes in CMake variables so that you could link your program to them. Here's how to do this for boost, for example.

相关文章