Использование SDL2 с CMake

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

Мой файл CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.4)
project(ChickenShooter)

set(SDL2_INCLUDE_DIR C:/SDL/SDL2-2.0.3/include)
set(SDL2_LIBRARY C:/SDL/SDL2-2.0.3/lib/x64)

include_directories(${SDL2_INCLUDE_DIR})
set(SOURCE_FILES main.cpp)

add_executable(ChickenShooter ${SOURCE_FILES})
target_link_libraries(ChickenShooter ${SDL2_LIBRARY})

Мой тест main.cpp:

#include <iostream>
#include "SDL.h" /* This one can't be found */

int main(){
    if (SDL_Init(SDL_INIT_VIDEO) != 0){
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }
    SDL_Quit();
    return 0;
}

Спасибо за любую помощь, которую вы могли бы мне дать.

Изменить: Я использую Windows, и CLion настроен на использование cygwin64.

Ответ 1

Не устанавливайте путь к SDL2 вручную. Используйте правильную команду поиска, которая использует FindSDL. Должно выглядеть так:

find_file(SDL2_INCLUDE_DIR NAME SDL.h HINTS SDL2)
find_library(SDL2_LIBRARY NAME SDL2)
add_executable(ChickenShooter main.cpp)
target_include_directories(ChickenShooter ${SDL2_INCLUDE_DIR})
target_link_libraries(ChickenShooter ${SDL2_LIBRARY})    

Если SDL2 не найден, вы должны добавить путь к CMAKE_PREFIX_PATH в CMAKE_PREFIX_PATH, где CMake ищет установленное программное обеспечение.

Если вы можете использовать Pkg-config, его использование может быть проще, см. Как использовать SDL2 и SDL_image с cmake

Если вам удобнее использовать файл FindSDL2.cmake, аналогичный файлу FindSDL.cmake, предоставленному CMake, см. Https://brendanwhitfield.wordpress.com/2015/02/26/using-cmake-with-sdl2/

Ответ 2

Это сообщение в блоге показывает, как вы можете это сделать: Использование SDL2 с CMake

В Linux вы можете использовать недавний CMake (например, версию 3.7), и использование SDL2 работает из коробки.

cmake_minimum_required(VERSION 3.7)
project(SDL2Test)

find_package(SDL2 REQUIRED)
include_directories(SDL2Test ${SDL2_INCLUDE_DIRS})

add_executable(SDL2Test Main.cpp)
target_link_libraries(SDL2Test ${SDL2_LIBRARIES})

В Windows вы можете загрузить пакет разработки SDL2, извлечь его где-нибудь и затем создать файл sdl-config.cmake в извлеченном месте со следующим содержимым:

set(SDL2_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include")

# Support both 32 and 64 bit builds
if (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
  set(SDL2_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x64/SDL2main.lib")
else ()
  set(SDL2_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2.lib;${CMAKE_CURRENT_LIST_DIR}/lib/x86/SDL2main.lib")
endif ()

string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES)

Когда вы теперь настраиваете внутри приложения CMake-GUI, будет переменная SDL2_DIR. Вы должны указать его в каталог SDL2, где вы извлекли пакет dev и переконфигурировали, тогда все должно работать.

Затем вы можете включить заголовки SDL2, просто написав #include "SDL.h".

Ответ 3

У вас нет ошибки CMake, генерирующей ваш файл make. Но я думаю, что ваша проблема в том, что заголовок SDL находится в подпапке под названием "SDL2".

Измените свой CMakeLists.txt, чтобы включить

C:/SDL/SDL2-2.0.3/include/SDL2

Вместо

C:/SDL/SDL2-2.0.3/include

Ответ 4

Используя модуль SDL2 CMake, который я разработал, вы можете легко интегрировать библиотеку SDL2 в современный и переносимый подход.

Вы должны просто скопировать модуль в cmake/sdl2 (или просто клонировать cmake/sdl2 модулей) в вашем проекте:

git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2

Затем добавьте следующие строки в ваш CMakeLists.txt:

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main)

Примечание. Если CMake не нашел библиотеку SDL2 (в Windows), мы можем указать параметр CMake SDL2_PATH следующим образом:

cmake .. -DSDL2_PATH="/path/to/sdl2"

Для более подробной информации, пожалуйста, прочитайте файл README.md.

Модули SDL2 CMake поддерживают другие связанные библиотеки: SDL2_image, SDL2_ttf, SDL2_mixer, SDL2_net и SDL2_gfx.

Вы можете найти список примеров/примеров и проектов, которые используют эти модули здесь: https://github.com/aminosbh/sdl-samples-and-projects

Ответ 5

к моменту моего ответа SDL2 снабжен исполняемым файлом sdl2-config (как я понимаю, разработчики называют его "экспериментальным" ). После "make install" SDL2 вы можете попробовать позвонить ему из терминала с помощью sdl2-config --cflags --libs, чтобы узнать, что он выводит.

И затем вы можете добавить его в свой файл:

set(PROJECT_NAME SomeProject)

project(${PROJECT_NAME})

execute_process(COMMAND /usr/local/bin/sdl2-config --libs RESULT_VARIABLE CMD_RES OUTPUT_VARIABLE SDL2_CFLAGS_LIBS ERROR_VARIABLE ERR_VAR OUTPUT_STRIP_TRAILING_WHITESPACE)
message("SDL2_CFLAGS_LIBS=${SDL2_CFLAGS_LIBS}; CMD_RES=${CMD_RES}; ERR_VAR=${ERR_VAR}")

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${SDL2_CFLAGS_LIBS}")

set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})

