ARM toolchain build - linux

I am building an ARM cross toolchain with GCC 4.6.3 using the sysroot approach. If I follow the LFS instructions and copy the gmp, mpfr and mpc source folders to the GCC source folder, the build will fail as mpc cannot locate mpfr even though the paths are correct.
The GCC build will complete without any errors when compiling gmp, mpfr and mpc manually as statically linked.
Now my question is if I should install gmp, mpfr and mpc to a random place in the toolchain build directory that gets deleted when the toolchain is finished, so they just are available for the different stages of GCC build or should I point the prefix at $SYSROOT so they become a permanent part of the toolchain? What is the most correct ting to do?

I take a different approach with cross-compiler infrastructure. I have a directory: $HOME/local, with all the expected subdirs: bin/, lib/, include/, etc. $HOME/local/bin is (first) in my $PATH, and $HOME/local/lib in $LD_LIBRARY_PATH (or $DYLD_LIBRARY_PATH on Darwin).
I then build and install gmp, mpfr, mpc, in --prefix=$HOME/local, with:
> ./configure --prefix=$HOME/local --enable-cxx [--disable-fft]
> ./configure --prefix=$HOME/local --with-gmp=$HOME/local
> ./configure --prefix=$HOME/local --with-mpfr=$HOME/local --with-gmp=$HOME/local
I can use fast, platform dependent flags for these packages, which generally don't work for gcc with a cross --target triple:
> env CFLAGS="-pipe -Wall -O2 -march=core2" CXXFLAGS="..." ./configure ...
The advantage is, wherever I build the cross compiler infrastructure, the gmp, mpfr, mpc libraries, includes, etc., are accessible - and the same libs can be used for more than one cross-compiler. i.e., I've got 4.6.x AVR, freestanding x86_64-pc-elf, ARM EABI. Each using the gcc configure options:
> --with-mpc=$HOME/local --with-mpfr=$HOME/local --with-gmp=$HOME/local
Obviously, when I fsck up a tool-chain build (I often do), at least I don't have to repeat this part of build.

Building a cross compiler is a tedious task. Why not use crosstool-NG to automate all the steps required to build a cross compiler?

Related

How do I specify the compiler to use when cross-compiling rustc?

When I compile rustc, there is a option in the configure script to specify other targets to the core libraries (libcore, libstd, etc), so for example:
./configure --target=x86_64-unknown-linux-gnu,i686-unknown-linux-gnu
will compile and install the rustlibs for both these architectures.
My problem is that this command will use my default gcc to compile everything, (since my system is multilib, it will successfully compile to i686 too), but what I want is to use my toolchain compiler instead, so for example:
I have 2 toolchains in my amd64 system: i686-unknown-linux-gnu and arm-unknown-linux-gnueabi.
When I run configure with these parameters:
./configure --target=x86_64-unknown-linux-gnu,i686-unknown-linux-gnu,arm-unknown-linux-gnueabi
When compiling the rustlibs, I want the script to use x86_64-unknown-linux-gnu-gcc for x86_64, and i686-unknown-linux-gnu-gcc for i686 and arm-unknown-linux-gnueabi-gcc for arm.
That way the rustlib will be compiled using the glibc and other libraries from the toolchain and not the default from my system. Is that possible?
It's specified using suffixed environment variables: see here for what they do in CI.

Header files are not found by GCC

