Linux 64bits : cross-compile for 32bits target using cmake - linux

I'm using gcc+cmake in a Linux 64bits and my compilation target is Linux 32bits.
So I added -m32 to my CMAKE_C_FLAGS.
But then cmake fails with the message: The C compiler "/usr/bin/gcc" is not able to compile a simple test program.
Of course, this is because a 32bits executable can't run on 64bits arch.
I had a look on the cross compilation cmake's page, but it seems very complex for my need.
So, my question : is there a way to simply build a 32bits binary (exe or lib) using cmake?
For information, here is what I tried by using an environment variable:
Add `${myflag}` to CMAKE_C_FLAGS
Set myflag to empty.
Call cmake to generate a makefile (so it will successfully check the compiler)
Set myflag to -m32.
Call make (so it will compile with my -m32 option
But it seems that gcc doesn't evaluate user environment variables.

Related

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

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.

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

specify target with gcc

I am trying to compile a library in linux with gcc. I want the lib to run on a different platform.
With configure, we normally use build and host. However, this library has no configure option. So I am writing my own code to compile lib using GCC. How I can specify the target machine as an option with GCC?
Unless the target is already possible with the current GCC (e.g. like the -m32 option of GCC on x86-64 Linux) you cannot compile your code with your usual GCC.
You have to either download and install a GCC cross-compiler or compile (as a cross-compiler using the --target= option for ./configure) GCC from its source code.
Every GCC installation has one single (main) target.
BTW, some Linux distributions are packaging some GCC cross-compilers. On Debian I have gcc-arm-none-eabi (targeted for ARM) and gcc-msp430 (targeted for MSP430)

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.

Resources