- How to work with external libraries when cross compiling?
- 5 Answers 5
- Cross-compiling tools package guidelines
- Important note
- Version compatibility
- Building a cross compiler
- Package naming
- File placement
- Example
- Hows and whys
- Why not installing into /opt
- What is that «out-of-path executables» thing?
- Troubleshooting
- What to do if compilation fails without clear message?
- What does this error [error message] means?
- Why do files get installed in wrong places?
- See also
- Кросс-компиляция под Linux
- Binutils
- GCC
- NewLib
- GDB
- Сборка Toolchain
- Порядок сборки Toolchain
How to work with external libraries when cross compiling?
I am writing some code for raspberry pi ARM target on x86 ubuntu machine. I am using the gcc-linaro-armhf toolchain. I am able to cross compile and run some independent programs on pi. Now, I want to link my code with external library such as ncurses. How can I achieve this. Should I just link my program with the existing ncurses lib on host machine and then run on ARM? (I don’t think this will work) Do I need to get source or prebuilt version of lib for arm, put it in my lib path and then compile? What is the best practice in this kind of situation? I also want to know how it works for the c stdlib. In my program I used the stdio functions and it worked after cross compiling without doing anything special. I just provided path for my arm gcc in makefile. So, I want to know, how it got correct std headers and libs?
5 Answers 5
Regarding your general questions:
The C library is part of your cross toolchain. That’s why the headers are found and the program correctly links and runs. This is also true for some other very basic system libraries like libm and libstdc++ (not in every case, depends on the toolchain configuration).
In general when dealing with cross-development you need some way to get your desired libraries cross-compiled. Using binaries in this case is very rare. That is, especially with ARM hardware, because there are so many different configurations and often everything is stripped down much in different ways. That’s why binaries are not very much binary compatible between different devices and Linux configurations.
If you’re running Ubuntu on the Raspberry Pi then there is a chance that you may find a suitable ncurses library on the internet or even in some Ubuntu apt repository. The typical way, however, will be to cross compile the library with the specific toolchain you have got.
In cases when a lot and complex libraries need to be cross-compiled there are solutions that make life a bit easier like buildroot or ptxdist. These programs build complete Linux kernels and root file systems for embedded devices.
In your case, however, as long as you only want ncurses you can compile the source code yourself. You just need to download the sources, run configure while specifying your toolchain using the —host option. The —prefix option will choose the installation directory. After running make and make install , considering everything went fine, you will have got a set of headers and the ARM-compiled library for your application to link against.
Regarding cross compilation you will surely find loads of information on the internet and maybe ncurses has got some pointers in its shipped documentation, too.
Cross-compiling tools package guidelines
This page describes how to create packages for cross-compiler toolchains. Another method to cross-compile makes use of distcc on mixed architectures. See Distcc#Cross compiling with distcc.
Tip: As alternative for creation of cross-compiler packages you could use crosstool-ng and create you own toolchain in fully automated way. crosstool-ng can be found on crosstool-ng .
Important note
This page describes the new way of doing things, inspired by the following packages:
- mingw-w64-gcc and other packages from mingw-w64-* series
- arm-none-eabi-gcc and other packages from arm-none-eabi-* series
- Other packages from arm-wince-cegcc-* series
Version compatibility
Warning: Using incompatible versions of packages for toolchain compilation leads to inevitable failures. By default consider all versions incompatible.
The following strategies allows you to select compatible versions of gcc, binutils, kernel and C library:
- General rules:
- there is a correlation between gcc and binutils releases, use simultaneously released versions;
- it is better to use latest kernel headers to compile libc but use —enable-kernel switch (specific to glibc, other C libraries may use different conventions) to enforce work on older kernels;
Building a cross compiler
The general approach to building a cross compiler is:
- binutils: Build a cross-binutils, which links and processes for the target architecture
- headers: Install a set of C library and kernel headers for the target architecture
- use linux-api-headers as reference and pass ARCH=target-architecture to make
- create libc headers package (process for Glibc is described here)
The source of the headers and libc will vary across platforms.
Tip: Exact procedure varies greatly, depending on your needs. For example, if you want to create a «clone» of an Arch Linux system with the same versions of kernel and glibc, you can skip building headers and pass —with-build-sysroot=/ to configure .
Package naming
The package name shall not be prefixed with the word cross- (it was previously proposed, but was not adopted in official packages, probably due to additional length of names), and shall consist of the package name, prefixed by GNU triplet without vendor field or with «unknown» in vendor field; example: arm-linux-gnueabihf-gcc . If shorter naming convention exists (e.g. mips-gcc ), it may be used, but this is not recommended.
File placement
Latest versions of gcc and binutils use non-conflicting paths for sysroot and libraries. Executables shall be placed into /usr/bin/ , to prevent conflicts here, prefix all of them with architecture name.
Typically, ./configure would have at least following parameters:
_target=your_target _sysroot=/usr/lib/$ . ./configure \ --prefix=$ \ --sysroot=$ \ --bindir=/usr/bin
where your_target can be, e.g., «i686-pc-mingw32».
Example
This is PKGBUILD for binutils for MinGW. Things worth noticing are:
- specifying root directory of the cross-environment
- usage of $ , $ and $ variables to make the code more readable
- removal of the duplicated/conflicting files
# Maintainer: Allan McRae # cross toolchain build order: binutils, headers, gcc (pass 1), w32api, mingwrt, gcc (pass 2) _target=i686-pc-mingw32 _sysroot=/usr/lib/$ pkgname=$=2.10.1' 'zlib') options=('!libtool' '!distcc' '!ccache') source=(http://ftp.gnu.org/gnu/$/$.tar.bz2) md5sums=('09a8c5821a2dfdbb20665bc0bd680791') build() < cd $/$ mkdir binutils-build && cd binutils-build ../configure --prefix=$ --bindir=/usr/bin \ --with-sysroot=$ \ --build=$CHOST --host=$CHOST --target=$ \ --with-gcc --with-gnu-as --with-gnu-ld \ --enable-shared --without-included-gettext \ --disable-nls --disable-debug --disable-win32-registry make make DESTDIR=$/ install # clean-up cross compiler root rm -r $/$/ >
Note: During cross-toolchain building always execute configure and make commands from dedicated directory (so-called out-of-tree compilation) and remove whole src directory after slightest change in PKGBUILD.
Hows and whys
Why not installing into /opt
- First, according to File Hierarchy Standard, these files just belong somewhere to /usr . Period.
- Second, installing into /opt is a last measure when there is no other option.
What is that «out-of-path executables» thing?
This weird thing allows easier cross-compiling. Sometimes, project Makefiles do not use CC & co. variables and instead use gcc directly. If you just want to try to cross-compile such project, editing the Makefile could be a very lengthy operation. However, changing the $PATH to use «our» executables first is a very quick solution. You would then run PATH=/usr/arch/bin/:$PATH make instead of make .
Troubleshooting
What to do if compilation fails without clear message?
For error, occurred during running configure , read $srcdir/pkgname-build/config.log . For error, occurred during compilation, scroll console log up or search for word «error».
What does this error [error message] means?
Most probably you made some of non-obvious errors:
- Too many or too few configuration flags. Try to use already proven set of flags.
- Dependencies are corrupted. For example misplaced or missing binutils files may result in cryptic error during gcc configuration.
- You did not add export CFLAGS=»» to your build() function (see bug 25672 in GCC Bugzilla).
- Some —prefix / —with-sysroot combination may require directories to be writable (non-obvious from clfs guides).
- sysroot does nor yet has kernel/libc headers.
- If google-fu does not help, immediately abandon current configuration and try more stable/proven one.
Why do files get installed in wrong places?
Various methods of running generic make install line results in different results. For example, some make targets may not provide DESTDIR support and instead require install_root usage. The same for tooldir , prefix and other similar arguments. Sometimes providing parameters as arguments instead of environment variables, e.g
and vice versa may result in different outcomes (often caused by recursive self-invocation of configure/make).
See also
Кросс-компиляция под Linux
Что же у нас есть для кросс-компиляции? Если не считать коммерческих продуктов и мелких поделок, то для того, чтобы скомпилировать любой проект под любую платформу, понадобится Gnu Compiler Collection, или, кратко, GCC. GCC — это один большой набор исходников, но собирать из него кросс-компилятор на каждую новую целевую платформу придётся отдельно.
Надо сказать, список целевых платформ довольно внушителен.
Вообще, для того, чтобы работать с GGC надо собрать т. н. Toolchain, набор утилит для компиляции. В toolchain входит помимно GCC, ещё Binutils, предназначенные для манипуляций с объектными и бинарными файлами. Для голого железа (если планируется работать не под ОС на целевой платформы, весьма полезной будет также NewLib — сборник стандартных процедур.
Binutils
GCC
В составе GCC большой набор разнообразных инструментов, однако, скорее всего иметь дело придётся с frontend, который так и называется, gcc. Он сам определяет тип исходного файла и вызывает соответствующий компилятор, а также, по необходимости, линковщик или библиотекарь.
NewLib
NewLib — специальная подборка стандартных функций для встраиваемых систем. Она включает в себя libc (функци работы со строками, файлами и т. д.), libm (разнообразные математические функции). Также она обладает широкими возможностями конфигурирования под разнообразные требования.
Надо сказать, NewLib далеко не единственный выбор. В принципе, если не пользоваться библиотечными функциями, можно вообще без библиотек обойтись, но этот путь сложен и тернист — стандарт си не требует наличия их в т. н. standalone environment 1) . Вполне возможно, есть другие подходящие варианты
GDB
GNU Debugger — стандартное средство отладки программ, и, в принципе, необязательно. Возможно, вы предпочтёте графический отладчик или вовсе пользуетесь исключительно printf-style-debug 2) .
Сборка Toolchain
Также стоит определить путь, куда будет всё установлено. В терминах GCC это называется prefix. По умолчанию этот путь — /usr/local . Однако по ряду различных причин иногда стоит специально указать другой. Первая причина — поставить в собственную домашнюю директорию, например, если нет root-полномочий на машине или просто его поставить только для себя (впрочем, лучше так не делать). Другая причина — бывает нужда с специальных вариантах сборки, и тогда это стоит делать, чтобы не спутать такую сборку с обычной. Стоит отметить, что компиляторы под различные платформы не перепутываются, так как имеют различные имена: gcc для ARM, например, будет именоваться arm-elf-gcc 3) или arm-linux-gcc , и именно его придётся указывать при компиляции (либо указывать target, тогда gcc сам вызовет нужный). Если же оставить путь по-умолчанию, сборка попадёт в стандартный путь поиска исполняемых файлов — /usr/local/bin , и может вызываться без специального указания пути или модификации $path .
Для указания prefix у configure есть соответствующая опция: — -prefix=…
Порядок сборки Toolchain
Сборка тулчейна в описанной конфигурации состоит из следующих этапов: