简体   繁体   English

如何正确链接库与 cmake?

[英]How to properly link libraries with cmake?

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.我正在使用 CLion,它使用 cmake 来构建它的项目。 I am trying to use several libraries in conjunction with OpenGL to texture some objects.我正在尝试将几个库与 OpenGL 结合使用来对某些对象进行纹理处理。 I initially built it in Visual Studio, because I couldn't ever figure out how to get cmake to work with Clion.我最初在 Visual Studio 中构建它,因为我无法弄清楚如何让 cmake 与 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.但是,既然代码都可以运行(无论如何在 Visual Studio 中),我希望能够使用 CLion,因为这是我首选的 IDE。

I am still new to cmake, and I don't understand what I am doing wrong with my CMakeLists.txt .我还是 cmake 的新手,我不明白我的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.我调整了它,直到它在 CLion 中不再给我任何错误,但我的代码中仍然无法识别头文件。

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: Clion 在项目中识别它们(它们不会因错误而显示为红色),但是当它构建时(当我尝试在 CLion 中运行它时),我收到以下错误:

CMakeFiles\texture_mapping.dir/objects.a(mesh.cpp.obj): In function `ZN4MeshD2Ev':
...texture-mapping/mesh.cpp:30: undefined reference to `_imp____glewDeleteVertexArrays'
CMakeFiles\texture_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\texture_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\texture_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\texture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6Shader4BindEv':
...texture-mapping/shader.cpp:28: undefined reference to `_imp____glewUseProgram'
CMakeFiles\texture_mapping.dir/objects.a(shader.cpp.obj): In function `ZN6Shader6UpdateERK9TransformRK6Camera':
...texture-mapping/shader.cpp:35: undefined reference to `_imp____glewUniformMatrix4fv'
CMakeFiles\texture_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\texture_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\texture_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\texture_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.基本上,每次使用 SDL 和 glew 都会出错,但不是 glm,这很奇怪。

What am I doing wrong with my CMakeLists.txt ?我的CMakeLists.txt什么问题?

My recommendation is to start simple, and then complicate your project further.我的建议是从简单的开始,然后使您的项目进一步复杂化。

Let me try to explain how linking works in CMake.让我试着解释一下 CMake 中的链接是如何工作的。 The idea is that you build modules in CMake, and link them together.这个想法是你在 CMake 中构建模块,并将它们链接在一起。 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.假设您有 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 .现在您将它们添加到名为LibsModule的模块中。 Keep that in mind.记在脑子里。 Say you want to link to pthread for example that's already in the system.假设您想链接到系统中已经存在的pthread You can combine it with LibsModule using the command:您可以使用以下命令将其与LibsModule结合使用:

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). (我添加了 BlaBla 只是为了表明名称是自定义的)。 And then you link LibsModule with your executable module MyProgramExecBlaBla然后你将LibsModule与你的可执行模块MyProgramExecBlaBla链接LibsModule

target_link_libraries(MyProgramExecBlaBla LibsModule)

And this will do it.这将做到。

What I see in your CMake file is a lot of redundancy.我在你的 CMake 文件中看到的是很多冗余。 For example, why do you have texture_mapping , which is an executable module in your include directories?例如,为什么你有texture_mapping ,它是你的包含目录中的一个可执行模块? 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.注意:请记住,这是使用 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.更好的跨平台方式是使用find_package ,它定位一个包/库,并提供库和包含在 CMake 变量中,以便您可以将您的程序链接到它们。 Here's how to do this for boost , for example.例如,以下是如何为 boost 执行此操作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM