Emscripten Clang produce ELF 64-bit executabel and wasm binary cross compiler targets - clang++

I have a prepared a minimal Cmake project containing one cpp file which represent the main and one cpp file which represent the shared library, that prints basically hello world.
https://github.com/courteous/wasmELF.git
The target is to compile this miniaml code with emscripten/clang only and produce
1) one WebAssembly (wasm) binary module version 0x1 (MVP)
2) one ELF 64-bit LSB
without clearing the cmake build directory and rebuilding it again.
Currently i can successfully produce them bought by running the commands
emconfigure cmake ../ -DCMAKE_BUILD_TYPE=WASM
make
and
cmake ../ -DCMAKE_BUILD_TYPE=Linux
make
However the problem is that in order to do that i need to compile the first one with Clang the to remove the build and then to do a second compilation with GCC. I would like Emscripten/Clang to produce them bought instead. I do not want to delete the build directory since the compilation times is taking too long. (Well not in this Project but imagine if the project was much larger)
What i see is that emscripten/clang selects always a target "wasm32-unknown-emscripten"
clang++ -target wasm32-unknown-emscripten
and if i understand that correctly the target should change
I do see that the project is producing LLVM IR bitcode since i have send the flag "flto"
i.e.
file TestSharedClass.cpp.o
TestSharedClass.cpp.o: LLVM IR bitcode
and in the CMakeLists.txt
set(CMAKE_CXX_FLAGS "-flto")
x86_64-unknown-linux-gnu is a supported target by emscripten/Clang
~/Projects/emscripten/emsdk/upstream/bin$ ./llc --version
LLVM (http://llvm.org/):
LLVM version 11.0.0git
Optimized build with assertions.
Default target: x86_64-unknown-linux-gnu
Host CPU: haswell
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
In cmake i do have
SET(TARGET x86_64-unknown-linux-gnu)
however when i run
emconfigure cmake ../ -DCMAKE_BUILD_TYPE=Linux
make
i get mainTestFile.js and mainTestFile.wasm instead of ELF 64-bitcode.
what i am doing wrong here. How to tell clang to product once ELF and once wasm from the same code run without having to clear the build directory. This should be possible since clang is producing LLVM IR bitcode. Or do i understand that wrong?
https://github.com/emscripten-core/emscripten/issues/10361

OK that seems to not be possible i.e. the reply from the dev on github states that emcc or emmake can not be used with another target other then wasm32-unknown-emscripten.

Related

Linux kernel on ARM Cortex-M: how to build proper executables

I need to build a complete linux development framework for a Cortex-M MCU, specifically a STM32F7 Cortex-M7. First I've to explain some background info so please bear with me.
I've downloaded and built a gcc toolchain with croostool-ng 1.24 specifying an armv7e-m architecture with thumb-only instructions and linux 4.20 as the OS and that I want the output to be FLAT executables (I assumed it will mean bFLT).
Then I proceeded to compile the linux kernel (version 4.20) using configs/stm32_defconf, and then a statically compiled busybox rootfs, all using my new toolchain.
Kernel booted just fine but throw me an error and kernel painc with the following message:
Starting init: /sbin/init exists but couldn't execute it (error -8)
and
request_module: modprobe binfmt-464c cannot be processed, kmod busy with 50 threads
The interesting part is the last message. My busybox excutable turned out to be an .ELF! Cortex-M has no MMU, so it's imposible to build a linux kernel on a MMU-less architecture with .ELF support, that's why an (464c)"LF" binary loader can't be found, there is none.
So at last, my question is:
how could I build bFLT executables to run on MMU-less Linux architectures? My toolchain has elf2flt, but in crosstool-ng I've already specified a MMU-less architecture and FLAT binary and I was expecting direct bFLT output, not a "useless" executable. Is that even possible?
Or better: is there anywhere a documented standard procedure to build a complete, working Linux system based on Cortex-M?
Follow-up:
I gave up on building FLAT binaries and tried FDPIC executables. Another dead end. AFAIK:
Linux has long been supporting ELF FDPIC, but the ABI for ARM is pretty new.
It seems that still at this day and age, GCC has not a standard way to enable FDPIC. On some architectures you can use -mfdpic. Not on arm, don't know why. I even don't know if ARM FDPIC is supported at all by mainline GCC. Info is extremely scarce if inexistent.
It seems crosstool-ng 1.24 is BROKEN at building ARM ELF FDPIC support. Resulting gcc has not -mfdpic, and -fPIC generates ARM executables, not ARM FDPIC.
Any insight will be very appreciated.
you can generate FDPIC ELF files just with a prebuilt arm-linux-gnueabi-gcc compiler.
Specifications of an FDPIC ELF file:
Position independent executable/code (i.e. -fPIE and fPIC)
Should be compiled as a shared executable (ET_DYN ELF) to be position independent
use these flags to compile your programs:
arm-linux-gnueabi-gcc -shared -fPIE -fPIC <YOUR PROGRAM.C> -o <OUTPUT FILE>
I've compiled busybox successfully for STM32H7 with this method.
As I know, unfortunately FDPIC ELFs should be compiled with - shared flag so, they use shared libraries and cannot be compiled as -static ELF.
For more information take a look at this file:
https://github.com/torvalds/linux/blob/master/fs/binfmt_elf_fdpic.c
Track the crosstool-ng BFLAT issue from here:
https://github.com/crosstool-ng/crosstool-ng/issues/1399

Cmake cross compiling linker errors

I have a project which must be build for two different architectures. I am running a x86_64 Linux machine with gcc installed at default path and also I have a cross-compiler gcc for second PowerPC Linux machine.
I have one CMakeLists.txt file where compiler choice depends on passed variable.
The problem is that when it uses not default compiler it somehow uses default linker that obviously can not link the executable with provided libraries.
So, I set
set(CMAKE_C_COMPILER ${tools}/bin/powerpc-e500v2-linux-gnuspe-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/powerpc-e500v2-linux-gnuspe-g++)
so it would use my cross-compiler but then there are errors in console
/usr/bin/ld: skipping incompatible /home/namtarr/Documents/libevent/usr/lib/powerpc-linux-gnuspe/libevent.a when searching for -levent
If I try to set
set(CMAKE_C_LINK_EXECUTABLE ${tools}/bin/powerpc-e500v2-linux-gnuspe-ld)
set(CMAKE_CXX_LINK_EXECUTABLE ${tools}/bin/powerpc-e500v2-linux-gnuspe-ld)
it throws another error
/home/namtarr/x-tools/powerpc-e500v2-linux-gnuspe/bin/powerpc-e500v2-linux-gnuspe-ld: no input files
So how can I properly set linker in Cmake and pass needed input files to it so I could build my project for two platforms with one CMakeLists.txt?

Can gcc produce binary for Arm without cross compilation

Can we configure gcc running on intel x64 architecture to produce binary for ARM chip by just passing some flags to gcc and not using a cross compiler.
Short: Nope
Compiler:
gcc is not a native crosscompiler, the target architecture has to be specified at the time you compile gcc. (Some exceptions apply, as for example x86 and x86_64 can be supported at the same time)
clang would be a native crosscompiler, and you can generate code for arm by passing -target=arm-linux-gnu, but you still cant produce binaries, as you need a linker and a C-library too. Means you can run clang -target=arm-linux-gnu -c <your file> and compile C/C++ Code (will likely need to point it to your C/C++ include paths) - but you cant build binaries.
Rest of the toolchain:
You need a fitting linker and toolchain too, both are specific to the architecture and OS you want to run at.
Possible solutions:
Get a fitting toolchain, or compile your own. For arm linux you have for ex. CrossToolchains if you are on debian, for barebones you can get a crosscompiler from codesourcery.
Since you were very vague, its not possible to give you a clearer answer

How do I compile and link a 32-bit Windows executable using mingw-w64

I am using Ubuntu 13.04 and installed mingw-w64 using apt-get install mingw-w64. I can compile and link a working 64-bit version of my program with the following command:
x86_64-w64-mingw32-g++ code.cpp -o app.exe
Which generates a 64-bit app.exe file.
What binary or command line flags do I use to generate a 32-bit version of app.exe?
That depends on which variant of toolchain you're currently using. Both DWARF and SEH variants (which come starting from GCC 4.8.0) are only single-target. You can see it yourself by inspecting the directory structure of their distributions, i.e. they contain only the libraries with either 64- or 32-bit addressing, but not both. On the other hand, plain old SJLJ distributions are indeed dual-target, and in order to build 32-bit target, just supply -m32 flag. If that doesn't work, then just build with i686-w64-mingw32-g++.
BONUS
By the way, the three corresponding dynamic-link libraries (DLLs) implementing each GCC exception model are
libgcc_s_dw2-1.dll (DWARF);
libgcc_s_seh-1.dll (SEH);
libgcc_s_sjlj-1.dll (SJLJ).
Hence, to find out what exception model does your current MinGW-w64 distribution exactly provide, you can either
inspect directory and file structure of MinGW-w64 installation in hope to locate one of those DLLs (typically in bin); or
build some real or test C++ code involving exception handling to force linkage with one of those DLLs and then see on which one of those DLLs does the built target depend (for example, can be seen with Dependency Walker on Windows); or
take brute force approach and compile some test code to assembly (instead of machine code) and look for presence of references like ___gxx_personality_v* (DWARF), ___gxx_personality_seh* (SEH), ___gxx_personality_sj* (SJLJ); see Obtaining current GCC exception model.

build c file with openssl by NDK under cygwin

I am trying to build c file included by ndk under cygwin
In Android.mk, I add -I/usr/include to LOCAL_FLAGS like
LOCAL_FLAGS := -I/usr/include
And I have checked that openssl does under /usr/include
But when I run ndk-build under by project dir, it output
"fatal error: openssl/ssl.h: No such file or directory"
I think I have specified the include directory, but not solve this problem.
Is there any other way can I try?
You seem to have some gaps in your knowledge:
C code compiles to processor's native instruction set. Your desktop/build machine probably has a different architecture from your Android device(thus a different instruction set).
NDK doesn't just compile, it cross-compiles. It means that the NDK runs on the build machine, but the executable it produces cannot run on the build machine(different instruction sets).
All libraries on your desktop are in your desktop's processoer's instruction set. Thus, you cannot link any program build by the NDK using the desktop's libraries. This means:
No includes from '/usr/include/'
No libs from /lib, /usr/lib, /lib64 or /usr/lib64
No Cygwin packages under on Windows
What you need to do is build your own openssl using the NDK and use that to link against when you build your executable.
Please note that the answer is missing a lot of information (at least 3 Bachelor's level Computer Science courses worth of information).

Resources