Как правильно связать библиотеки с cmake?

Я не могу получить дополнительные библиотеки, с которыми я работаю, чтобы правильно связать мой проект.

Я использую CLion, который использует cmake для создания своих проектов. Я пытаюсь использовать несколько библиотек в сочетании с OpenGL для текстурирования некоторых объектов. Я изначально построил это в Visual Studio, потому что я никогда не мог понять, как заставить cmake работать с Clion. Однако теперь, когда весь код работает (в любом случае в Visual Studio), я хочу иметь возможность использовать CLion для него, потому что это мой предпочтительный IDE.

Я все еще новичок в cmake, и я не понимаю, что я делаю неправильно с моим CMakeLists.txt. Вот что у меня есть:

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

Я подправил его, пока он не дал мне больше ошибок в CLion, но заголовочные файлы все еще не распознаются в моем коде.

Вот структура моего проекта:
project structure

Итак, я поместил все библиотеки, которые мне были нужны, но он, похоже, не распознает их в коде. 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'

В основном, ошибки при каждом использовании SDL и glew, но не glm, что странно.

Что я делаю не так с моим CMakeLists.txt?

Ответ 1

Я рекомендую начать с простого, а затем усложнить ваш проект.

Позвольте мне попытаться объяснить, как работает связывание в CMake. Идея в том, что вы создаете модули в CMake и связываете их вместе. Давайте пока игнорируем заголовочные файлы, так как все они могут быть включены в ваши исходные файлы.

Допустим, у вас есть file1.cpp, file2.cpp, main.cpp. Вы добавляете их в свой проект с помощью:

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

Теперь вы добавили их в модуль под названием LibsModule. Запомни. Допустим, вы хотите pthread ссылку на 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)  #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)

Самая важная вещь для понимания - это структура модулей, где вы создаете модули и связываете их все вместе со своим исполняемым файлом. Как только это сработает, вы можете еще больше усложнить свой проект с более подробной информацией. Удачи!


Примечание: имейте в виду, что это простой способ использования CMake. Лучшим кроссплатформенным способом было бы использовать find_package, который находит пакет/библиотеку и предоставляет библиотеки и включает переменные CMake, чтобы вы могли связать с ними свою программу. Вот как это сделать для повышения, например.

Ответ 2

Вы рекомендуете какие-либо ресурсы, которые помогут начинающим изучать CMake?