如何在Windows上静态编译SDL游戏

17

我一直在尝试为Windows制作一个静态链接的“单个二进制”版本的游戏。我想要链接sdl、sdl_image和sdl_mixer,这些库又会引入几个支持库。不幸的是,我还没有找到使用cygwin/mingw/gcc编译和链接它们所有的方法。据我所知,所有现有的公共版本都只是共享库/动态链接库。

请注意,我在这里并不讨论许可问题。源代码将是开放的,因此sdl的GPL/LGPL性质并不相关。


我不想因为不完整而成为被接受的答案 :(. 如果您能提供更多信息(例如从sdl-config调用的输出和链接器错误列表),我愿意尝试修复我的答案。 - Alex Lyman
sdl --static-libs 的返回值为: “-L/usr/local/lib -lmingw32 -lSDLmain -lSDL -mno-cygwin -mwindows” 看起来对我来说是正确的。还有其他信息我可以提供吗? - Sec
5个回答

23

当编译项目时,您需要对makefile进行一些修改。

  • sdl-config --libs替换为sdl-config --static-libs
  • 在上述提到的sdl-config --static-libs之前和之后分别添加-Wl,-Bstatic-Wl,-Bdynamic。这告诉GCC强制进行静态链接,但仅针对它们之间指定的库。

如果您的makefile当前类似于:

SDLLIBS=`sdl-config --libs`

将其更改为:

SDLLIBS=-Wl,-Bstatic `sdl-config --static-libs` -Wl,-Bdynamic

实际上,这些是你在类Unix系统上应该做的相同的事情。如果你在类Unix系统上使用更简单的-static标志来编译GCC,通常不会像在Windows上那样导致很多错误。


我将此标记为答案,因为它似乎是最好的答案。但我仍然无法让它工作,因为我得到了大量“未定义引用”的函数,例如_waveOutOpen@24或_timeGetTime@0。 - Sec
@Sec 这些是因为 SDL 静态库使用它们而被引入的要求。WinMM 多媒体库和其他一些库可能需要添加到您的链接行中。 - WhozCraig

2
通过这篇SDL邮件列表文章,似乎sdl开发工具附带了一个sdl-config脚本,您可以使用--static-libs标志来确定需要使用的链接器标志。请注意保留HTML标签。

1

环境: VMWare虚拟机,安装了Windows 7 x64和Dev c++ 7.4.2.569编译器g++ (tdm-1) 4.6.1

一旦安装了SDL2-2.0.3 API作为配置Dev c++,并不是很清楚我所做的事情,因为传统方法需要使用命令行。

第一个问题是Windows 7似乎已经改变了方法,他们自己处理。库存。参考https://stackoverflow.com/users/464581/cheers-and-hth-alf

在第一个障碍之后,SDL_platform.h有点糟糕,还有另一个问题,我不记得我从哪里下载的,但是下一个在指定版本中不起作用。

我们必须将SDL2.h放在可执行文件的目录中。

D:\prg_desa\zsdl2>g++ bar.cpp main.cpp -o pepe1 -ID:\SDL2-2.0.3\i686-w64-mingw32\include\SDL2 -LD:\SDL2-2.0.3\i686-w64-mingw32\lib -lmingw32 -lSDL2main -lSDL2 -mwindow

我终于编译成功了,SDL2测试也正常运行。


这是您的源代码文件:bar.cpp#undef UNICODE, #define UNICODE, #include <windows.h>, #include <string> ,include <sstream> ,Using namespace std; ,int wmain(int argc,wchar_t* argv[] ),{ wostringstream text; text<<argc-1<<L" 个命令行参数:\n";for(int i=1;i<argc;++i){text<<"\n[" <<argv[i]<<"]";} } - Anónimo
主.cpp # include <cstdlib> #include<windows.h>#include<iostream> # include<SDL.h> using namespace std; int main(int argc,char *argv[]) { SDL_Surface *screen; SDL_Event event; if(SDL_Init(SDL_INIT_VIDEO)==-1) { SDL_GetError()); return 1;} MessageBox(0, TEXT("Pulsa el OK"), TEXT("Hola"), MB_SETFOREGROUND); while(SDL_WaitEvent(&event)) {if(event.type==SDL_QUIT) break;} SDL_Quit(); return 0;} - Anónimo

0

在我的系统(Ubuntu)上,我必须使用以下标志:

-Wl,Bstatic -lSDL_image `sdl-config --libs` -lpng12 -lz -ltiff -ljpeg -lasound -laudio -lesd -Wl,-Bdynamic `directfb-config --libs` -lpulse-simple -lcaca -laa -ldl

这将SDL、SDL_image以及它们的许多依赖项作为静态链接。libdl永远不需要静态链接,因此制作一个完全静态的使用SDL_image的二进制文件是一个糟糕的想法。pulse、caca、aa和directfb可能可以被静态链接。我还没有深入研究它们。


0

这是因为SDL库采用LGPL许可证。

如果您想静态链接库(如果您重新编译它们,可以这样做。但需要对makefile进行一些修改),您还必须将游戏放在某个兼容的开源许可证下。

SDL库作为共享库提供,因为大多数使用它们的程序都是闭源的。二进制发行版以大多数人需要的形式提供。


1
LGPL是一种非常宽松的许可证,允许在闭源应用程序中进行静态包含。而GPL则不允许除dll类型包含之外的闭源应用程序中进行包含。 - KPexEA
据我所知,GPL不允许与闭源代码进行任何形式的链接。LGPL允许动态链接(用户必须能够更新/更改LGPL代码)。在闭源软件中静态链接LGPL是不允许的。 - Nils Pipenbrinck
3
只要您给客户提供了重新链接到LGPL库的工具,他们就可以选择提供静态链接二进制文件。您还必须包含LGPL,并声明使用的库属于此许可证。 - Artelius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接