How do I tell gcc to use a specific instantiation of glibc? - gcc

For "reasons", I need to build an x86 toolchain that emits no SIMD instructions (trying to use -march isn't enough because glibc will include functions that are built to use SIMD instructions, etc.).
I have built my own gcc 5.3 using the following configure flags:
../src/gcc/configure --prefix=/scratch/install --enable-languages=c,c++ \
--with-cpu=ivybridge \
--with-arch=ivybridge \
CFLAGS="-march=ivybridge" \
CXXFLAGS="-march=ivybridge"
I then built my own glibc using the following configure flags:
../src/glibc/configure --prefix=/scratch/install --with-arch=ivybridge \
CC="/scratch/install/bin/gcc" \
CXX="/scratch/install/bin/g++" \
CFLAGS="-O2 -march=ivybridge" \
CXXFLAGS="-O2 -march=ivybridge -Wa,-march=corei7+nommx+nosse+noavx"`
I verified that my gcc is NOT using my glibc.
$ /scratch/install/bin/gcc -print-file-name=libc.so
/usr/lib/x86_64-linux-gnu/libc.so
Question:
How do I link in my newly compiled glibc? I'm only interested in compiling -static binaries, if that helps.

I verified that my gcc is NOT using my glibc.
Why would it?
You need to rebuild gcc again, adding --with-sysroot=/scratch/install (and possibly other flags).
In general, building correct linux-to-linux cross-compilers is quite tricky, and you may find that using crosstool-ng will save you quite a bit of trial and error.

Related

Can't build old libstdc++.so.6 (gcc-5 on arm-glibc-2.13) with version symbols included (leading to libstdc++.so.6: no version information available)

I need to run a dotnet5 app (or build dotnet5 from source) to be compatible with arm machines with very old glibc (as low as glibc-2.13, cannot be upgraded because these are semi-embedded systems).
The target machines come with libstdc++ based on gcc <5.1 and therefore don't support the necessary C++11 ABI.
First solution was to "just" get an arm-binary libstdc++.so.6.0.21 from somewhere and trying to run the app with it (via LD_LIBRARY_PATH). This almost worked, but this libstdc++ depended on glibc-2.16.
Next solution: build gcc >=5.1 (including libstdc++) from source in my debian-wheezy-armhf container, which is based on glibc-2.13.
This works quite well, though I have to force a few things because the gcc build process at some stages seems to believe it's cross-building (but not really?), getting errors like this: cannot find bits/predefs.h and hard- vs. soft-float errors. These were solved by doing the build like this (Makefile rule executed in build container):
C_INCLUDE_PATH=/usr/include:/usr/include/$$(gcc -print-multiarch); \
CPATH=/usr/include:/usr/include/$$(gcc -print-multiarch); \
LIBRARY_PATH=/usr/lib:/usr/lib/$$(gcc -print-multiarch); \
CFLAGS="-mfloat-abi=hard"; \
CXXFLAGS="-mfloat-abi=hard"; \
LDFLAGS="-mfloat-abi=hard"; \
export LIBRARY_PATH C_INCLUDE_PATH CPATH CFLAGS CXXFLAGS LDFLAGS; \
../gcc-5.5.0/configure --enable-languages=c,c++ --enable-shared=libgcc,libstdc++ `#--build=$$(gcc -print-multiarch)` --disable-multilib --disable-bootstrap --prefix=/build/install \
&& make -j24 && make install
... but the resulting libstdc++ doesn't contain version symbols:
> objdump -p .build/arm-glibc2.13/install/lib/libstdc++.so.6.0.21 | grep GLIBCXX
# nothing
/build/gcc-5.5.0-build/armv7l-unknown-linux-gnueabihf/libstdc++-v3/config.log shows:
configure:78121: WARNING: === You have requested GNU symbol versioning, but
configure:78123: WARNING: === you are not building a shared libgcc_s.
configure:78125: WARNING: === Symbol versioning will be disabled.
so that appears to be the reason. But why am I not building a shared libgcc_s? Even with --enable-shared=libgcc,libstdc++ (which is supposed to be the default anyway) it doesn't work...
Any ideas?

Building gcc 11.2 with jit support requires GMP, MPFR, MPC, ISL recompiled with -fPIC

I'm on a CentOS 7 Linux system where I don't have the root access. So I have to build gcc from source. I want to build gcc 11.2 with the jit support. I invoked
contrib/download_prerequisites for GMP, MPFR, MPC and ISL. Then from a build directory I configured gcc using
../gcc-11.2.0/configure --prefix=/some/path --enable-bootstrap --enable-shared \
--enable-host-shared --enable-threads=posix --enable-languages=c,c++,jit \
--disable-multilib
then I hit make.
It failed with ld errors asking me to recompile libisl.a, libmpc.a, libmpfr.a, libgmp.a with -fPIC. Right before these errors I saw lots of jit related outputs. I assume jit is behind all of this?
Then I tried adding CFLAGS=-fPIC to the above configure command as ../gcc-11.2.0/configure CFLAGS=-fPIC *rest_of_the_options_above*. The same ld errors were emitted.
I'm aware that those dependencies each has --with-pic option to their own configure. But I'm wondering if there is a way to have gcc invoke that for me? If not, does it mean that to build gcc with jit support, one has to build the four dependencies manually with --with-pic? Thanks.

Using Clang to compile for RISC-V

I am trying to build a hello world program using Clang (version 12.0.1) for RISC-V architecture. I have installed it with LLVM (version 12.0.1) with the following setup:
cmake -G "Unix Makefiles" \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests" \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_ASSERTIONS=On \
../llvm
According to here, default LLVM_TARGETS_TO_BUILD is LLVM_ALL_TARGETS, which includes RISC-V.
So I try to compile it with clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world and I am getting the error:
hello_world.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
^~~~~~~~~
1 error generated.
At the same time, /opt/risv/, where I have installed the riscv-gnu-toolchain, is in my path, and I can run riscv64-unknown-linux-gnu-gcc hello_world.c -o hello_world without issues.
I am trying on an Ubuntu machine with kernel 5.8.0-63-generic.
Any idea how can I solve this issue and be able to compile RISC-V programs through Clang?
Foreknowledge:
I had same delusion about this: "If llvm is targeting for all backends including riscv, we should be able to compile our codes just giving a clang flag like --target=riscv32, -target riscv64 etc. without doing extra operation" and I had similar question, but it is not like that. Although LLVM supports riscv target, you need to specify sysroot and gcc toolchain for using riscv headers and libraries, in the other words you need cross compilation. (because you are currently operating a system like x86-64 different from riscv and your default libraries are different) That's why you need to link your riscv-gnu-toolchain paths. Here I assume that you built your riscv-gnu-toolchain from github clone.
Note: Some people have problems with first option (1) and please try to use other options (2) (3) (4) firstly. (Look into comments.)
Solution:
1-) You can add these lines as your cmake configuration flags before building your llvm library:
For 32 bit riscv:
-DDEFAULT_SYSROOT="{your-riscv-gnu-toolchain-install-or-build-path}/riscv32-unknown-elf"
-DGCC_INSTALL_PREFIX="{your-riscv-gnu-toolchain-install-or-build-path}"
For 64 bit riscv:
-DDEFAULT_SYSROOT="{your-riscv-gnu-toolchain-install-or-build-path}/riscv64-unknown-elf"
-DGCC_INSTALL_PREFIX="{your-riscv-gnu-toolchain-install-or-build-path}"
and then build llvm library again. Probably as you know, in your llvm build directory:
cmake --build .
Here is an example in my case according to your cmake configuration for clearance:
cmake -G "Unix Makefiles" \
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;libcxx;libcxxabi;libunwind;lldb;compiler-rt;lld;polly;debuginfo-tests" \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_ASSERTIONS=On \
-DDEFAULT_SYSROOT="/home/shc/riscv/install/riscv64-unknown-elf" \
-DGCC_INSTALL_PREFIX="/home/shc/riscv/install" \
../llvm
cmake --build .
Also you can set default target triple as riscv with another cmake configuration flag:
For 32 bit riscv:
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv32-unknown-elf"
For 64 bit riscv:
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf"
After this you should be able to compile your codes like these examples:
For C:
/home/shc/llvm/llvm-project/build/bin/clang -march=rv64gc hello_world.c -o hello_world
For C++:
/home/shc/llvm/llvm-project/build/bin/clang++ -march=rv64gc hello_world.cpp -o hello_world
If you didn't set default target triple with cmake flag, target option should remain:
For C:
/home/shc/llvm/llvm-project/build/bin/clang --target=riscv64 -march=rv64gc hello_world.c -o hello_world
For C++:
/home/shc/llvm/llvm-project/build/bin/clang++ --target=riscv64 -march=rv64gc hello_world.cpp -o hello_world
2-) You can pass sysroot and gcc toolchain as flags(as in cmake configurations above) while compiling your code without building your library again. However, if you will use this, you need to give these flags in every compilation:
For 32 bit riscv:
--sysroot="{your-riscv-gnu-toolchain-install-or-build-path}/riscv32-unknown-elf"
--gcc-toolchain="{your-riscv-gnu-toolchain-install-or-build-path}"
For 64 bit riscv:
--sysroot="{your-riscv-gnu-toolchain-install-or-build-path}/riscv64-unknown-elf"
--gcc-toolchain="{your-riscv-gnu-toolchain-install-or-build-path}"
Usage of Flags For C:
/home/shc/llvm/llvm-project/build/bin/clang --sysroot=/home/shc/riscv/install/riscv64-unknown-elf --gcc-toolchain=/home/shc/riscv/install --target=riscv64 -march=rv64gc hello_world.c -o hello_world
Usage of Flags For C++:
/home/shc/llvm/llvm-project/build/bin/clang++ --sysroot=/home/shc/riscv/install/riscv64-unknown-elf --gcc-toolchain=/home/shc/riscv/install --target=riscv64 -march=rv64gc hello_world.cpp -o hello_world
3-) You can try to pass these flags while compiling (instead of your --target=riscv64 flag) although it is not more healthy than above options. (Attention: difference is only linux keyword, normally it was -target riscv32-unknown-elf):
For 32 bit riscv:
-target riscv32-unknown-linux-elf
For 64 bit riscv:
-target riscv64-unknown-linux-elf
4-) You can use riscv-llvm repo by following given instructions, although it is outdated.
Note: I adapted my file locations to your examples to better understanding.
Further information you can look here: https://github.com/lowRISC/riscv-llvm#how-can-i-build-upstream-llvmclang-and-use-it-to-cross-compile-for-a-riscv32-target
Finally i deal with that! i`m used next keys:
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE="Release" \
-DBUILD_SHARED_LIBS=True \
-DCMAKE_INSTALL_PREFIX="/home/username/llvm-install" \
-DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_BUILD_TESTS=False \
-DDEFAULT_SYSROOT="/home/username/esp-toolchain-install/riscv64-unknown-elf" \
-DGCC_INSTALL_PREFIX="/home/username/esp-toolchain-install" \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
-DLLVM_DEFAULT_TARGET_TRIPLE="riscv64-unknown-elf" \
-DLLVM_TARGETS_TO_BUILD="RISCV" ../llvm
and i copied content of esp-toolchain-install/* into llvm-install/*. And clang finally saw all of GCC files:
clang -v -print-search-dirs
clang version 12.0.1 (https://github.com/llvm/llvm-project.git fed41342a82f5a3a9201819a82bf7a48313e296b)
Target: riscv64-unknown-unknown-elf
Thread model: posix
InstalledDir: /home/username/llvm-install/bin
Found candidate GCC installation: /home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0
Selected GCC installation: /home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0
Candidate multilib: rv32i/ilp32;#march=rv32i#mabi=ilp32
Candidate multilib: rv32im/ilp32;#march=rv32im#mabi=ilp32
Candidate multilib: rv32iac/ilp32;#march=rv32iac#mabi=ilp32
Candidate multilib: rv32imac/ilp32;#march=rv32imac#mabi=ilp32
Candidate multilib: rv32imafc/ilp32f;#march=rv32imafc#mabi=ilp32f
Candidate multilib: rv64imac/lp64;#march=rv64imac#mabi=lp64
Candidate multilib: rv64imafdc/lp64d;#march=rv64imafdc#mabi=lp64d
Selected multilib: rv64imac/lp64;#march=rv64imac#mabi=lp64
programs: =/home/username/llvm-install/bin:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/bin:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/../../../../bin
libraries: =/home/username/llvm-install/lib/clang/12.0.1:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/rv64imac/lp64:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0/../../../../riscv64-unknown-elf/lib/rv64imac/lp64:/home/username/llvm-install/bin/../lib/gcc/riscv64-unknown-elf/9.2.0:/home/username/esp-toolchain-install/riscv64-unknown-elf/lib

LLVM IR to Executable Segfaults after Compilation

I'm currently in the throes of writing a compiler for a toy language; this is a new area for me. I'm using the LLVM C++ API to generate LLVM IR and from there, an object.
The issue comes (I think) with linking the object and being able to execute it.
I have main.ll comprised of the utter minimum IR I could come up with:
define void #main() {
ret void
}
This runs just fine with lli main.ll, i.e. it does nothing.
I compile it to object format with: llc --filetype=obj -o main.{o,ll}.
And link to no existing library with: ld.lld -o main{,.o}
However the resulting binary immediately segfaults. I took the advice of a few tutorials which led me to try to link via GCC and I was informed that "[Relocations] can not be used when making a PIE object" which Wikipedia tells me refers to position independence in the resulting binary.
So I recompiled to object with: llc --filetype=obj --relocation-model=pic main.{o,ll} and recompiled with GCC and it worked, running the output did nothing as expected.
But running the ld.lld command again and attempting to run that binary, again, immediately segfaults.
So, the first question I had was: what step am I missing between linked-object (assuming I'm linking correctly) and binary for this simple example?
Is there an ld flag I'm missing, some required library even if I'm not making use of any one in particular?
There are then more issues even with the GCC method when I try to link against libc to make use of printf in the IR but I think I need a better understanding of this simple example before attacking that.
Any help would be appreciated.
For anyone else that finds this and is trying to make a .ll file into an executable: I've found that the C runtime libraries were what was missing. These are included by default by both gcc and clang but the -v options didn't give me much to go on sadly...
Using the relocation model under LLVM of PIC_ and linking the resulting object dynamically with the C runtime libs, I've managed to get the .ll file to run regularly.
An example command (obviously OS specific) would be:
ld --verbose -L/usr/lib -lc \
-dynamic-linker \
/lib64/ld-linux-x86-64.so.2 \
/usr/lib/Scrt1.o \
/usr/lib/crti.o \
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/crtbeginS.o \
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/crtendS.o \
<object file> \
-o <binary> \
/usr/lib/crtn.o
I'm not 100% sure on the "why" of the matter aside of guessing, but this works and your standard ld -L... -lc <object file> does not.
If anyone can provide clarification, I will happily accept their answer.

Can we have a compiler running in embedded device

It may sound weird but I would like to know if we can have compiler in embedded device (lets say gcc support on imx6).
Of course, it is not uncommon to have target tools, but is is not trivial. A non-native (from the host perspective) compiler must be cross-compiled for the target architecture. You didn't provide any details, but maybe your build system can build target tools for you. Of course, you need much more than just a compiler. You probably need make, autotools, and probably more. It depends on what you are trying to compile on the target.
Your best bet would be to gain some proficiency using a cross-compiler environment. If you haven't already, you might check out the Yocto Project. It supports i.mx6 (and much more) and probably provides a path to get target tools on your board.
Good luck!
To arm arch, it will be easy to get target compiler, linaro ubuntu of linaro project will provide a completely solution for arm arch, it can provide GNOME desktop、toolchain and informative tools on your target.
You can get more info from the following link:
https://wiki.linaro.org/Platform/DevPlatform/Ubuntu
Yes that should easy enough.. What version of cross-compiler do you have in your machine, download the matching gcc compiler from here https://ftp.gnu.org/gnu/gcc/
Now what you want to do is cross-compile the GCC which you downloaded using the crosscompiler which you already have.
Following is an example of compiling 4.7.4, NOTE: replace the HOST and BUILD according to your platform:
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
../gcc-4.7.4/configure --build=$BUILD \
--host=$HOST \
--target=$HOST \
--prefix=/usr \
--disable-nls \
--enable-languages=c,c++ \
--with-float=hard
make -j $JOBS
make DESTDIR=<path_where_to_install> install

Resources