Здесь у меня есть проблема - если я ставил только исполняемое имя без пути, например

execute_process(COMMAND sdl2-config --libs <...>

Я получаю сообщение об ошибке "Нет такого файла", т.е. cmake не ищет в текущем пути, и я не знаю, как его правильно записать.

Еще одно уведомление: в моем make файле я не являюсь пользователем --cflags, потому что наборы cmake включены правильно, и мне не нужно явно указывать их.

Ответ 6

У меня была такая же проблема, и ни одно из других решений не сработало. Но, наконец, я заработал, следуя этому решению: Как правильно связать библиотеки с помощью cmake?

В двух словах, проблема заключалась в том, что библиотека SDL2 не была правильно связана в моем CMakeLists.txt. И записав это в файл, это сработало (больше объяснений в другом потоке):

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)

Ответ 7

cmake_minimum_required(VERSION 2.8.4)

project(ChickenShooter)

set(SDL2_INCLUDE_DIR C:/SDL/SDL2-2.0.3/include/SDL2)
set(SDL2_LIB_DIR C:/SDL/SDL2-2.0.3/lib/x64)

include_directories(${SDL2_INCLUDE_DIR})
link_directories(${SDL2_LIB_DIR})

set(SOURCE_FILES main.cpp)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(${PROJECT_NAME} SDL2main SDL2)

Ответ 8

Вы также можете вставить исходный репозиторий SDL в качестве подмодуля и построить/связать его статически вместе с основной программой с помощью add_subdirectory() и target_link_libraries():

cmake_minimum_required( VERSION 3.7.0 )
project( sdl2-demo )

set( SDL_STATIC ON CACHE BOOL "" FORCE )
set( SDL_SHARED OFF CACHE BOOL "" FORCE )
add_subdirectory( external/sdl )

add_executable(
    sdl2-demo
    "src/main.cpp"
    )
target_link_libraries( sdl2-demo SDL2main SDL2-static )

(По крайней мере, из тега release-2.0.9, возможно, раньше.)

Ответ 9

Выделим шаги, как я смог в конечном итоге сделать это с помощью модуля FindSDL2.cmake:

  • Загрузите SDL2-devel-2.0.9-VC.zip (или любую другую версию, вышедшую после публикации этого ответа) в разделе "Библиотеки разработки" на странице загрузок.
  • Извлеките папку zip, и вы должны увидеть папку, похожую на "SDL2-2.0.9". Вставьте эту папку в папку C:\Program Files (x86) \.
  • Скопируйте модуль FindSDL2.cmake и поместите его в новый каталог "cmake" в вашем проекте. Я нашел файл FindSDL2.cmake в ответе, указанном в "Принятом ответе": https://brendanwhitfield.wordpress.com/2015/02/26/using-cmake-with-sdl2/
  • Найдите строку SET(SDL2_SEARCH_PATHS в FindSDL2.cmake и добавьте скопированный каталог разработки для SDL2 в виде новой строки: "/Program Files (x86)/SDL2-2.0.9" # Windows
  • В моем CMakeLists.txt добавьте эту строку: set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

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

cmake_minimum_required(VERSION 2.8.4)
project(Test_Project)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

# includes cmake/FindSDL2.cmake
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

set(SOURCE_FILES src/main.cpp src/test.cpp)
add_executable(test ${SOURCE_FILES})

# The two lines below have been removed to run on my Windows machine
#INCLUDE(FindPkgConfig)
#PKG_SEARCH_MODULE(SDL2 REQUIRED sdl2)
find_package(SDL2 REQUIRED)

INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(chip8 ${SDL2_LIBRARY})

Надеюсь, это поможет кому-то в ближайшем будущем.

Ответ 10

С скомпилированной версией SDL2-2.0.9 с MinGW-w64 в Windows у меня работает следующая конфигурация:

find_package(SDL2 REQUIRED)

add_executable(sdl-test ${SOURCES})

target_link_libraries(sdl-test
  mingw32
  SDL2::SDL2main
  SDL2::SDL2
)

Более длинное объяснение

Читая файл SDL2Targets.cmake, я узнал, что SDL2 предоставляет несколько целей:

  • SDL2::SDL2main (lib/libSDL2main.a)
  • SDL2::SDL2 (lib/libSDL2.dll.a)
  • SDL2::SDL2-static (lib/libSDL2-static.a)

Для каждого из них определен INTERFACE_INCLUDE_DIRECTORIES, что означает, что нам не нужно вручную указывать include_directories для SDL2.

Но только при добавлении SDL2::SDL2main и SDL2::SDL2, как target_link_libraries недостаточно. Компилятор g++ может жаловаться на "неопределенную ссылку на" WinMain "".

-lmingw32 параметры компилятора, я обнаружил, что библиотеки -lmingw32 добавляются до -lmingw32. Чтобы опция -lmingw32 появилась перед библиотеками SDL2, мы также должны указать mingw32 в качестве первого target_link_libraries. Который заставит эту конфигурацию работать.

Команда, которую я использовал для его построения:

$ mkdir build && cd build && cmake .. -G"MinGW Makefiles" && cmake --build .

Единственная небольшая проблема здесь в окончательно сгенерированных опциях компилятора, опция -lmingw32 дублируется. Но поскольку это не влияет на процесс компоновки, я пока проигнорировал это.