web-dev-qa-db-fra.com

Comment lier correctement les bibliothèques avec cmake?

Je ne parviens pas à relier correctement les bibliothèques supplémentaires avec lesquelles je travaille.

J'utilise CLion, qui utilise cmake pour construire ses projets. J'essaie d'utiliser plusieurs bibliothèques avec OpenGL pour texturer certains objets. Je l'ai initialement créé dans Visual Studio, car je ne savais jamais comment faire fonctionner cmake avec Clion. Cependant, maintenant que tout le code fonctionne (dans Visual Studio en tout cas), je veux pouvoir utiliser CLion pour cela, car c'est mon IDE préféré.

Je suis encore nouveau chez cmake et je ne comprends pas ce que je fais mal avec mon CMakeLists.txt. Voici ce que j'ai

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

Je l'ai modifié jusqu'à ce que cela ne me donne plus d'erreurs dans CLion, mais les fichiers d'en-tête ne sont toujours pas reconnus dans mon code.

Voici la structure de mon projet:
project structure

Donc, j'ai mis toutes les bibliothèques dont j'avais besoin, mais cela ne semble pas les reconnaître dans le code. Clion les reconnaît dans le projet (ils ne s'affichent pas en rouge avec des erreurs), mais lors de sa construction (lorsque je tente de l'exécuter dans CLion), j'obtiens ces erreurs:

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'

Fondamentalement, des erreurs avec chaque utilisation de SDL et glew, mais pas de GLM, ce qui est étrange.

Qu'est-ce que je fais mal avec mon CMakeLists.txt?

24
Cache Staheli

Ma recommandation est de commencer simplement, puis de compliquer davantage votre projet.

Laissez-moi essayer d’expliquer le fonctionnement des liens dans CMake. L'idée est de construire des modules dans CMake et de les lier ensemble. Ignorons pour l'instant les fichiers d'en-tête, car ils peuvent tous être inclus dans vos fichiers source.

Disons que vous avez file1.cpp, file2.cpp, main.cpp. Vous les ajoutez à votre projet avec:

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

Maintenant, vous les avez ajoutés à un module appelé LibsModule. Garde cela à l'esprit. Supposons que vous souhaitiez créer un lien vers pthread, par exemple, qu'il se trouve déjà dans le système. Vous pouvez le combiner avec LibsModule en utilisant la commande:

target_link_libraries(LibsModule -lpthread)

Et si vous souhaitez lier une bibliothèque statique à cela aussi, procédez comme suit:

target_link_libraries(LibsModule liblapack.a)

Et si vous souhaitez ajouter un répertoire contenant l’une de ces bibliothèques, procédez comme suit:

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

Maintenant, vous ajoutez un exécutable et vous le liez avec votre fichier principal:

ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)

(J'ai ajouté BlaBla juste pour préciser que le nom est personnalisé). Et puis vous liez LibsModule avec votre module exécutable MyProgramExecBlaBla

target_link_libraries(MyProgramExecBlaBla LibsModule)

Et ça va le faire.

Ce que je vois dans votre fichier CMake, c'est beaucoup de redondance. Par exemple, pourquoi avez-vous texture_mapping, qui est un module exécutable dans vos répertoires d’inclusion? Vous devez donc nettoyer cela et suivre la logique simple que j'ai expliquée. Espérons que cela fonctionne.


En résumé, cela ressemble à ceci:

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)

La chose la plus importante à comprendre est la structure de module, dans laquelle vous créez et connectez tous les modules avec votre exécutable. Une fois que cela fonctionne, vous pouvez compliquer davantage votre projet avec plus de détails. Bonne chance!


Remarque: N'oubliez pas qu'il s'agit d'un moyen simple d'utiliser CMake. La meilleure façon multi-plateforme serait d'utiliser find_package, qui localise un paquet/une bibliothèque, fournit les bibliothèques et inclut dans CMake des variables afin que vous puissiez lier votre programme à celles-ci. Voici comment faire cela pour booster , par exemple.

62