CMake выдает ошибку неопределенной ссылки, даже если используется команда link_libraries

Вопрос или проблема

CMake выдает ошибку неопределенной ссылки, даже если используется команда link_libraries

Я пытаюсь подключить GLFW, используя git submodule. Вот мой CMakeLists.txt:

cmake_minimum_required(VERSION 3.0.0)
project(guitest VERSION 0.1.0 LANGUAGES C CXX)

add_executable(guitest main.cpp)

add_subdirectory(glfw)
include_directories(glfw/include)
link_directories(glfw/src)
link_libraries(glfw)

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

[build] C:/Users/Konstantin/Documents/sasha/guitest/main.cpp:7: неопределенная ссылка на `glfwInit'

Вот мой код

#include <iostream>
#include <GLFW/glfw3.h>

int main(int, char**){
    GLFWwindow *window;
    if(!glfwInit()){
        std::cout << "Ошибка инициализации!"<<std::endl;
        exit(EXIT_FAILURE);
    }
}

Я использую Visual Studio Code и компилятор GCC 6.3.0 MinGW.

Команда link_libraries влияет только на цели, которые создаются после. Поскольку вызов add_executable предшествует link_libraries, ваша исполняемая программа не связана.

Корректно (но не лучший вариант):

add_subdirectory(glfw)
link_libraries(glfw)
add_executable(guitest main.cpp)

Предпочтительнее использовать target_link_libraries вместо link_libraries.

add_subdirectory(glfw)
add_executable(guitest main.cpp)
target_link_libraries(guitest PRIVATE glfw)

В обоих случаях вызов include_directories можно опустить, так как связь с целью glfw также включает ваши каталоги для заголовков GLFW в исполняемую программу.

Ответ или решение

Для решения проблемы с "undefined reference" в CMake, возникающей при использовании команды link_libraries, важно понимать, как работает связывание библиотек. В вашем случае причина заключается в том, что команда link_libraries применяется к целям, которые создаются после неё. Так как вы вызываете add_executable до link_libraries, ваша исполняемая программа не подключена к библиотеке GLFW.

Вместо использования link_libraries, рекомендуется использовать target_link_libraries, так как это более современный и предпочтительный подход в CMake. Он позволяет точно указать, какие библиотеки связывать с конкретной целью, что повышает читаемость и контроль.

Вот как можно изменить ваш CMakeLists.txt:

cmake_minimum_required(VERSION 3.0.0)
project(guitest VERSION 0.1.0 LANGUAGES C CXX)

add_subdirectory(glfw)
add_executable(guitest main.cpp)
target_link_libraries(guitest PRIVATE glfw)

В этом изменённом варианте кода:

  1. Сначала вызывается add_subdirectory(glfw), чтобы добавить GLFW как подкаталог.
  2. Затем создаётся исполняемый файл guitest с помощью add_executable.
  3. Наконец, используется target_link_libraries, чтобы связать вашу программу с библиотекой GLFW. Здесь мы указываем PRIVATE, что означает, что библиотека будет доступна только для данной цели (в данном случае, для guitest).

Также, как вы заметили, также можно опустить вызов include_directories, так как при связывании с целевой библиотекой CMake автоматически добавляет необходимые директории для включения.

Таким образом, данный подход не только решит вашу проблему с "undefined reference", но и улучшит структуру вашего проекта. Теперь ваше приложение должно успешно собираться и линковаться с библиотекой GLFW.

Оцените материал
Добавить комментарий

Капча загружается...