Working with embedded C-projects. There are libraries, include files and so on - for micro controllers. No need for me to use GCC for a host machine and OS (Linux Mint 64 bit). As a rule...
But now I'm trying to compile mspdebug project from a Github - with a GCC of course. And I get an error at the very begin of make:
mspdebug$ make
cc -DUSE_READLINE -O1 -Wall -Wno-char-subscripts -ggdb -I. -Isimio -Iformats -Itransport -Idrivers -Iutil -Iui -DLIB_DIR=\"/usr/local/lib/\" -o util/btree.o -c util/btree.c
util/btree.c:19:20: fatal error: assert.h: No such file or directory
#include <assert.h>
^
compilation terminated.
I search for the includes in all possible paths (I've got the list of them via gcc -v command) - there are no assert.h file, as well, as stdio.h and so on. Except virtual box directories there is only one place (where GCC does not search includes): /usr/lib/syslinux/com32/include
AFAIK, all standard libs and includes are installed with the GCC. So I try to reinstall GCC (4.8.4) - nothing changes.
What is the normal way to give GCC all standard environment it needs?
Thanks to the right direction set by Sam Varshavchik I found the info in the stackoverflow. So I did the following:
1) installed build-essential:
sudo apt-get install build-essential
2) installed libusb (since my try to build the package revealed the absence of usb.h):
sudo apt-get install libusb-dev
And it is OK! The mspdebug (v.023) is compiled and successfully tested!
So, Linux Mint 17.2 (at least) requires installing some libs to a GCC, the most basic is build-essential.
assert.h is not part of gcc, it's a part of glibc.
Most likely, your Linux distribution puts the system headers into a separate package that you need to install.
Fedora, for examples, puts the header files in the glibc-headers package. However, you can't be using Fedora, because Fedora's gcc package has a dependency on glibc-headers, to make sure that it gets pulled in.
Whatever Linux distribution you're using, you need to research which distribution package will install the system header files you need to build stuff with.

Cross compiling libSDL

