LLVM & Clang can't compile for a supported arch - c++

Under Ubuntu 64 bit I got
llc --version
LLVM (http://llvm.org/):
LLVM version 3.1
Optimized build with assertions.
Built Oct 15 2012 (18:15:59).
Default target: x86_64-pc-linux-gnu
Host CPU: btver1
Registered Targets:
arm - ARM
mips - Mips
mips64 - Mips64 [experimental]
mips64el - Mips64el [experimental]
mipsel - Mipsel
thumb - Thumb
x86 - 32-bit X86: Pentium-Pro and above
x86-64 - 64-bit X86: EM64T and AMD64
I can't do this
clang -march=arm -x c++ /tmp/cpp.cpp
error: unknown target CPU 'arm'
I'm missing something here ? Why I can't compile for ARM ?

-march is LLVM's internal tools command line option and is not connected with clang at all. If you need to compile for other target you need to specify the target triplet. This can be done in several ways (I do not remember offhand, whether they work with 3.1, but they definitely work with 3.2):
Make a link from clang to your-target-triple-clang, e.g. to
arm-none-linux-gnueabi-clang and compile everything via it
Provide -target option, e.g. clang -target arm-none-linux-gnueabi

To get a list of options of the clang compiler, use:
clang -cc1 -help
To specify the target, use -triple:
clang -cc1 -triple "arm-vendor-os" filename
where "vendor" and "os" should be replaced with the actual vendor and OS name. It can also be replaced with unknown.
-triple is a string of the form ARCHITECTURE-VENDOR-OS or ARCHITECTURE-VENDOR-OS-ENVIRONMENT. For example: x86_64-apple-darwin10

the llvm linker links for the host, which is only one of the targets, it wont link to every target in the list. it will definitely compile for any target. Basically clang goes from C/C++ to bytecode, then llc takes bytecode and makes assembly for the specific target (new experrimental option to take the bytecode straight to object file) then you need to get a cross assembler and a cross linker to take it the final mile (I use gnu binutils). Unfortunately I found that clang to bytecode is not completely generic (I had hoped and expected that it would be), it does in fact change the target independent output based on the target. The example below using the host triple instead of using -march allowed for my examples to build properly on more hosts.
ARMGNU?=arm-none-eabi
LOPS = -Wall -m32 -emit-llvm -ccc-host-triple $(ARMGNU)
OOPS = -std-compile-opts
LLCOPS = -march=thumb -mtriple=$(ARMGNU)
clang $(LOPS) -c blinker03.c -o blinker03.clang.bc
opt $(OOPS) blinker03.clang.bc -o blinker03.clang.thumb.opt.bc
llc $(LLCOPS) blinker03.clang.thumb.opt.bc -o blinker03.clang.thumb.opt.s
$(ARMGNU)-as blinker03.clang.thumb.opt.s -o blinker03.clang.thumb.opt.o
$(ARMGNU)-ld -o blinker03.clang.thumb.opt.elf -T memmap vectors.o blinker03.clang.thumb.opt.o
I have not, but before long will experiment with using the llc straight to object (actually I tried it on a simple test but have not used it on anything larger or posted it anywhere).

You're confusing your flags. clang's -march= wants a processor family. You probably meant to use clang -arch arm instead.

As this comment says this option it's not supported yet under linux, for now.

"-arch arm" is equivalent to "-arch armv4t" in clang. I suppose that a generic "arm" target is not allowed with "-march=", which should require something more precise, such as "armv6", "thumbv7", "armv4t", ...
Try selecting a specific subarch.

Starting Clang 11 (trunk), the list of supported target architectures could be handily printed using the newly added -print-targets flag.

Related

GCC 8 Cross Compiler outputs ARMv7 executable instead of ARMv6

I'm trying to compile a C++ application for a Raspberry Pi Zero using GCC 8.2.1.
I'm using this for a relatively large C++17 project that is being built using CMake, and I'm trying to cross-compile it on my x86-64 laptop.
Even with the simplest code possible, I'm not able to compile it for ARMv6:
int main() {}
$ arm-linux-gnueabihf-g++ test.cpp -static -march=armv6 -mfpu=vfp -mfloat-abi=hard
When running the file on the Pi, I get an Illegal instruction error, and readelf returns the following:
$ arm-linux-gnueabihf-readelf -A a.out
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "7-A"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Application
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv3
Tag_Advanced_SIMD_arch: NEONv1
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_rounding: Needed
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_VFP_args: VFP registers
Tag_CPU_unaligned_access: v6
GCC seems to ignore my architecture flags.
When simply compiling it into an object file, it seems to work just fine, but the linking stage always uses ARMv7:
$ arm-linux-gnueabihf-g++ test.cpp -static -march=armv6 -mfpu=vfp -mfloat-abi=hard -c
$ arm-linux-gnueabihf-readelf -A test.o
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "6"
Tag_CPU_arch: v6
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-1
Tag_FP_arch: VFPv2
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
Tag_ABI_VFP_args: VFP registers
Tag_ABI_optimization_goals: Aggressive Debug
Tag_CPU_unaligned_access: v6
What am I doing wrong?
I ended up compiling GCC from source, following this post. I didn't need all of the steps (I compiled everything using GCC 8 instead of compiling GCC 6.3 first, and I didn't edit any source files.)
I posted a Dockerfile with all build steps on GitHub.
The architecture of the executables produced is correct now, but I can't test it on target yet to check if it actually runs.
By default, newer GCC versions do not create correct binaries for ARMv6. Even though you pass the correct -mcpu= flag to gcc, it will create startup code for the newer ARMv7 architecture. Running them on your RasPI Zero will cause an "Illegal Instruction" exception.
this info is mentioned here https://github.com/Pro/raspi-toolchain

