使用 CMake 作为 makefile 生成器构建 SDL2 应用程序时,构建的应用程序在打开后立即关闭,没有输出,即使使用 SDL_sleep(int) 也是如此。平台等是 64 位的,尽管以后最好也支持 32 位。
PS F:\Koodit\Vivaria> .\scripts\build_windows_debug_x64.bat
F:\Koodit\Vivaria>mkdir build
F:\Koodit\Vivaria>cmake -G "MinGW Makefiles" -S . -B ./build/ -DCMAKE_TOOLCHAIN_FILE=./buildtools/win-x64-debug.cmake ..
-- The C compiler identification is GNU 10.1.0
-- The CXX compiler identification is GNU 10.1.0
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/x86_64-w64-mingw32-g++.exe
-- Check for working CXX compiler: C:/msys64/mingw64/bin/x86_64-w64-mingw32-g++.exe - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: F:/Koodit/Vivaria/build
F:\Koodit\Vivaria\build>mingw32-make
mingw32-make[1]: Entering directory 'F:/Koodit/Vivaria/build'
mingw32-make[2]: Entering directory 'F:/Koodit/Vivaria/build'
Scanning dependencies of target Vivaria
mingw32-make[2]: Leaving directory 'F:/Koodit/Vivaria/build'
mingw32-make[2]: Entering directory 'F:/Koodit/Vivaria/build'
[ 50%] Building CXX object CMakeFiles/Vivaria.dir/src/vivaria.cpp.obj
[100%] Linking CXX executable ..\deploy\Windows_x64_Debug\Vivaria.exe
mingw32-make[2]: Leaving directory 'F:/Koodit/Vivaria/build'
[100%] Built target Vivaria
mingw32-make[1]: Leaving directory 'F:/Koodit/Vivaria/build'
PS F:\Koodit\Vivaria> .\deploy\Windows_x64_Debug\Vivaria.exe
PS F:\Koodit\Vivaria>
包含的文件(当前为 SDL2)使用 install_buildtools_xxx.xxx 脚本安装到包含目录。那(应该)允许在不同的计算机上快速设置项目。
├── build
│ └── -cmake generated files
├── buildtools
│ └── win-x64-debug.cmake
├── deploy
│ └── Windows_x64_Debug
│ └── Vivaria.exe
├── includes
│ └── SDL2
│ └── SDL2-2.0.12
│ └── lib
│ └── x64
│ ├── SDL2.lib
│ └── SDL2main.lib
├── resources
├── scripts
│ ├── install_includes_windows.bat
│ ├── build_windows_debug_x64.bat
│ └── build_windows_debug_x86.bat
├── src
│ ├── vivaria.h
│ └── vivaria.cpp
└── CMakeLists.txt
vivaria.h
#ifndef VIVARIA_H
#define VIVARIA_H
#include "SDL.h"
class Vivaria {
private:
bool running;
SDL_Window* window;
public:
Vivaria();
int onExecute();
bool onInit();
void onEvent(SDL_Event* event);
void onLoop();
void onRender();
void onCleanup();
SDL_Window* getWindow() const;
};
#endif
vivaria.cpp(重要的部分)
#define SDL_MAIN_HANDLED
#include <iostream>
#include "SDL.h"
#include "vivaria.h"
int main(int argc, char* argv[]) {
SDL_SetMainReady();
Vivaria game;
return game.onExecute();
}
Vivaria::Vivaria() {
std::cout << "Starting Vivaria..." << std::endl;
}
// called in onExecute
bool Vivaria::onInit() {
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
return false;
}
window = SDL_CreateWindow(
"Vivaria",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640,
480,
SDL_WindowFlags::SDL_WINDOW_OPENGL
);
if(window == nullptr) {
printf("Could not create window: %s\n", SDL_GetError());
return false;
}
return true;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(Vivaria VERSION 1.0.0)
set(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/includes")
set(SDL2_DIR "${INCLUDE_DIR}/SDL2/SDL2-2.0.12")
set(SDL2_INCLUDE_DIRS "${SDL2_DIR}/include")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/deploy/${CMAKE_SYSTEM_NAME}_${BITSIZE}_${CMAKE_BUILD_TYPE}/")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/deploy/${CMAKE_SYSTEM_NAME}_${BITSIZE}_${CMAKE_BUILD_TYPE}/lib")
set(SDL2_MAIN_LIB "${SDL2_DIR}/lib/${BITSIZE}/SDL2main.lib")
set(SDL2_LIB "${SDL2_DIR}/lib/${BITSIZE}/SDL2.lib")
link_directories(${SDL2_LIBRARIES})
# Project files and linking
set(SOURCES
src/vivaria.cpp
)
add_executable(${PROJECT_NAME} ${SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${SDL2_MAIN_LIB} ${SDL2_LIB})
win-x64-debug.cmake
set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++.exe)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_MAKE_PROGRAM mingw32-make.exe)
# flags
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS OFF)
set(BITSIZE x64)
build_windows_debug_x64.bat
mkdir build
cmake -G "MinGW Makefiles" -S . -B ./build/ -DCMAKE_TOOLCHAIN_FILE=./buildtools/win-x64-debug.cmake ..
cd .\build\
mingw32-make
我在 2023 年 3 月遇到了同样的问题,虽然这个帖子早已关闭,但我遇到了同样的问题并且花了太多时间寻找解决方案。这是今天在 Windows 上有效的东西。
设置
解决步骤:
链接到 .lib 文件并构建 .exe 是不够的,您还需要将 SDL2.dll 复制到构建文件夹中,就在您的.exe 旁边
最后的 DLL 拼图感谢这个人:Cant execute a simple "SDL2HelloWorld" on Windows with CMake
工作 CMAKE 文件
cmake_minimum_required(VERSION 3.0)
project(SDL2Test)
# Windows
IF (WIN32)
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/ext/win_sdl2_2.26.4/cmake)
ENDIF(WIN32)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
message("SDL2_INCLUDE_DIRS: ${SDL2_INCLUDE_DIRS}")
message("SDL2_INCLUDE_DIRS: ${SDL2_LIBRARIES}")
add_executable(SDL2Test Main.cpp)
# Will also like to SDL2Main.lib and defining SDL_MAIN_HANDLED has NO EFFECT
#target_link_libraries(SDL2Test ${SDL2_LIBRARIES})
# Link just the SDL2.lib and not SDL2main.lib
# This allows defining SDL_MAIN_HANDLED to take effect and call int main(int argc, char* argv[])
target_link_libraries(SDL2Test ${CMAKE_CURRENT_SOURCE_DIR}/ext/win_sdl2_2.26.4/lib/x64/SDL2.lib)
工作测试文件*
#define SDL_MAIN_HANDLED
#include "SDL.h"
// If you define SDL_MAIN_HANDLED and do not link to SDL2main.lib
int main(int argc, char* argv[]) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow(
"SDL2Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
0
);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
// Called if you don't define SDL_MAIN_HANDLED, whether you link to SDL2main.lib or not
int wmain(void) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow(
"SDL2Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
0
);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}