emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.63k stars 3.29k forks source link

Compilation failure when using <iostream> #15576

Closed HenryAWE closed 2 years ago

HenryAWE commented 2 years ago

emcc&em++ version: 2.0.31 My Code:

#include <iostream>

int main()
{
    std::cout << "hello emscripten" << std::endl;
    return 0;
}

Error Output:

[ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.o
In file included from /mnt/d/dev-wsl/submodule/main.cpp:1:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/iostream:37:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/ios:215:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:15:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/string:511:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/string_view:179:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__string:57:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/algorithm:653:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/memory:687:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/atomic:579:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__threading_support:17:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/errno.h:10:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/bits/errno.h:1:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/wasi/api.h:29:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/stddef.h:17:
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/bits/alltypes.h:291:54: error: typedef redefinition with different types ('struct max_align_t' vs 'struct max_align_t')
typedef struct { long long __ll; long double __ld; } max_align_t;
                                                     ^
/mnt/d/dev-wsl/emsdk/upstream/lib/clang/14.0.0/include/__stddef_max_align_t.h:24:3: note: previous definition is here
} max_align_t;
  ^
In file included from /mnt/d/dev-wsl/submodule/main.cpp:1:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/iostream:37:
In file included from /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/ios:215:
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:461:32: error: use of undeclared identifier '_CTYPE_S'
    static const mask space  = _CTYPE_S;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:462:32: error: use of undeclared identifier '_CTYPE_R'
    static const mask print  = _CTYPE_R;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:463:32: error: use of undeclared identifier '_CTYPE_C'
    static const mask cntrl  = _CTYPE_C;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:464:32: error: use of undeclared identifier '_CTYPE_U'
    static const mask upper  = _CTYPE_U;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:465:32: error: use of undeclared identifier '_CTYPE_L'
    static const mask lower  = _CTYPE_L;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:466:32: error: use of undeclared identifier '_CTYPE_A'
    static const mask alpha  = _CTYPE_A;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:467:32: error: use of undeclared identifier '_CTYPE_D'
    static const mask digit  = _CTYPE_D;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:468:32: error: use of undeclared identifier '_CTYPE_P'
    static const mask punct  = _CTYPE_P;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:469:32: error: use of undeclared identifier '_CTYPE_X'
    static const mask xdigit = _CTYPE_X;
                               ^
/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/__locale:477:32: error: use of undeclared identifier '_CTYPE_B'
    static const mask blank  = _CTYPE_B;
                               ^