Error while installing "RcppArmadillo" package in R

I am using macOS High Sierra version 10.13.4. While installing "RcppArmadillo"package, I get the following two WARNING messages :
checking whether /usr/local/clang6/bin/clang++ -Wall accepts -g... (cached) yes
checking whether g++ version is sufficient... almost
configure: WARNING: Compiler self-identifies as being compliant with GNUC extensions but is not g++.
checking for macOS... found
checking for macOS Apple compiler... not found
checking for clang compiler... found
checking for OpenMP compatible version of clang... found and suitable
checking LAPACK_LIBS... R-supplied partial LAPACK found
configure: WARNING: Some complex-valued LAPACK functions may not be available
When I type "gcc --version" on my terminal, I get
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
And my Makevars file in R looks like:
FLIBS=-L/usr/local/gfortran/lib/gcc/x86_64-apple-darwin16/6.3.0 -L/usr/local/gfortran/lib -lgfortran -lquadmath -lm
F77 = /usr/local/bin/gfortran
FC = $F77
CXX = /usr/local/clang6/bin/clang++ -Wall
LDFLAGS=-L/usr/local/clang6/lib
CC= /usr/local/clang6/bin/clang
SHLIB_CXXLD=ccache /usr/local/clang6/bin/clang++
CXX11 = /usr/local/clang6/bin/clang++
CXX98 = /usr/local/clang6/bin/clang++
CXX14 = /usr/local/clang6/bin/clang++
How can I remove these two WARNING signs?
In short, these are warnings and not errors. Moreover, these warnings do not matter.
Let's talk about what each warning means...
First Warning
configure: WARNING: Compiler self-identifies as being compliant with GNUC extensions but is not g++.
This is stating that the compiler defined in the Makevars file's CXX variable is identifying as gcc but is not the gcc compiler. In essence, each compiler has its own predefined header, see Section 3.7.2 Common Predefined Macros of The C Preprocessor, and this check is focused on verifying that a modern gcc compiler is selected. However, it's hard to check the presence of a compiler if the compiler is lying about who it is.
For details on the origin, see discussion in the issue Add a check message success in config after g++version check #183 and the commit the default message on the g++ test).
Second Warning
configure: WARNING: Some complex-valued LAPACK functions may not be available
Within this warning, there is a complaint that the underlying Linear Algebra PACKage is the same one that is shipped with R. Unfortunately, the LAPACK that is shipped with R is severely limited and a bit out of date. So, the check here is hoping for an external LAPACK being present via either OpenBLAS, Intel MKL, or ATLAS. Due to the way this check is structured, unless you are compiling R from source -- that is you opt not to use the binary provided by CRAN -- there is no way to avoid the hiccup.
Simply put, the CRAN binary looks for the LAPACK in a specific location. Switching to another LAPACK would require the establishment of a symbolic link to the existing lRlapack location, which is what the check searches for. Though, it isn't advisable doing such a symbolic link. (Sorry vecLib lovers!)
If you are interested in compiling from source, consider viewing Section A.3 Linear algebra of R Installation and Administration, which describes the procedure for using external LAPACKs.

How to force clang use llvm assembler instead of system?

