emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.86k stars 3.32k forks source link

compile time errors when including header file emscripten.h from $ENV{EMSDK}/upstream/emscripten/cache/sysroot/include/emscripten #22948

Open reiend opened 4 days ago

reiend commented 4 days ago

emcc - v3.1.71

including header file emscripten.h compiles successfully but it causes compile time error which hinders code completion such as emscripten_set_main_loop.

cmake config

target_include_directories(
    ${CMAKE_PROJECT_NAME} 
    PUBLIC 
        $ENV{EMSDK}/upstream/emscripten/cache/sysroot/include/emscripten
)

for some unknown reason cmake can't include this specific path

$ENV{EMSDK}/upstream/emscripten/cache/sysroot/include

so i use

$ENV{EMSDK}/upstream/emscripten/cache/sysroot/include/emscripten

instead.

first error

In included file: 'emscripten/em_macros.h' file not found. solution

// em_js.h
#include em_macros.h 

second new error

In included file: typedef redefinition with different types ('struct _iobuf' vs 'struct _IO_FILE') [redefinition_different_typedef].

// emscripten.h
struct _IO_FILE;
typedef struct _IO_FILE FILE;

char *emscripten_get_preloaded_image_data(const char *path, int *w, int *h);
char *emscripten_get_preloaded_image_data_from_FILE(FILE *file, int *w, int *h);

my naive solution

// emscripten.h
struct _IO_FILE;

char *emscripten_get_preloaded_image_data(const char *path, int *w, int *h);
char *emscripten_get_preloaded_image_data_from_FILE(_IO_FILE *file, int *w, int *h);

after the following changes compile time error gone and code completion now works.

sbc100 commented 4 days ago

Can you share the full compiler output? I imagine you could be mixing system headers with emscripten headers, but the full output should make it clean what the problem is.

reiend commented 3 days ago

Can you share the full compiler output? I imagine you could be mixing system headers with emscripten headers, but the full output should make it clean what the problem is.

successfully compiles but compiler shows nothing image

image

compiling with build tool cmake was a success too with compiler set to em++ --target=wasm32

the problem is the lsp I'm using, clangd can't seem to find where the headers are even though I included it in the target include directories and compile command json was on.

for some unknown reason cmake can't add this specifically in compile command json

$ENV{EMSDK}/upstream/emscripten/cache/sysroot/include
// this works
$ENV{EMSDK}/upstream/emscripten/cache/sysroot/include/emscripten

when I use clang++ --target=x86_64-windows-gnu, cmake outputs compile command json with the included headers successfully, this is where I encounter the compile time errors. unless I conditionally add headers

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
// do emscripten stuff
#endif

and remove

  $ENV{EMSDK}/upstream/emscripten/cache/sysroot/include

in cmake target include directories, program will not compile and will lose all the code completion lsp provided for emscripten.

sbc100 commented 3 days ago

Which LSP are you using?

The primary include path for emscripten should be upstream/emscripten/cache/sysroot/include. However you should not need to add this explicitly. Also, you can't use the emscripten headers with --target=x86_64-windows-gnu. That target should be wasm32-unknown-emscripten.

Can you not just tell the LSP to use emcc/em++ instead of raw clang/clang++. That would seem like the most (perhaps only) correct solution.

reiend commented 3 days ago

Which LSP are you using?

The primary include path for emscripten should be upstream/emscripten/cache/sysroot/include. However you should not need to add this explicitly. Also, you can't use the emscripten headers with --target=x86_64-windows-gnu. That target should be wasm32-unknown-emscripten.

Can you not just tell the LSP to use emcc/em++ instead of raw clang/clang++. That would seem like the most (perhaps only) correct solution.

Thanks @sbc100 for quick response.

I use clangd.

changing target to wasm32-unknown-emscripten with clang++ as compiler gives me error

error: unable to create target: 'No available targets are compatible with triple "wasm32-unknown-emscripten"'

this error occur because by default this config

  set(CMAKE_C_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_C_COMPILER clang)
  set(CMAKE_CXX_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_CXX_COMPILER clang++)

uses clang++ not provided by emscripten

// clang++ --print-targets
  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64

changing the config to use the emscripten provided clang++

  // $ENV{EMSDK}/upstream/bin/clang++.exe --print-targets
    Registered Targets:
    wasm32 - WebAssembly 32-bit
    wasm64 - WebAssembly 64-bit
    x86    - 32-bit X86: Pentium-Pro and above
    x86-64 - 64-bit X86: EM64T and AMD64

  set(CMAKE_C_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_C_COMPILER "$ENV{EMSDK}/upstream/bin/clang.exe")
  set(CMAKE_CXX_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_CXX_COMPILER "$ENV{EMSDK}/upstream/bin/clang++.exe")

this gives me next error

