用emscripten编译SDL/SDL2导致重定义错误

标签 c linux sdl sdl-2 emscripten

tl;dr 使用 SDL2 编译 C 代码,使用 -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS='["png"]' -s USE_SDL_TTF=2 在 arch linux 上导致大量的“重新定义错误”。

我正在尝试使用 emscripten 在浏览器中使用 SDL2,但它完全失败了。我正在关注 this有关移动黄色方 block 的简单 SDL2 脚本的指南。该示例适用于他的网络浏览器。使用 gcc 在本地编译代码工作得很好并且按预期工作。

我目前正在运行 Arch Linux,并且安装了所有依赖项(SDL2、emscripten、emsdk、lib32-sdl2 sdl2_image sdl2_ttf)。我最初只是安装了 SDL2,并按照说明通过 git 安装了 emscripten 和 emsdk,但当这不起作用时,我尝试通过 repo 安装其余部分。和 AUR。仍然无济于事。我现在已经卸载了列出的每个包并重新安装了 SDL2,我现在只使用 git 安装,如下所示

运行 make em 以使用 emscripten 编译脚本失败并导致以下错误:

/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)

主.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>

生成文件

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"]'

使用其他标志(例如 -O1 或 -USE_SDL=1)编译会导致相同的错误。

值得一说:编译运行timhutton的示例非常有效

编辑:

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)

最佳答案

哈哈改了就解决了

#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

#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

不同的是网上很多例子都是用#include <SDL/SDL_ttf.h>由于某种原因,在这种情况下这对我不起作用。该演示甚至在其代码中包含两个版本。在包含 header 时将任何斜杠 (/) 之前的 SDL 更改为 SDL2 解决了这个问题:)

关于用emscripten编译SDL/SDL2导致重定义错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61985172/

相关文章:

c++ - Linux 上 C++ 程序的资源存储位置

c++ - 编译 SDL 测试时出错

c++ - 我在链接 SDL 库时遇到问题

c - 为什么我不能用这样的其他字符串替换一个字符串?

c - Pthread 未打印正确的值

regex - 如何在 ubuntu 终端的目录中搜索两个标记之间的字符串并保存输出

c++ - 程序在退出时崩溃

c - 如何在 C 中的 for 循环之外使用 for 循环索引(选择排序)

c - C 和 ncurses 中的 ANSI 颜色

linux - debian:mysql-workbench 安装错误 [找不到-lpython2.7.a]