I'm working on LLVM/Clang fork (for AVR). How can i force Clang Driver to use LLVM assembler instead of system one?
MBA-Anton:bin asmirnov$ ./clang++
-I/Applications/avr.app/Contents/Resources/Java/hardware/avr/cores/avr -I/Applications/avr.app/Contents/Resources/Java/hardware/avr/variants/standard
/var/folders/64/fwfkm1k51zbd4_c5lwpsbljh0000gn/T/build5450310618632673119.tmp/Blink.cpp
-o /tmp/Blink.avr.hex -I /Applications/avr.app//Contents/Resources/Java/hardware/tools/avr/avr/include/
--target=avr -O1 -v
And it uses LLVM clang compiler (not system, correct):
clang version 3.6.0 (https://github.com/4ntoine/clang.git 0d08deedd548d964f63cf896ae9acb8d878a5fd8) (https://github.com/dylanmckay/avr-llvm.git 447b58bced825fa7bea31f3882f277535cc9fca6)
Target: avr
Thread model: posix
"/Users/asmirnov/Documents/dev/src/llvm_dylan/installed/bin/clang" -cc1 ...
But system assembler (incorrect):
"/usr/bin/as" -o ...
It should use LLVM's llvm-as as it "knows" AVR target (opcodes, etc). How can i force it use LLVM's assembler?
You can use clang to emit LLVM IR code by using the option -emit-llvm.
Let's say you want to compile a C file into LLVM IR:
clang -emit-llvm -c file.c
It will create a LLVM bytecode file file.bc. You will be able to compile the file with llc.

how to port c/c++ applications to legacy linux kernel versions

Ok, this is just a bit of a fun exercise, but it can't be too hard compiling programmes for some older linux systems, or can it?
I have access to a couple of ancient systems all running linux and maybe it'd be interesting to see how they perform under load. Say as an example we want to do some linear algebra using Eigen which is a nice header-only library. Any chance to compile it on the target system?
user#ancient:~ $ uname -a
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown
user#ancient:~ $ gcc --version
egcs-2.91.66
Maybe not... So let's compile it on a current system. Below are my attempts, mainly failed ones. Any more ideas very welcome.
Compile with -m32 -march=i386
user#ancient:~ $ ./a.out
BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed!
Compile with -m32 -march=i386 -static: Runs on all fairly recent kernel versions but fails if they are slightly older with the well known error message
user#ancient:~ $ ./a.out
FATAL: kernel too old
Segmentation fault
This is a glibc error which has a minimum kernel version it supports, e.g. kernel 2.6.4 on my system:
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, for GNU/Linux 2.6.4, not stripped
Compile glibc myself with support for the oldest kernel possible. This post describes it in more detail but essentially it goes like this
wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.bz2
tar -xjf glibc-2.14.tar.bz2
cd glibc-2.14
mkdir build; cd build
../configure --prefix=/usr/local/glibc_32 \
--enable-kernel=2.0.0 \
--with-cpu=i486 --host=i486-linux-gnu \
CC="gcc -m32 -march=i486" CXX="g++ -m32 -march=i486"
make -j 4
make intall
Not sure if the --with-cpu and --host options do anything, most important is to force the use of compiler flags -m32 -march=i486 for 32-bit builds (unfortunately -march=i386 bails out with errors after a while) and --enable-kernel=2.0.0 to make the library compatible with older kernels. Incidentially, during configure I got the warning
WARNING: minimum kernel version reset to 2.0.10
which is still acceptable, I suppose. For a list of things which change with different kernels see ./sysdeps/unix/sysv/linux/kernel-features.h.
Ok, so let's link against the newly compiled glibc library, slightly messy but here it goes:
$ export LIBC_PATH=/usr/local/glibc_32
$ export LIBC_FLAGS=-nostdlib -L${LIBC_PATH} \
${LIBC_PATH}/crt1.o ${LIBC_PATH}/crti.o \
-lm -lc -lgcc -lgcc_eh -lstdc++ -lc \
${LIBC_PATH}/crtn.o
$ g++ -m32 -static prog.o ${LIBC_FLAGS} -o prog
Since we're doing a static compile the link order is important and may well require some trial and error, but basically we learn from what options gcc gives to the linker:
$ g++ -m32 -static -Wl,-v file.o
Note, crtbeginT.o and crtend.o are also linked against which I didn't need for my programmes so I left them out. The output also includes a line like --start-group -lgcc -lgcc_eh -lc --end-group which indicates inter-dependence between the libraries, see this post. I just mentioned -lc twice in the gcc command line which also solves inter-dependence.
Right, the hard work has paid off and now I get
$ file ./prog
./prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, for GNU/Linux 2.0.10, not stripped
Brilliant I thought, now try it on the old system:
user#ancient:~ $ ./prog
set_thread_area failed when setting up thread-local storage
Segmentation fault
This, again, is a glibc error message from ./nptl/sysdeps/i386/tls.h. I fail to understand the details and give up.
Compile on the new system g++ -c -m32 -march=i386 and link on the old. Wow, that actually works for C and simple C++ programmes (not using C++ objects), at least for the few I've tested. This is not too surprising as all I need from libc is printf (and maybe some maths) of which the interface hasn't changed but the interface to libstdc++ is very different now.
Setup a virtual box with an old linux system and gcc version 2.95. Then compile gcc version 4.x.x ... sorry, but too lazy for that right now ...
???
Have found the reason for the error message:
user#ancient $ ./prog
set_thread_area failed when setting up thread-local storage
Segmentation fault
It's because glibc makes a system call to a function which is only available since kernel 2.4.20. In a way it can be seen as a bug of glibc as it wrongly claims to be compatible with kernel 2.0.10 when it requires at least kernel 2.4.20.
The details:
./glibc-2.14/nptl/sysdeps/i386/tls.h
[...]
/* Install the TLS. */ \
asm volatile (TLS_LOAD_EBX \
"int $0x80\n\t" \
TLS_LOAD_EBX \
: "=a" (_result), "=m" (_segdescr.desc.entry_number) \
: "0" (__NR_set_thread_area), \
TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \
[...]
_result == 0 ? NULL \
: "set_thread_area failed when setting up thread-local storage\n"; })
[...]
The main thing here is, it calls the assembly function int 0x80 which is a system call to the linux kernel which decides what to do based on the value of eax, which is set to
__NR_set_thread_area in this case and is defined in
$ grep __NR_set_thread_area /usr/src/linux-2.4.20/include/asm-i386/unistd.h
#define __NR_set_thread_area 243
but not in any earlier kernel versions.
So the good news is that point "3. Compiling glibc with --enable-kernel=2.0.0" will probably produce executables which run on all linux kernels >= 2.4.20.
The only chance to make this work with older kernels would be to disable tls (thread-local storage) but which is not possible with glibc 2.14, despite the fact it is offered as a configure option.
The reason you can't compile it on the original system likely has nothing to do with kernel version (it could, but 2.2 isn't generally old enough for that to be a stumbling block for most code). The problem is that the toolchain is ancient (at the very least, the compiler). However, nothing stops you from building a newer version of G++ with the egcs that is installed. You may also encounter problems with glibc once you've done that, but you should at least get that far.
What you should do will look something like this:
Build latest GCC with egcs
Rebuild latest GCC with the gcc you just built
Build latest binutils and ld with your new compiler
Now you have a well-built modern compiler and (most of a) toolchain with which to build your sample application. If luck is not on your side you may also need to build a newer version of glibc, but this is your problem - the toolchain - not the kernel.