FAILED: cmTC_dca1b.exe

    wasm-ld: error: unknown argument: --out-implib
    wasm-ld: error: unknown argument: --major-image-version
    wasm-ld: error: unknown argument: --minor-image-version
    wasm-ld: error: cannot open crt1.o: no such file or directory
    wasm-ld: error: cannot open libcmTC_aacba.dll.a: no such file or directory
    wasm-ld: error: cannot open 0: no such file or directory
    wasm-ld: error: cannot open 0: no such file or directory
    wasm-ld: error: unable to find library -lkernel32
    wasm-ld: error: unable to find library -luser32
    wasm-ld: error: unable to find library -lgdi32
    wasm-ld: error: unable to find library -lwinspool
    wasm-ld: error: unable to find library -lshell32
    wasm-ld: error: unable to find library -lole32
    wasm-ld: error: unable to find library -loleaut32
    wasm-ld: error: unable to find library -luuid
    wasm-ld: error: unable to find library -lcomdlg32
    wasm-ld: error: unable to find library -ladvapi32
    wasm-ld: error: unable to find library -lc++
    wasm-ld: error: unable to find library -lc++abi
    wasm-ld: error: unable to find library -lc
reiend commented 3 days ago

Which LSP are you using? The primary include path for emscripten should be upstream/emscripten/cache/sysroot/include. However you should not need to add this explicitly. Also, you can't use the emscripten headers with --target=x86_64-windows-gnu. That target should be wasm32-unknown-emscripten. Can you not just tell the LSP to use emcc/em++ instead of raw clang/clang++. That would seem like the most (perhaps only) correct solution.

Thanks @sbc100 for quick response.

I use clangd.

changing target to wasm32-unknown-emscripten with clang++ as compiler gives me error

error: unable to create target: 'No available targets are compatible with triple "wasm32-unknown-emscripten"'

this error occur because by default this config

  set(CMAKE_C_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_C_COMPILER clang)
  set(CMAKE_CXX_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_CXX_COMPILER clang++)

uses clang++ not provided by emscripten

// clang++ --print-targets
  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64

changing the config to use the emscripten provided clang++

  // $ENV{EMSDK}/upstream/bin/clang++.exe --print-targets
    Registered Targets:
    wasm32 - WebAssembly 32-bit
    wasm64 - WebAssembly 64-bit
    x86    - 32-bit X86: Pentium-Pro and above
    x86-64 - 64-bit X86: EM64T and AMD64

  set(CMAKE_C_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_C_COMPILER "$ENV{EMSDK}/upstream/bin/clang.exe")
  set(CMAKE_CXX_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_CXX_COMPILER "$ENV{EMSDK}/upstream/bin/clang++.exe")

this gives me next error

FAILED: cmTC_dca1b.exe

    wasm-ld: error: unknown argument: --out-implib
    wasm-ld: error: unknown argument: --major-image-version
    wasm-ld: error: unknown argument: --minor-image-version
    wasm-ld: error: cannot open crt1.o: no such file or directory
    wasm-ld: error: cannot open libcmTC_aacba.dll.a: no such file or directory
    wasm-ld: error: cannot open 0: no such file or directory
    wasm-ld: error: cannot open 0: no such file or directory
    wasm-ld: error: unable to find library -lkernel32
    wasm-ld: error: unable to find library -luser32
    wasm-ld: error: unable to find library -lgdi32
    wasm-ld: error: unable to find library -lwinspool
    wasm-ld: error: unable to find library -lshell32
    wasm-ld: error: unable to find library -lole32
    wasm-ld: error: unable to find library -loleaut32
    wasm-ld: error: unable to find library -luuid
    wasm-ld: error: unable to find library -lcomdlg32
    wasm-ld: error: unable to find library -ladvapi32
    wasm-ld: error: unable to find library -lc++
    wasm-ld: error: unable to find library -lc++abi
    wasm-ld: error: unable to find library -lc

if it matters OS - Windows NT Terminal - Windows Terminal Shell - Powershell

sbc100 commented 3 days ago

If you want to use em++/emcc with cmake the easiest way is to use emcmake (or -DCMAKE_TOOLCHAIN_FILE=cmake/Modules/Platform/Emscripten.cmake)

The issues you are running into here are because cmake still thinks you are targetting windows, when you are not.

reiend commented 3 days ago

Thank you for the suggestion @sbc100, I'll probably stick with the toolchain setup

  set(CMAKE_TOOLCHAIN_FILE $ENV{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake)
  set(CMAKE_C_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_C_COMPILER emcc)
  set(CMAKE_CXX_COMPILER_TARGET wasm32-unknown-emscripten) 
  set(CMAKE_CXX_COMPILER em++)
sbc100 commented 3 days ago

Thank you for the suggestion @sbc100, I'll probably stick with the toolchain setup

  set(CMAKE_TOOLCHAIN_FILE $ENV{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake)

If you use this line then you should not also need CMAKE_C_COMPILER_TARGET/CMAKE_C_COMPILER/etc since the Emscripten.cmake should take care of that.

sbc100 commented 3 days ago

Assuming that works can we close this issue?

reiend commented 3 days ago

Thank you for the suggestion @sbc100, I'll probably stick with the toolchain setup

  set(CMAKE_TOOLCHAIN_FILE $ENV{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake)

If you use this line then you should not also need CMAKE_C_COMPILER_TARGET/CMAKE_C_COMPILER/etc since the Emscripten.cmake should take care of that.

noted.

reiend commented 3 days ago

Assuming that works can we close this issue?

this works and compiles successfully but still show lsp diagnostics errors cause of not including target directories for emscripten