11 errors generated.
em++: error: '/mnt/d/dev-wsl/emsdk/upstream/bin/clang++ -target wasm32-unknown-emscripten -DEMSCRIPTEN -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=31 -D_LIBCPP_ABI_VERSION=2 -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot -Xclang -iwithsysroot/include/compat -I/mnt/d/dev-wsl/submodule/submod/. -isystem /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include -g -c /mnt/d/dev-wsl/submodule/main.cpp -o CMakeFiles/main.dir/main.cpp.o' failed (returned 1)
CMakeFiles/main.dir/build.make:63: recipe for target 'CMakeFiles/main.dir/main.cpp.o' failed
make[2]: *** [CMakeFiles/main.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:72: recipe for target 'CMakeFiles/main.dir/all' failed
make[1]: *** [CMakeFiles/main.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
HenryAWE commented 2 years ago

Some additional information I've compiled AngelScript library by Emscripten and it worked well. But when I link it with codes that has #include <iostream>, this strange error occurs.

sbc100 commented 2 years ago

That is very odd. The code compiles just fine a simple em++ -c test.cc call. Can you share the full emcc command that fails?

Sadly the makefile generated by cmake hides this command from you by default. You can work around this by running make VERBOSE=1 or by using -Gninja which always shows the failing command. (I recommend using ninja for this and other reasons).

sbc100 commented 2 years ago

Are there any header files in /mnt/d/dev-wsl/submodule/submod that might be confused for the system headers?

HenryAWE commented 2 years ago

Are there any header files in /mnt/d/dev-wsl/submodule/submod that might be confused for the system headers?

There is only one header file for testing the sub-project function of CMake. But that header file only declares one simple function for testing and doesn't include any other header file. I think it won't confuse the system headers.

HenryAWE commented 2 years ago

That is very odd. The code compiles just fine a simple em++ -c test.cc call. Can you share the full emcc command that fails?

Sadly the makefile generated by cmake hides this command from you by default. You can work around this by running make VERBOSE=1 or by using -Gninja which always shows the failing command. (I recommend using ninja for this and other reasons).

I ran make VERBOSE=1 and the em++ command is as follow

[ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.o
/mnt/d/dev-wsl/emsdk/upstream/emscripten/em++   @CMakeFiles/main.dir/includes_CXX.rsp -g   -o CMakeFiles/main.dir/main.cpp.o -c /mnt/d/dev-wsl/submodule/main.cpp

I think the content of the includes_CXX.rsp might be helpful

-I/mnt/d/dev-wsl/submodule/submod/. -isystem /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include
sbc100 commented 2 years ago

Can you add -v to your CFLAGS and run again and include the full output.

Also, can you skip the whole cmake thing and just run via emcc -c main.cpp .. that should give the same result but reduce the number of moving parts involved.

sbc100 commented 2 years ago

The problem is that -isystem /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include being injected by cmake. Do you know where that is come from?

That is having the effect of putting the C headers before the C++ headers in the input path. Can you remove that addition? When you run emcc/clang you should see that C++ headers first in the include path:

#include <...> search starts here:
 /usr/local/google/home/sbc/dev/wasm/emscripten/cache/sysroot/include/SDL
 /usr/local/google/home/sbc/dev/wasm/emscripten/cache/sysroot/include/compat
 /usr/local/google/home/sbc/dev/wasm/emscripten/cache/sysroot/include/c++/v1
 /usr/local/google/home/sbc/dev/wasm/llvm-build/lib/clang/14.0.0/include
 /usr/local/google/home/sbc/dev/wasm/emscripten/cache/sysroot/include
End of search list.

See how emscripten/cache/sysroot/include comes last? In C++ mode the sysroot/include/stddef.h should never get includes since the C++ version in lib/clang/14.0.0/include/stddef.h will override.

HenryAWE commented 2 years ago

I think the injection is caused by angelscript installation. Because after I configured the library using emcmake cmake and then compiled and installed it, its header was automatically installed in the Emscripten's sysroot/include directory.

HenryAWE commented 2 years ago

After moving the angelscript's installation to a normal directory, this error disappeared.

HenryAWE commented 2 years ago

It seems that this error is causing by emcmake setting an inappropriate default install directory for cmake's install command.

sbc100 commented 2 years ago

sysroot/include seems like a good default to me. Where else would you expect the install step to put stuff by default?

Do you know why installing angelscript cause issues, does it contains headers or other files that conflict with or overwrite system headers?

HenryAWE commented 2 years ago

I think default installation path needs a standalone path, which means it shouldn't mix with the system folder. The angelscript library only has a angelscript.h and its header is installed in sysroot/include by default. It is this header that let cmake inject the include command that cause the trouble.

HenryAWE commented 2 years ago

I searched the ChangeLog.md and noticed a new feature added in version 2.0.24 - 06/10/2021. It mentioned that Emscripten.cmake will set cmake's default install path to the sysroot of Emscripten.
Link to the content in ChangeLog.md

sbc100 commented 2 years ago

Indeed, this is what emscripten does, but why is installing angelscript.h in this directory causing any issue? What are your resons for believing that.

From my POV the problem is the -isystem /mnt/d/dev-wsl/emsdk/upstream/emscripten/cache/sysroot/include argument being passed to emscripten. Its because of this that the wrong version stddef.h is being included. The one in /usr/local/google/home/sbc/dev/wasm/emscripten/cache/sysroot/include/c++/v1 should take precedence. Do you know how/why this argument is being added?

sbc100 commented 2 years ago

Make you could share your entire CMake project? It might help track down where this is coming from?

HenryAWE commented 2 years ago

Do you know how/why this argument is being added?

Because angelscript.h is installed to sysroot/include by default. And then I use cmake's find_package() command to locate the angelscript installation in the project, which will automatically set up the include directory and linking flags.
Besides, after I moved the angelscript to /mnt/d/dev-wsl/emlib/ and told this path to cmake manually , the include_CXX.rsp's content (generated by cmake) changed to -isystem /mnt/d/dev-wsl/emlib/include and the sysroot/include disappeared.

sbc100 commented 2 years ago

I see, so cmake is using -isystem here it inject paths to packages it finds. But it currently breaks the include order in emscripten if one adds -isystem that points to sysroot/include. This does seems like something that we can/should work around.

Simply telling cmake to install headers into some other folder is only a partial workaround since we have our own system packages that install into sysroot/include (for example zlib). Any user that uses find_package to locate zlib would presumably run into the same issue.

So I think we need to do some further investigation.