I'm trying to cross-compile libSDL version 1.2 for a custom made, debian based Linux system. The toolchain I'm using is already configured properly so that I just run gcc/g++ on my the desired code and the resulting output is compatible with the target machine.
When I run ./configure --help in the libSDL source directory, I see that I can basically just set some environment variables to point to my cross-compiler.
However, I also see the following options:
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
I looked into the configure.in, build-scripts/config.sub, and build-scripts/config.guess files but couldn't really figure out how it works.
Are these options required? If not, is it a good idea to use them?
With autotools, --build is what you are building on and --host is what you want it to run on (there's also --target, but that's only important if what you're compiling is itself a compiler). Autotools will generally figure out --build on their own, so don't specify it if you don't have to (but look in /usr/lib/gcc to see what your compiler probably thinks --build should be)
So, eg, if you're building for i686 on x86_64, do
./configure --host=i686-linux-gnu
(And use the -m32 options in CFLAGS, etc., but it sounds like you already have that ready.)
Whereas if you're building for x86_64 on i686, do
./configure --host=x86_64-linux-gnu
(You can build for all kinds of crazy hosts: rs6000-ibm-aix, sparc-sun-solaris, mips-idt-ecoff, etc..., assuming you have the appropriate gcc cross-compilers installed...)
GNU's page on it is here:
http://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html

How to deploy a portable gcc with cloog?

I'm trying to build a portable version of gcc 4.8.2. (for only C/C++ languages) The end result is have gcc installed into a specific application directory, eg, /opt/gcc-4.8.2 so that I can copy that directory from one computer to another (all computers are either intel corei5 or corei7, running recent Linux versions, eg, Ubuntu 12, Suse 10/11, Centos 5 & 6).
So far I'm able to build gcc ok, using --prefix to have the gcc outputs placed in a single directory (which can then be later copied to the other hosts). I configured & built gcc's dependencies (gmp, mpfr, mpc, isl) to have --disable-shared, so I can be sure that the final gcc, when copied to other hosts, won't complain about missing libraries or symbols.
I have a question with cloog. I configured gcc with --with-cloog (to pick up my locally built cloog, which I built along with the other gcc dependencies). However, what I don't know, is whether I also need to copy the cloog libraries and binary to each host I copy gcc to?
Also, how can I test gcc & cloog interaction? Is there a simple C file example and/or gcc command line that can be used to test whether gcc is successfully making use of cloog?
Additionally, are there any other considerations when trying to build a gcc which I then want to run on other hosts?
It depends if cloog is installed as a shared library libcloog-isl.so.* or as a static one libcloog.a ; use
ldd $(gcc-4.8 -print-file-name=cc1)
to find out. Of course you need to install all the shared libraries dependencies. If libcloog*so appears in the output of above ldd command, it is a shared library. Otherwise a static one.
You could set the LD_LIBRARY_PATH, or add the directory containing libcloog-isl.so.* (e.g. /usr/local/lib/ or /opt/lib/ etc...) to /etc/ld.so.conf (then run ldconfig)
I am not entirely sure your gcc build can run on every platform you mentioned. There might be libc* dependencies. See this. And perhaps also binutils dependencies (notably for gcc-4.8 -flto compilations).
To test gcc just compile with optimizations (e.g. gcc-4.8 -Wall -O3) some non-trivial file.

How to cross compile for linux x86 with linux amd64, cmake and g++?

+1 for each piece of information that helps to complete the whole picture. You don't need to know the whole answer. I'll appreciate individual pieces of the puzzle just as much. Thanks.
I am about to attempt my first cross-compilation. I have searched both SO and the web and found many pieces of information, but I don't always know how to put those pieces together because there are still some missing pieces.
My host: linux Kubuntu amd64.
Target: linux kubuntu x86 (32bit) (should be easy, no?)
Tools: g++ and cmake.
Here is the information I found:
How to compile a 32-bit binary on a 64-bit linux machine with gcc/cmake
mentions export CFLAGS=-m32. That's one piece.
Cross-platform: selecting data types to use 32/64 bit
mentions data types. I may have to pay attention to that within my code.
#ifdef for 32-bit platform
#ifdef for 32-bit platform
links to the following, although I am not too sure yet how to use it:
http://predef.sourceforge.net/prearch.html
http://ww.ubuntuforums.org/showthread.php?t=1377396
I did: sudo apt-get install g++-multilib
missing pieces:
Ideally, when I do 'make' (with cmake), it should spit out both a amd64 binary and a x86 one.
Part of my CMakeLists.txt looks like this:
add_definitions(-Wall -pthread)
add_executable (../run.amd64 user.cpp time.cpp init.cpp utils.cpp main.cpp)
target_link_libraries(../run.amd64 cppcms dbixx config++ ctemplate)
How do I introduce the flag -m32 to create a second executable?
Should I want to make only one executable (e.g. for testing and debugging), how do I tell cmake to make either one or both binaries?
Also, you can see that I use some third party libraries, some of which I had to compile myself. Does this mean that I need to compile each of those binaries for the target host as well? Some use cmake and some use: ./configure; make;
How would I do about compiling those libraries for the target host (flags to use, etc.)?
Note: the dynamically linked libraries are already compiled and installed on the target computer, so maybe I don't need to worry about this step... I am not sure: this is one of my missing pieces...
What I need is a kind of tutorial, or at least some of the missing pieces. I'll update this post with more details on what I achieved and how.
Thanks.
P.S.
Is it possible at all?
Searching more, I found this:
http://www.mail-archive.com/cmake#cmake.org/msg26265.html
"The original design doesn't seem to be designed for anything more than windows-linux or linux-windows cross compiles."
cmake is NOT tested for linux amd64 to linux x86.
http://www.cmake.org/Wiki/CMake_Cross_Compiling#FAQ.2FPotential_Problems
"On mixed 32/64 bit Linux installations cross compilation cannot be used to build for 32/64 bit only."
??
If you want to use a toolchain file there is an easier solution (IMHO) than what is proposed by #auledoom. You do not need to write the shell wrapper scripts at all, simply put this in the toolchain file:
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# Which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc -m32)
set(CMAKE_CXX_COMPILER g++ -m32)
This will make it a "list variable" in cmake. This solution works for me. Benefit of the toolchain file is that you can there also define paths for 32bit libraries etc, which is usually different from standard paths.
This solution will allow you cross-compile your cmake project on a linux64 host targeting 32bits, on systems with multi-arch support.
It's uses a "fake" cmake toolchain so CMAKE somehow "believes" it's on 32bit system, so no additional modifications are needed inside your cmake project files, no special configurations, no special settings (well almost).
Install multilib support:
$sudo apt-get install gcc-multilib
Create a "fake" linux32 toolchain
First, we create a "fake" i686 compiler. Go where your CMakeLists.txt resides and create a bin directory. Open your preferred editor and create this simple bash script for gcc compiler.
#!/bin/sh
/usr/bin/gcc -m32 "$#"
As you see, it's just make a call to the system compiler adding the -m flag. Save this as i686-linux-gnu-gcc. Do the same for the g++ compiler
#!/bin/sh
/usr/bin/g++ -m32 "$#"
Save it as i686-linux-gnu-g++. Remember to set the executable flags on this scrips
Create also a symlink to the system ar binary in this form
$ln /usr/bin/ar i686-linux-gnu-ar
At last create the toolchain-linux32.cmake file
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# Which compilers to use for C and C++
set(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-g++)
and create the build directory and call cmake with the toolchain file as argument
$mkdir build && cd build
$cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-linux32.cmake ..
and your done!!!!!
I'll write a more complete guide here, which covers some problems i have with libraries not multi-lib compliant
this is a simplified version of what I use, and it does create x86 binaries:
set( TargetName myExe )
set( SOURCES a.cpp b.cpp )
add_executable( ${TargetName} ${SOURCES} )
target_link_libraries( ${TargetName} m pthread stdc++ )
set_target_properties( ${TargetName} PROPERTIES COMPILE_FLAGS -m32 LINK_FLAGS -m32 )
furthermore you'll use add_definitions to set compiler flags like -W -Ox -Dxxx etc.
All the lines above are actually split in seperate cmake files, and to get one file to build a number of executables, I generate a master cmake file containing all different configurations I want to build:
project( myProject )
set( SOURCES a.cpp b.cpp )
if( ${ConfigurationType} strequal "Debugx86" )
include( debugopts.cmake )
include( x86.cmake )
include( executable.cmake )
...
elseif( ${ConfigurationType} strequal "Releasex64" )
include( debugopts.cmake )
include( x86.cmake )
include( executable.cmake )
...
etc
Then there's a driver shell script to build it all. It takes commandline options to set some extra options and select to build everything or just one configuration. Here's a piece of it:
if [ "$myConfig" = "all" -o "$myConfig" = "Debugx86" ]; then
mkdir -p project_Debugx86
cd project_Debugx86
cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Debugx86"
make clean
make "$makeopts"
fi
if [ "$myConfig" = "all" -o "$myConfig" = "Releasex64" ]; then
mkdir -p project_Releasex64
cd project_Releasex64
cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Releasex64
make clean
make "$makeopts"
fi
While this is not exactly what you ask for, it works flawlessly and does the same. (Not sure if it is possible in cmake to define any number of targets in cmake itself, and have them built all together by one file.) It just takes some time to write the generator for this files, but once that is done all I have to do is point the generator to a directory with sources, let ir run, then invoke the build script to make everything.
All you need is to add -m32 to CFLAGS and CXXFLAGS when running CMake. This can be done via environment variables:
$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .
or by setting corresponding CMake variables:
$ cmake -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 .
This can easily tested with a simple CMake project:
$ uname -m
x86_64
$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
....
$ make
Scanning dependencies of target foo
[100%] Building CXX object CMakeFiles/foo.dir/foo.cc.o
Linking CXX executable foo
[100%] Built target foo
$ file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x5b1871446c92cbdcbf905583e16189f68f3bf5f2, not stripped
where CMakeLists.txt is a trivial CMake file:
project(TEST)
add_executable(foo foo.cc)
and foo.cc is as follows:
int main () {}
Here is the basic recipe I use all the time for cmake projects..
OPTION(FORCE32 "Force a 32bit compile on 64bit" OFF)
IF(FORCE32)
if(APPLE)
SET(CMAKE_OSX_ARCHITECTURES "i386")
else()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
endif()
ENDIF()
IF(APPLE)
set(BIN_LIBROOT "macosx")
ELSE()
if(CMAKE_SIZEOF_VOID_P MATCHES "8" AND NOT(FORCE32) )
set(BIN_LIBROOT "linux64")
set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86_64")
set(BIN_RPATH "\$ORIGIN/lib64")
else()
set(BIN_LIBROOT "linux")
set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86")
set(BIN_RPATH "\$ORIGIN/lib")
endif()
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH ${BIN_RPATH})
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
ENDIF()
Then every target automatically has the .bin.${arch} extension and I never have to think about this for any targets I add. the ${BIN_LIBROOT} is useful if you have a bunch of precompiled libraries as you as you can use that to dynamically search for libs in your private lib dirs based on the target platform/arch.

Resources