web-dev-qa-db-de.com

Wie kann ich Bibliotheken richtig mit cmake verknüpfen?

Die zusätzlichen Bibliotheken, mit denen ich arbeite, können nicht ordnungsgemäß in mein Projekt eingebunden werden.

Ich benutze CLion, das cmake verwendet, um seine Projekte zu erstellen. Ich versuche, mehrere Bibliotheken in Verbindung mit OpenGL zu verwenden, um einige Objekte zu texturieren. Ich habe es ursprünglich in Visual Studio erstellt, weil ich nie herausgefunden habe, wie ich cmake dazu bringen kann, mit Clion zu arbeiten. Da der Code jetzt jedoch alle funktioniert (in Visual Studio), möchte ich CLion dafür verwenden können, da dies meine bevorzugte IDE ist.

Ich bin noch ein Neuling und verstehe nicht, was ich mit meinem CMakeLists.txt Falsch mache. Folgendes habe ich:

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})

Ich habe es optimiert, bis es in CLion keine Fehler mehr gab, aber die Header-Dateien werden in meinem Code immer noch nicht erkannt.

Hier ist die Struktur meines Projekts:
project structure

Also habe ich alle Bibliotheken abgelegt, die ich brauchte, aber es scheint, als würde es sie nicht im Code erkennen. Clion erkennt sie im Projekt (sie erscheinen nicht rot mit Fehlern), aber wenn es erstellt wird (wenn ich versuche, es in CLion auszuführen), erhalte ich diese Fehler:

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'

Grundsätzlich Fehler bei jeder Verwendung von SDL und GLEW, aber nicht GLM, was seltsam ist.

Was mache ich falsch mit meinem CMakeLists.txt?

24
Cache Staheli

Meine Empfehlung ist, einfach anzufangen und dann Ihr Projekt weiter zu komplizieren.

Lassen Sie mich versuchen zu erklären, wie das Verknüpfen in CMake funktioniert. Die Idee ist, dass Sie Module in CMake erstellen und diese miteinander verknüpfen. Lassen Sie uns jetzt die Header-Dateien ignorieren, da sie alle in Ihren Quelldateien enthalten sein können.

Angenommen, Sie haben file1.cpp, file2.cpp, main.cpp. Sie fügen sie Ihrem Projekt hinzu mit:

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

Jetzt haben Sie sie zu einem Modul namens LibsModule hinzugefügt. Behalt das im Kopf. Angenommen, Sie möchten einen Link zu pthread erstellen, der sich bereits im System befindet. Sie können es mit dem Befehl LibsModule kombinieren:

target_link_libraries(LibsModule -lpthread)

Und wenn Sie auch eine statische Bibliothek damit verknüpfen möchten, gehen Sie folgendermaßen vor:

target_link_libraries(LibsModule liblapack.a)

Wenn Sie ein Verzeichnis hinzufügen möchten, in dem sich eine dieser Bibliotheken befindet, gehen Sie folgendermaßen vor:

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

Nun fügen Sie eine ausführbare Datei hinzu und verknüpfen sie mit Ihrer Hauptdatei:

ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)

(Ich habe BlaBla hinzugefügt, um zu verdeutlichen, dass der Name benutzerdefiniert ist). Und dann verknüpfen Sie LibsModule mit Ihrem ausführbaren Modul MyProgramExecBlaBla

target_link_libraries(MyProgramExecBlaBla LibsModule)

Und das wird es tun.

Was ich in Ihrer CMake-Datei sehe, ist viel Redundanz. Zum Beispiel, warum hast du texture_mapping, welches ist ein ausführbares Modul in Ihren Include-Verzeichnissen? Sie müssen dies also bereinigen und der einfachen Logik folgen, die ich erklärt habe. Hoffentlich klappt es.


Zusammenfassend sieht es so aus:

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)

Das Wichtigste, was Sie verstehen müssen, ist die Modulstruktur, in der Sie Module erstellen und sie alle mit Ihrer ausführbaren Datei verknüpfen. Sobald dies funktioniert, können Sie Ihr Projekt mit weiteren Details komplizieren. Viel Glück!


Hinweis: Beachten Sie, dass dies der einfache Weg ist, CMake zu verwenden. Der bessere plattformübergreifende Weg wäre die Verwendung von find_package, das ein Paket/eine Bibliothek findet und die Bibliotheken und Include-Dateien in CMake-Variablen bereitstellt, damit Sie Ihr Programm mit ihnen verknüpfen können. So geht's bei Boost , zum Beispiel.

62