SDL 静态编译教程
- W_Z_C
- 共 2467 字,阅读约 6 分钟
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用 C语言 写成。本文主要介绍 SDL 库的静态编译方法。SDL 当前是第二版,开源协议改为 Zlib 授权模式,官方文档上描述虽然 SDL 可以编译为静态库,但不会主动介绍静态库的编译方法,也不推荐将 SDL 编译为静态库使用,不过在很多场合下,静态编译去除依赖可以让程序看起来更便捷,所以这里简单的记录一下在 Windows 平台上静态编译的简易流程。
1. 下载源码
首先去 SDL 官网下载编译所需的源代码,当前最新的版本是 SDL2-2.0.10 。
如果你不需要静态编译,推荐直接使用官方已经编译好的开发库,基本上解压即用。
2. 配置 CMake
这里编译 SDL 使用 CMake 的方式,所以在编译之前需要确保你的电脑已经安装最新版本的 CMake 和 Visual Studio,如果你不知道怎样安装,可以查看 CMake 安装教程 和 Visual Studio 安装教程。 安装好 CMake 和 Visual Studio 之后,解压 SDL 压缩包,并确保找到压缩包里面的 CMakeLists.txt 文件,这个文件是 CMake 的配置文件,一会生成工程需要使用这个文件。
打开 CMake 的使用界面:
将前面提到的 CMakeLists.txt 拖到界面上,并在 Where to build the binaries
目录后面增加 _build
目录。这样可以确保生成的文件在 _build
目录中,而不会污染原有的 SDL 目录。
点击左下角的 Configure 按钮:
中间可能弹出是否确认创建 _build
目录的提示,这里直接点击确认即可。接着会弹出配置生成工程的相关属性,因为我机器上安装了 vs2019,并且电脑是 64 位系统,所以选择如下图所示,你可以根据自身系统的情况自行选择:
选择完毕后,点击 Finish,CMake 会自动生成相应的工程配置信息,下面是我电脑的生成配置日志:
Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.18363.
The C compiler identification is MSVC 19.24.28314.0
The CXX compiler identification is MSVC 19.24.28314.0
Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.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:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Detecting CXX compile features
Detecting CXX compile features - done
Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
Performing Test HAVE_WIN32_CC
Performing Test HAVE_WIN32_CC - Success
Performing Test HAVE_XINPUT_H
Performing Test HAVE_XINPUT_H - Success
Performing Test HAVE_XINPUT_GAMEPAD_EX
Performing Test HAVE_XINPUT_GAMEPAD_EX - Failed
Performing Test HAVE_XINPUT_STATE_EX
Performing Test HAVE_XINPUT_STATE_EX - Failed
Looking for d3d9.h
Looking for d3d9.h - found
Looking for d3d11_1.h
Looking for d3d11_1.h - found
Looking for ddraw.h
Looking for ddraw.h - found
Looking for dsound.h
Looking for dsound.h - found
Looking for dinput.h
Looking for dinput.h - found
Looking for dxgi.h
Looking for dxgi.h - found
Looking for mmdeviceapi.h
Looking for mmdeviceapi.h - found
Looking for audioclient.h
Looking for audioclient.h - found
Looking for endpointvolume.h
Looking for endpointvolume.h - found
SDL2 was configured with the following options:
Platform: Windows-10.0.18363
64-bit: TRUE
Compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
Subsystems:
Atomic: ON
Audio: ON
Video: ON
Render: ON
Events: ON
Joystick: ON
Haptic: ON
Power: ON
Threads: ON
Timers: ON
File: ON
Loadso: ON
CPUinfo: ON
Filesystem: ON
Dlopen: ON
Sensor: ON
Options:
3DNOW (Wanted: ON): OFF
ALSA (Wanted: OFF): OFF
ALSA_SHARED (Wanted: OFF): OFF
ALTIVEC (Wanted: ON): OFF
ARTS (Wanted: OFF): OFF
ARTS_SHARED (Wanted: OFF): OFF
ASSEMBLY (Wanted: ON): OFF
ASSERTIONS (Wanted: auto): auto
BACKGROUNDING_SIGNAL (Wanted: OFF): OFF
CLOCK_GETTIME (Wanted: OFF): OFF
DIRECTFB_SHARED (Wanted: OFF): OFF
DIRECTX (Wanted: ON): ON
DISKAUDIO (Wanted: ON): ON
DUMMYAUDIO (Wanted: ON): ON
ESD (Wanted: OFF): OFF
ESD_SHARED (Wanted: OFF): OFF
FOREGROUNDING_SIGNAL (Wanted: OFF): OFF
FUSIONSOUND (Wanted: OFF): OFF
FUSIONSOUND_SHARED (Wanted: OFF): OFF
GCC_ATOMICS (Wanted: OFF): OFF
HIDAPI (Wanted: ON): ON
INPUT_TSLIB (Wanted: OFF): OFF
JACK (Wanted: OFF): OFF
JACK_SHARED (Wanted: OFF): OFF
KMSDRM_SHARED (Wanted: OFF): OFF
LIBC (Wanted: OFF): OFF
LIBSAMPLERATE (Wanted: OFF): OFF
LIBSAMPLERATE_SHARED (Wanted: OFF): OFF
MMX (Wanted: ON): OFF
NAS (Wanted: OFF): OFF
NAS_SHARED (Wanted: OFF): OFF
OSS (Wanted: OFF): OFF
PTHREADS (Wanted: OFF): OFF
PTHREADS_SEM (Wanted: OFF): OFF
PULSEAUDIO (Wanted: OFF): OFF
PULSEAUDIO_SHARED (Wanted: OFF): OFF
RENDER_D3D (Wanted: ON): ON
RPATH (Wanted: OFF): OFF
SDL_DLOPEN (Wanted: ON): OFF
SDL_STATIC_PIC (Wanted: OFF): OFF
SDL_TEST (Wanted: OFF): OFF
SNDIO (Wanted: OFF): OFF
SSE (Wanted: ON): ON
SSE2 (Wanted: ON): ON
SSE3 (Wanted: ON): ON
SSEMATH (Wanted: ON): OFF
VIDEO_COCOA (Wanted: OFF): OFF
VIDEO_DIRECTFB (Wanted: OFF): OFF
VIDEO_DUMMY (Wanted: ON): ON
VIDEO_KMSDRM (Wanted: OFF): OFF
VIDEO_OPENGL (Wanted: ON): ON
VIDEO_OPENGLES (Wanted: ON): ON
VIDEO_RPI (Wanted: OFF): OFF
VIDEO_VIVANTE (Wanted: OFF): OFF
VIDEO_VULKAN (Wanted: ON): ON
VIDEO_WAYLAND (Wanted: OFF): OFF
VIDEO_WAYLAND_QT_TOUCH (Wanted: OFF): OFF
VIDEO_X11 (Wanted: OFF): OFF
VIDEO_X11_XCURSOR (Wanted: OFF): OFF
VIDEO_X11_XINERAMA (Wanted: OFF): OFF
VIDEO_X11_XINPUT (Wanted: OFF): OFF
VIDEO_X11_XRANDR (Wanted: OFF): OFF
VIDEO_X11_XSCRNSAVER (Wanted: OFF): OFF
VIDEO_X11_XSHAPE (Wanted: OFF): OFF
VIDEO_X11_XVM (Wanted: OFF): OFF
WASAPI (Wanted: ON): OFF
WAYLAND_SHARED (Wanted: OFF): OFF
X11_SHARED (Wanted: OFF): OFF
CFLAGS: /DWIN32 /D_WINDOWS /W3 -IC:/projects/SDL2-2.0.10/SDL2-2.0.10/src/hidapi/hidapi
EXTRA_CFLAGS:
EXTRA_LDFLAGS:
EXTRA_LIBS: user32;gdi32;winmm;imm32;ole32;oleaut32;version;uuid;advapi32;setupapi;shell32;dinput8
Build Shared Library: ON
Build Static Library: ON
Build Static Library with Position Independent Code: OFF
Configuring done
日志中可以确定当前工程配置选择开关属性,也可以在界面中查看:
这里显示红色,代表需要你选择自己的配置信息,并不代表配置错误,大家不要过分担心。大部分的配置其实 CMake 已经自动检测完成无需修改,因为咱们要编译静态库,因此请确保勾选 SDL_STATIC 设置,并移除 SDL_SHARED 选项。剩下的暂时无需改动,再次按下 Configure 按钮,确保生成的配置和我们期望的一致。
生成完毕后,界面不会在显示红色,这时候可以点击 Generate 按钮,生成我们的工程文件。如果生成成功,则旁边的 Open Project 按钮会从禁用状态变为可用,可以直接点击该按钮打开工程,也可以自己去 _build
目录寻找 SDL2.sln 自行打开。
3. 编译 SDL2 静态库
按照 vs 的属性,编译的时候可以选择 Debug/Release,运行时库也可以选择 MT/MD,按照二者的组合,最后可以生成四种库文件,将它们放到不同的目录备用。具体的配置方法可以查看 运行时库详解 这篇文章,每次修改配置都编译一次工程,编译成功后,将生成的结果放到一开始设定的目录下,最后的目录结构如下:
---
|--- include //放头文件
|--- lib
|--- Debug
| |--- MDd
| | |-- SDL2d.lib
| | |-- SDL2maind.lib
| |
| |--- MTd
| |-- SDL2d.lib
| |-- SDL2maind.lib
|
|--- Release
|--- MD
| |-- SDL2d.lib
| |-- SDL2maind.lib
|
|--- MT
|-- SDL2d.lib
|-- SDL2maind.lib
大家可以去下载页面下载我编译好的版本,不过这里只有 x64 版本,如果你的机器还是 32 位系统则无法使用。SDL2 静态库下载
编译的时候有一点需要注意,在 include 头文件的目录里面需要加入 CMake 生成的 SDL_config.h 文件,这个文件默认生成在
_build/include/SDL_config.h
里面,如果忘记这个头文件,在使用 SDL库的时候,可能会因为无法找到 SDL_config.h 而无法编译通过。
如果在程序中使用 SDL2 开发库的时候,可能会报链接错误:
1>MSVCRT.lib(ftol2.obj) : error LNK2005: __ftol2_sse 已经在 SDL2.lib(SDL_stdlib.obj) 中定义
1>SDL2.lib(SDL_systimer.obj) : error LNK2001: 无法解析的外部符号 __imp__timeGetTime@0
1>SDL2.lib(SDL_systimer.obj) : error LNK2001: 无法解析的外部符号 __imp__timeBeginPeriod@4
1>SDL2.lib(SDL_systimer.obj) : error LNK2001: 无法解析的外部符号 __imp__timeEndPeriod@4
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _GetFileVersionInfoSizeA@8
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _GetFileVersionInfoA@16
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _VerQueryValueA@16
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmGetIMEFileNameA@12
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmGetContext@4
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmReleaseContext@8
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmAssociateContext@8
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmGetCompositionStringW@16
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmSetCompositionStringW@24
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmGetCandidateListW@16
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmNotifyIME@16
1>SDL2.lib(SDL_windowskeyboard.obj) : error LNK2001: 无法解析的外部符号 _ImmSetCompositionWindow@8
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutGetNumDevs@0
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutGetDevCapsW@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutGetErrorTextW@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutOpen@24
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutClose@4
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutPrepareHeader@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutUnprepareHeader@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutWrite@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveOutReset@4
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInGetNumDevs@0
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInGetDevCapsW@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInOpen@24
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInClose@4
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInPrepareHeader@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInUnprepareHeader@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInAddBuffer@12
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInStart@4
1>SDL2.lib(SDL_winmm.obj) : error LNK2001: 无法解析的外部符号 __imp__waveInReset@4
1>SDL2.lib(hid.obj) : error LNK2001: 无法解析的外部符号 __imp__SetupDiEnumDeviceInfo@12
1>SDL2.lib(hid.obj) : error LNK2001: 无法解析的外部符号 __imp__SetupDiDestroyDeviceInfoList@4
1>SDL2.lib(hid.obj) : error LNK2001: 无法解析的外部符号 __imp__SetupDiEnumDeviceInterfaces@20
1>SDL2.lib(hid.obj) : error LNK2001: 无法解析的外部符号 __imp__SetupDiGetDeviceInterfaceDetailA@24
1>SDL2.lib(hid.obj) : error LNK2001: 无法解析的外部符号 __imp__SetupDiGetClassDevsA@16
1>SDL2.lib(hid.obj) : error LNK2001: 无法解析的外部符号 __imp__SetupDiGetDeviceRegistryPropertyA@28
主要的原因是 SDL 内部调用了几个 WIN32 API 导致的,默认情况下程序没有链接这几个 API 的库,你可以在 [链接] -> [输入] -> [附加依赖项] 中添加下面几个库:
Setupapi.lib
Winmm.lib
Imm32.lib
Version.lib
也可以直接在代码中输入:
#pragma comment(lib, "Setupapi.lib")
#pragma comment(lib, "Winmm.lib")
#pragma comment(lib, "Imm32.lib")
#pragma comment(lib, "Version.lib")
一般情况下就可以解决了,如果还解决不了,欢迎留言!