Is it possible to build 32-bit applications on OSX 10.6 that run on other OSX 10.6 systems?

When building C++ projects using make on OSX 10.6, I have determined that the preprocessor definition __LP64__ seems to be always automatically set by the compiler (i.e., it is not defined in any header file) (see Where is __LP64__ defined for default builds of C++ applications on OSX 10.6?). This leads to the question: Is it even possible to build a 32-bit application on OSX 10.6 that targets (and runs) on another OSX 10.6 system?
I have heard that OSX 10.6 is always a 64-bit OS - that it's not even possible to run OSX 10.6 as a 32-bit operating system. If this is the case, it would make sense that it is impossible to build a 32-bit application on OSX 10.6 that will run on another OSX 10.6 system.
I need to know this so I can know whether I'm building a 64-bit application or not (I have been attempting to build my current project as a 32-bit application, since the corresponding Windows version is also being built as 32-bit - but perhaps I need to enable all 64-bit flags and build the OSX 10.6 version of this application as a full-fledged 64-bit application).
Yes, it is perfectly possible to do that. One limited demonstration:
$ tar -xf Packages/range-1.14.tgz
$ cd range-1.14
$ ls
COPYING Makefile README gpl-3.0.txt range.c range.mk stderr.c stderr.h
$ rmk CC='gcc -m32'
gcc -m32 -g -c stderr.c
gcc -m32 -g -c range.c
gcc -m32 -o range -g stderr.o range.o
$ file range
range: Mach-O executable i386
$ rmk -u CC='gcc -m64'
gcc -m64 -g -c stderr.c
gcc -m64 -g -c range.c
gcc -m64 -o range -g stderr.o range.o
$ file range
range: Mach-O 64-bit executable x86_64
$
rmk -u is equivalent to (GNU) make -B. This GCC is my home-built 4.6.0. You can do more with the Apple-provided versions of GCC - like cross-compiling and/or universal builds.
Mac OS X 10.6 runs perfectly well on 32-bit Intel Macs. It dropped support for PowerPC. Future versions of Mac OS X (cough cough NDA cough) may or may not drop support for 32-bit Intel Macs, requiring a 64-bit system.
Even a 64-bit Mac, however, has implicit support for running 32-bit processes, and GCC can cross-compile for i386 targets (or PPC/PPC64/ARMv6/ARMv7 targets.) You must make sure the desired architectures are specified in your build flags however, or it will default to the native architecture (i.e. x86_64.)
If you use the xcodebuild command-line utility and pass it the path to an Xcode project bundle, it will automatically use the build settings in the project when calling on GCC. There's rarely a need to use GCC directly on Mac OS X unless you're compiling from generic *NIX sources.
If you tell us why you're using make on Mac OS X, we may be able to give you more specific advice, but the preferred command-line compilation method on Mac OS X is still xcodebuild.