tl;dr compiling C code, with SDL2, using -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' -s USE_SDL_TTF=2 results in lots and lots of "redefinition error" on arch linux.
I am trying to use SDL2 in the browser using emscripten but it completely fails. I am following this guide on a simple SDL2 script that moves a yellow square around. The example works on his web browser. Compiling the code locally with gcc works perfectly fine and works as expected.
I am currently running Arch Linux and I have all dependencies installed (SDL2, emscripten, emsdk, lib32-sdl2 sdl2_image sdl2_ttf). I started out initially just having SDL2 installed and installed emscripten and emsdk via git following the instructions but when that didn't work I tried installing the rest via the repo. and AUR. Still to no avail. I have now uninstalled every package listed and reinstalled SDL2, and I am now only using the git installation as you can see below
Running make em to compile the script with emscripten fails and results in the following error:
/home/user/gitclones/emsdk/upstream/emscripten/cache/wasm/include/SDL2/SDL_error.h:41:29: note: previous declaration is here
extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
^
In file included from main.c:7:
In file included from /home/user/gitclones/emsdk/upstream/emscripten/system/include/SDL/SDL_ttf.h:30:
In file included from /home/user/gitclones/emsdk/upstream/emscripten/system/include/SDL/SDL.h:76:
In file included from /home/user/gitclones/emsdk/upstream/emscripten/system/include/SDL/SDL_audio.h:32:
/home/user/gitclones/emsdk/upstream/emscripten/system/include/SDL/SDL_error.h:57:5: error: redefinition of enumerator 'SDL_ENOMEM'
SDL_ENOMEM,
^
/home/user/gitclones/emsdk/upstream/emscripten/cache/wasm/include/SDL2/SDL_error.h:57:5: note: previous definition is here
SDL_ENOMEM,
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
emcc: error: '/home/user/gitclones/emsdk/upstream/bin/clang -target wasm32-unknown-emscripten -D__EMSCRIPTEN_major__=1 -D__EMSCRIPTEN_minor__=39 -D__EMSCRIPTEN_tiny__=16 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -nostdsysteminc -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/system/include/compat -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/system/include -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/system/include/libc -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/system/lib/libc/musl/arch/emscripten -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/system/local/include -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/cache/wasm/include -DEMSCRIPTEN -fignore-exceptions -O3 main.c -Xclang -isystem/home/user/gitclones/emsdk/upstream/emscripten/cache/wasm/include/SDL2 -I/home/user/gitclones/emsdk/upstream/emscripten/cache/wasm/include/freetype2/freetype -c -o /tmp/emscripten_temp_yax02_qn/main_0.o -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr' failed (1)
main.c
#include <stdio.h>
#include <stdlib.h>
#if __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#include <SDL2/SDL.h>
#include <SDL/SDL_ttf.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#endif
#define SCREEN_WIDTH 200
#define SCREEN_HEIGHT 200
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
#define MAX(a,b) ((a) > (b) ? a : b)
#define MIN(a,b) ((a) < (b) ? a : b)
int posX=0;
int posY=0;
int sizeW=20;
int sizeH=20;
static int quit = 0;
void render()
{
SDL_Rect r_scr;
r_scr.x = posX;
r_scr.y = posY;
r_scr.w = sizeW;
r_scr.h = sizeH;
SDL_SetRenderDrawColor( renderer, 0x00, 0x00, 0x00, 0xFF );
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0x00, 0x00);
SDL_RenderDrawRect(renderer, &r_scr);
SDL_RenderPresent(renderer);
}
#if __EMSCRIPTEN__
void main_tick() {
#else
int main_tick() {
#endif
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
{
quit = 1;
break;
}
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym)
{
case SDLK_UP:
{
if (posY>=20)
{
posY-=20;
}
break;
}
case SDLK_DOWN:
{
if (posY+sizeH<SCREEN_HEIGHT)
{
posY += 20;
}
break;
}
case SDLK_LEFT:
{
if (posX>=20)
{
posX-=20;
}
break;
}
case SDLK_RIGHT:
{
if (posX+sizeW<SCREEN_WIDTH)
{
posX+=20;
}
break;
}
}
break;
}
}
}
render();
SDL_UpdateWindowSurface(window);
#if !__EMSCRIPTEN__
return 0;
#endif
}
void main_loop()
{
#if __EMSCRIPTEN__
emscripten_set_main_loop(main_tick, -1, 1);
#else
while (0 == quit)
{
main_tick();
}
#endif
}
int main()
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"WEBASM",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff);
main_loop();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
index.html
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<script type='text/javascript'>
var Module = {};
fetch('index.wasm')
.then(response =>
response.arrayBuffer()
).then(buffer => {
Module.canvas = document.getElementById("canvas");
Module.wasmBinary = buffer;
var script = document.createElement('script');
script.src = "index.js";
script.onload = function() {
console.log("Emscripten boilerplate loaded.")
}
document.body.appendChild(script);
});
</script>
<canvas id="canvas" style="width:100%; height:100%"></canvas>
</body>
</html>
Makefile
CC=gcc
CFALGS=
LDFLAGS=-lSDL2 -lSDL2_ttf
EM_ENV=LLVM=/usr/bin NODE_JS=node EMSCRIPTEN_ROOT=/usr/lib/emscripten
EM_CC=emcc
EM_CFLAGS=-s WASM=1 -O3
EM_LDFALGS=-s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' -s USE_SDL_TTF=2
pc:
$(CC) $(CFLAGS) $(LDFLAGS) main.c -o main
em:
$(EM_CC) main.c $(EM_CFLAGS) $(EM_LDFALGS) -o index.js -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'
compiling with other flags (e.g. -O1 or -USE_SDL=1) results in the same error.
Worth telling: compiling and running timhutton's example works perfectly well
Edit:
emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.39.16
clang version 11.0.0 (/b/s/w/ir/cache/git/chromium.googlesource.com-external-gec77df5e957828ca0475aa3d566977b)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/user/gitclones/emsdk/upstream/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Selected GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
shared:INFO: (Emscripten: Running sanity checks)
Haha solved it by changing
#if __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#include <SDL2/SDL.h>
#include <SDL/SDL_ttf.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#endif
to
#if __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#endif
the difference is that a lot of examples online use #include <SDL/SDL_ttf.h> which for some reason does not work for me in this situation. This demo even have both versions in its code. Changing SDL to SDL2 before any slash (/) when including headers solved it :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With