Building a toolchain with cmake to cross-compile for android - android-ndk

gcc (GCC) 4.8.1
android-ndk-r9
Hello,
My host machine is Fedora 19 and I want to create a tool-chain for compiling programs to run on android, later I want to extend this for iOS.
I get the following error:
Check for working C compiler: /opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -- broken
I am not sure why I am getting this error, as everything has been installed. I have also installed binutils-arm-linux-gnu. However, this is my first time do this type of thing, so many I have got something mixed up.
I am trying to create a toolchain file using cmake to croos-compile to run libraries on an android device.
I have installed the android-ndk-r9 in the following location with the path to the compiler:
/opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin
arm-linux-androideabi-addr2line
arm-linux-androideabi-ar
arm-linux-androideabi-as
arm-linux-androideabi-c++
arm-linux-androideabi-c++filt
arm-linux-androideabi-cpp
arm-linux-androideabi-elfedit
arm-linux-androideabi-g++
arm-linux-androideabi-gcc
arm-linux-androideabi-gcc-4.8
arm-linux-androideabi-gcc-ar
arm-linux-androideabi-gcc-nm
arm-linux-androideabi-gcc-ranlib
arm-linux-androideabi-gcov
arm-linux-androideabi-gdb
arm-linux-androideabi-gprof
arm-linux-androideabi-ld
arm-linux-androideabi-ld.bfd
arm-linux-androideabi-ld.gold
arm-linux-androideabi-ld.mcld
arm-linux-androideabi-nm
arm-linux-androideabi-objcopy
arm-linux-androideabi-objdump
arm-linux-androideabi-ranlib
arm-linux-androideabi-readelf
arm-linux-androideabi-run
arm-linux-androideabi-size
arm-linux-androideabi-strings
arm-linux-androideabi-strip
My cross-compile file is:
include(CMakeForceCompiler)
set(toolchain_path /opt/ndk/toolchains)
# Target system
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSTEM_VERSION 1)
# Compiler to build for the target
set(CMAKE_C_COMPILER /opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc)
set(CMAKE_FIND_ROOT_PATH /opt/ndk/toolchains)
I run this from my build/debug directory with my toolchain being in the root directory.
[ant#localhost debug]$ cmake -DCMAKE_TOOLCHAIN_FILE=arm-eabi-gcc.cmake ../..
Output
-- The C compiler identification is GNU 4.8.0
-- Check for working C compiler: /opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
-- Check for working C compiler: /opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc -- broken
CMake Error at /usr/share/cmake/Modules/CMakeTestCCompiler.cmake:61 (message):
The C compiler
"/opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /home/steve/mobile_progs/linux_pjsip/build/debug/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/gmake "cmTryCompileExec379796592/fast"
/usr/bin/gmake -f CMakeFiles/cmTryCompileExec379796592.dir/build.make
CMakeFiles/cmTryCompileExec379796592.dir/build
gmake[1]: Entering directory
`/home/steve/mobile_progs/linux_pjsip/build/debug/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report
/home/steve/mobile_progs/linux_pjsip/build/debug/CMakeFiles/CMakeTmp/CMakeFiles
1
Building C object
CMakeFiles/cmTryCompileExec379796592.dir/testCCompiler.c.o
/opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
-o CMakeFiles/cmTryCompileExec379796592.dir/testCCompiler.c.o -c
/home/steve/mobile_progs/linux_pjsip/build/debug/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec379796592
/usr/bin/cmake -E cmake_link_script
CMakeFiles/cmTryCompileExec379796592.dir/link.txt --verbose=1
/opt/ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
CMakeFiles/cmTryCompileExec379796592.dir/testCCompiler.c.o -o
cmTryCompileExec379796592 -rdynamic
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld:
error: cannot open crtbegin_dynamic.o: No such file or directory
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld:
error: cannot open crtend_android.o: No such file or directory
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld:
error: cannot find -lc
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld:
error: cannot find -ldl
collect2: error: ld returned 1 exit status
gmake[1]: *** [cmTryCompileExec379796592] Error 1
gmake[1]: Leaving directory
`/home/steve/mobile_progs/linux_pjsip/build/debug/CMakeFiles/CMakeTmp'
gmake: *** [cmTryCompileExec379796592/fast] Error 2
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:4 (project)
Many thanks in advance,

I managed to solve the problem by first going to this website:
http://developer.android.com/tools/sdk/ndk/index.html
There is an example of using the standalone toolchain that comes with NDK.
make-standalone-toolchain.sh --toolchain=arm-linux-androideabi-4.8
Extracted the into my /opt directory.
And using this sample toolchain cmake file
# Target system
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 1)
# Compiler to build for the target
set(CMAKE_C_COMPILER /opt/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-gcc)
set(CMAKE_CXX_COMPILER /opt/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-g++)
Everything just worked after that. However, I couldn't get my previous problem working. Maybe I have set some environmental variables incorrectly to the wrong paths.
Hope this helps someone else.

Why you don't try this android-cmake. I still use this script and it works fairly well. If that approach does not fit your needs, you could use it as an inspiration anyway :-) .

For original problem from ant2009, please have a try to add following lines in .cmake:
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=/opt/ndk/platforms/android-23/arch-arm" CACHE STRING "" FORCE)
SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=/opt/ndk/platforms/android-23/arch-arm" CACHE STRING "" FORCE)

In 2020 the make-standalone-toolchain.sh approach is deprecated.
This is an updated CMakeList.txt:
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 24)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
PROJECT(mylib C)
CMAKE_MINIMUM_REQUIRED(VERSION 3.18.0)
SET( ${PROJECT_NAME}_CURRENT 1 )
SET( ${PROJECT_NAME}_REVISION 0 )
SET( ${PROJECT_NAME}_AGE 0 )
SET(VERSION "${${PROJECT_NAME}_CURRENT}.${${PROJECT_NAME}_REVISION}.${${PROJECT_NAME}_AGE}")
SET(SOURCES foobar.c)
ADD_LIBRARY(mylib SHARED ${SOURCES})
NOTE: For the ABI arm64-v8a CMake 3.18 is needed to detect the NDK toolchain correctly, 3.10 which is the version in Ubuntu 18.04, does not find the toolchain.

Related

Buildroot: `CMake Error at FindPackageHandleStandardArgs.cmake:230 (message): Could NOT find Boost (missing: thread) (found version "1.80.0")`

Buildroot: CMake Error at /home/gabriel/repos/my_repo/output/board/host/share/cmake-3.25/Modules/FindPackageHandleStandardArgs.cmake:230 (message): Could NOT find Boost (missing: thread) (found version "1.80.0")
I'm trying to build a host-ros-cpp-common package in Buildroot for an embedded Linux board, containing the contents of this folder here: https://github.com/ros/roscpp_core/tree/noetic-devel/cpp_common
I'm building that folder above at version tag 0.5.8, actually: https://github.com/ros/roscpp_core/tree/0.5.8/cpp_common
I'm building on Ubuntu 22.04 with gcc-11, migrating from Ubuntu 18.04 with gcc-8. Any idea how to solve this error? Also, what does (missing: thread) mean?:
CMake Error at /home/gabriel/repos/my_repo/output/board/host/share/cmake-3.25/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find Boost (missing: thread) (found version "1.80.0")
Here is the larger context:
$ make
...[stuff removed]...
>>> host-ros-cpp-common 0.5.8 Configuring
(mkdir -p /home/gabriel/repos/my_repo/output/board/build/host-ros-cpp-common-0.5.8/cpp_common && cd /home/gabriel/repos/my_repo/output/board/build/host-ros-cpp-common-0.5.8/cpp_common && rm -f CMakeCache.txt && PATH="/home/gabriel/repos/my_repo/output/board/host/bin:/home/gabriel/repos/my_repo/output/board/host/sbin:/home/gabriel/Downloads/Install_Files/gcloud/google-cloud-sdk/bin:/home/gabriel/.local/bin:/home/gabriel/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin:/usr/local/go/bin" PKG_CONFIG="/home/gabriel/repos/my_repo/output/board/host/bin/pkg-config" PKG_CONFIG_SYSROOT_DIR="/" PKG_CONFIG_LIBDIR="/home/gabriel/repos/my_repo/output/board/host/lib/pkgconfig:/home/gabriel/repos/my_repo/output/board/host/share/pkgconfig" PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 /home/gabriel/repos/my_repo/output/board/host/bin/cmake /home/gabriel/repos/my_repo/output/board/build/host-ros-cpp-common-0.5.8/cpp_common -DCMAKE_INSTALL_SO_NO_EXE=0 -DCMAKE_FIND_ROOT_PATH="/home/gabriel/repos/my_repo/output/board/host" -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM="BOTH" -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY="BOTH" -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE="BOTH" -DCMAKE_INSTALL_PREFIX="/home/gabriel/repos/my_repo/output/board/host" -DCMAKE_C_FLAGS="-O2 -I/home/gabriel/repos/my_repo/output/board/host/include" -DCMAKE_CXX_FLAGS="-O2 -I/home/gabriel/repos/my_repo/output/board/host/include" -DCMAKE_EXE_LINKER_FLAGS="-L/home/gabriel/repos/my_repo/output/board/host/lib -Wl,-rpath,/home/gabriel/repos/my_repo/output/board/host/lib" -DCMAKE_SHARED_LINKER_FLAGS="-L/home/gabriel/repos/my_repo/output/board/host/lib -Wl,-rpath,/home/gabriel/repos/my_repo/output/board/host/lib" -DCMAKE_ASM_COMPILER="/usr/bin/as" -DCMAKE_C_COMPILER="/home/gabriel/repos/my_repo/output/board/host/bin/ccache" -DCMAKE_CXX_COMPILER="/home/gabriel/repos/my_repo/output/board/host/bin/ccache" -DCMAKE_C_COMPILER_ARG1="/usr/bin/gcc" -DCMAKE_CXX_COMPILER_ARG1="/usr/bin/g++" -DCMAKE_COLOR_MAKEFILE=OFF -DBUILD_DOC=OFF -DBUILD_DOCS=OFF -DBUILD_EXAMPLE=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TEST=OFF -DBUILD_TESTS=OFF -DBUILD_TESTING=OFF -DCMAKE_PREFIX_PATH="/home/gabriel/repos/my_repo/output/board/host//opt/ros/indigo/;/home/gabriel/repos/my_repo/output/board/host/usr" -DCMAKE_INSTALL_PREFIX="/home/gabriel/repos/my_repo/output/board/host//opt/ros/indigo/" )
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
Compatibility with CMake < 2.8.12 will be removed from a future version of
CMake.
Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions.
-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /home/gabriel/repos/my_repo/output/board/host/bin/ccache - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /home/gabriel/repos/my_repo/output/board/host/bin/ccache - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
CMake Error at /home/gabriel/repos/my_repo/output/board/host/share/cmake-3.25/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find Boost (missing: thread) (found version "1.80.0")
Call Stack (most recent call first):
/home/gabriel/repos/my_repo/output/board/host/share/cmake-3.25/Modules/FindPackageHandleStandardArgs.cmake:600 (_FPHSA_FAILURE_MESSAGE)
/home/gabriel/repos/my_repo/output/board/host/share/cmake-3.25/Modules/FindBoost.cmake:2376 (find_package_handle_standard_args)
CMakeLists.txt:4 (find_package)
-- Configuring incomplete, errors occurred!
See also "/home/gabriel/repos/my_repo/output/board/build/host-ros-cpp-common-0.5.8/cpp_common/CMakeFiles/CMakeOutput.log".
make[2]: *** [package/pkg-generic.mk:259: /home/gabriel/repos/my_repo/output/board/build/host-ros-cpp-common-0.5.8/.stamp_configured] Error 1
make[1]: *** [Makefile:84: _all] Error 2
make[1]: Leaving directory '/home/gabriel/repos/my_repo/buildroot'
make: *** [Makefile:209: /home/gabriel/repos/my_repo/output/board/images/image.swu] Error 2
I recently upgraded the Boost package to the latest from Buildroot, here: https://github.com/buildroot/buildroot/tree/master/package/boost, because boost itself was failing to build on my new build system of gcc-11 and Ubuntu 22.04 prior to doing that.
I also opened an issue about this here: https://github.com/ros/roscpp_core/issues/134
And I left a comment here: https://github.com/ethz-asl/kalibr/issues/566#issuecomment-1376788400
My research attempts:
Google search for Could NOT find Boost (missing: thread) (found version "1.80.0")
Update: I think the problem has something to do with this CMake line, but I don't know CMake: https://github.com/ros/roscpp_core/blob/0.5.8/cpp_common/CMakeLists.txt#L4:
find_package(Boost REQUIRED COMPONENTS system thread)
After 1 hr of research and trial and error...
My host is the build machine, which is Ubuntu 22.04. It is building stuff for my host (host-ros-cpp-common), and therefore needs the Boost libs for my host. So, the buildroot target (for the embedded Linux ARM-core device) boost package I just upgraded has nothing to do with my host I think! It's for the target. So, the solution appears to be to simply install libboost-thread-dev onto Ubuntu 22.04, which is my host. The package libboost-all-dev, contains libboost-thread-dev plus more, so just install that instead:
sudo apt update
sudo apt install libboost-all-dev
Now make gets past that previous error and onto the next one!
That must be it!
Credit: I had a conversation with ChatGPT to stumble upon this information. I tested the commands above myself. All words here are my own.

aarch64 cross compile linker cannot find a library

Can someone give me a hint why the linker did not find a library which exists in /usr/local/lib.
I try to cross compile an proprietary sw for a rasberrypi(aarch64) on Windows WSL2 (Ubuntu 20.04).
So I use this tutorial.
My toolchain file is:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_CROSSCOMPILING TRUE)
# Name of C compiler.
# /opt/cross-pi-gcc-10.2.0-64/bin
set(CMAKE_C_COMPILER "/opt/cross-pi-gcc-10.2.0-64/bin/aarch64-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "/opt/cross-pi-gcc-10.2.0-64/bin/aarch64-linux-gnu-g++")
# Where to look for the target environment.
set(CMAKE_FIND_ROOT_PATH /opt/cross-pi-gcc-10.2.0-64/aarch64-linux-gnu)
set(CMAKE_INCLUDE_PATH /opt/cross-pi-gcc-10.2.0-64/aarch64-linux-gnu/include)
set(CMAKE_LIBRARY_PATH /opt/cross-pi-gcc-10.2.0-64/aarch64-linux-gnu/lib /usr/local/lib)
set(CMAKE_PROGRAM_PATH /opt/cross-pi-gcc-10.2.0-64/aarch64-linux-gnu/bin)
# Adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Search headers and libraries in the target environment only.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
Compiling works fine but when linking I got the error:
Scanning dependencies of target mytest_demo
[ 25%] Linking C executable mytest_demo
/opt/cross-pi-gcc-10.2.0-64/bin/../lib/gcc/aarch64-linux-gnu/10.2.0/../../../../aarch64-linux-gnu/bin/ld: cannot find -lmytest_lib
collect2: error: ld returned 1 exit status

'cannot find -lgcc_s' error when giving toolchain file for Power-PC to CMAKE setup

I am facing some strange issue in cmake while trying to do the cross compilation build. For native build it is working as per expectation:
Case 1: toolchain file is given in include() of CMakelists.txt file.
For Power-PC build, when I give the toolchain file in following way in the CMakelists.txt file :
if(ARM)
include(config/toolchain_la9.cmake)
elseif(POWER-PC)
include(config/toolchain_lppc.cmake)
endif()
everything is working fine and I am able to get all generated executable and binaries with these following compiler and linker flags
/opt/freescale-2010.09/bin/powerpc-linux-gnu-gcc -mdouble-float
-msoft-float -static-libgcc -lpthread -lm -lrt
Case 2: toolchain file is given with cmake -D command.
Again when I commented the case 1 code snippet and try to give the same file as
cmake PATH_TO_CMAKE_DIRECTORY -DCMAKE_TOOLCHAIN_FILE=/home/one/toolchain_files/toolchain_lppc.cmake
This time I am not able to cross compile the source code.
with the following error:
/opt/freescale-2010.09/bin/../lib/gcc/powerpc-linux-gnu/4.5.1/../../../../powerpc-linux-gnu/bin/ld:
cannot find -lgcc_
s
Case 3: With Cmake-gui using 'specify toolchain file for cross-compiling' option
When I give the same file as input to this option. Again I am getting the same issue:
/opt/freescale-2010.09/bin/../lib/gcc/powerpc-linux-gnu/4.5.1/../../../../powerpc-linux-gnu/bin/ld:
cannot find -lgcc_s
The error clearly indicates that the libgcc_s is not present under specified toolchain path. But if it is not present how it is working in case 1.
How I am getting -static-libgcc flag in case 1, do I need to give it explicitly in toolchain file in 2nd and 3rd case.
Even in toolchain file if I am using CMAKE_EXE_LINKER_FLAGS for adding -static-libgcc in 2nd and 3rd case, it is still showing same errors.
I am new in cmake. though it seems very useful to me but here I am stuck.
The toolchain file content is as follows:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER /opt/freescale-2010.09/bin/powerpc-linux-gnu-gcc )
set(CMAKE_CXX_COMPILER /opt/freescale-2010.09/bin/powerpc-linux-gnu-g++)
set(CMAKE_STRIP /opt/freescale-2010.09/bin/powerpc-linux-gnu-strip)
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/opt/freescale-2010.09/lib/gcc/powerpc-linux-gnu/4.5.1/")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mdouble-float -msoft-float")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mdouble-float -msoft-float")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Gcc compilation "cannot compute suffix of object files: cannot compile"

I'm actually reading the LFS book (version 7.1) and I'm blocked at page 53. Trying to compile gcc, I tried the following command:
./configure --target=$LFS_TGT --prefix=$LFS/build/gcc-build --disable-nls\
--disable-shared --disable-multilib --disable-decimal-float --disable-threads\
--disable-libmudflap --disable-libssp --disable-libgomp --disable-libquadmath\
--disable-target-libiberty --disable-target-zlib\
--enable-languages=c\
--without-ppl --without-cloog\
--with-mpfr-include=$LFS/source/mpfr/src
--with-mpfr-lib=$LFS/source/mpfr/src/.libs\
--with-gmp-include=/mnt/LFS/source/gmp\
--with-gmp-lib=/mnt/LFS/source/gmp/.libs\
--with-mpc-include=/mnt/LFS/source/mpc/src\
--with-mpc-lib=/mnt/LFS/source/mpc/src/.libs
to run the configure script of gcc (of course I already compiled mpfr, mpc and gmp as well).
But once I launch:
make -j4
I get the following error:
checking for suffix of object files... configure: error: in `/mnt/LFS/source/gcc-4.6.2/x86_64-lfs-linux-gnu/libgcc':
configure: error: cannot compute suffix of object files: cannot compile
See `config.log' for more details.
make[1]: *** [configure-target-libgcc] Error 1
I tried to google for it and tried the solutions I found but nothing worked. Does anyone know why I get this error?
This issue is caused by dyanmic link library path issue when the test programs try to link against libmpc/libmpfr/libgmp.
Append below environment variable to allow ld link against the correct so file:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/mpc/lib/
Then try build gcc again.
"Building GCC is not trivial, but is not difficult if you follow the instructions carefully.
Many people rush into trying to build it without reading the installation docs properly and make one or more of these common mistakes:
do not run ./configure from gcc src dir (this is not supported) => you need to run configure from outside the gcc source directory
Note: if GCC links dynamically to the prerequisite libs (GMP/MPFR/MPC) then the shared libraries must be in the dynamic linker's path (LD_LIBRARY_PATH), both when building gcc and when using the installed compiler."
Simple example (without dynamic link to GMP/MPFR/MPC):
tar xzf gcc-4.8.0.tar.gz
cd gcc-4.8.0
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir
$PWD/../gcc-4.8.0/configure --prefix=/opt/gcc-4.8.0
make
make install
Sources:
Advogato Doc -
GNU Doc
This error message can arise from a number of different reasons. The best way to figure out which one is to check the logfile '/home/manu/gcc/gcc/i686-pc-linux-gnu/libgcc/config.log' in the example below. Or in the original posters case '/mnt/LFS/source/gcc-4.6.2/x86_64-lfs-linux-gnu/libgcc' and look for the last error line.
Quoting GCC FAQ: http://gcc.gnu.org/wiki/FAQ#configure_suffix
Like any of the GNU projects, GCC is using the GNU autotools to
commonly configure the compilation for the specifics of the build
system. The configure script thereby uses small test programs -
usually called conftest.c - to test if certain functions and/or
features are available. If the compilation of such a test program
fails, you'll see an error message like:
checking for suffix of object files... configure: error: in
`/home/manu/gcc/gcc/i686-pc-linux-gnu/libgcc': configure: error:
cannot compute suffix of object files: cannot compile See `config.log'
for more details. make[2]: *** [configure-stage1-target-libgcc] Error
1 make[2]: Leaving directory `/home/manu/gcc/gcc'
This error message is quite misleading and frequently the problem has
nothing to do with the message. You have to check the file
'config.log' in the directory where the error occurred. In the example
above, you would have to check the 'config.log' file in the directory
'/home/manu/gcc/gcc/i686-pc-linux-gnu/libgcc'. There might be several
test programs that failed during the configuration, but some of these
failures are non-critical. Check for the last error entry in the file.
Common causes for this error message are:
Required libraries for the GCC build are missing, specifically MPFR,
GMP and MPC. If installed as shared libraries they must be in the
runtime linker's search path so they can be found. Please, follow the
instructions in the answer to Why does my ./configure and make fail?
The compiler crashed. For example, if there is an error such as
'conftest.c: internal compiler error:', this indicates a bug in the
compiler. If you are using an unmodified version of GCC, please follow
the procedure to report the bug.
This happens while creating a cross-compiler.
It's not referring to the top-level config.log, but $LFS_TGT/libgcc/config.log.
For me, in there, it says:
configure:3566: /foo/gcc/build/./gcc/xgcc -B/foo/gcc/build/./gcc/ -B/opt/gcc-cross-11.1.0/aarch64-none-elf/bin/ -B/opt/gcc-cross-11.1.0/aarch64-none-elf/lib/ -isystem /opt/gcc-cross-11.1.0/aarch64-none-elf/include -isystem /opt/gcc-cross-11.1.0/aarch64-none-elf/sys-include -o conftest -g -O2 conftest.c >&5
conftest.c:9:10: fatal error: stdio.h: No such file or directory
9 | #include <stdio.h>
| ^~~~~~~~~
compilation terminated.
configure:3569: $? = 1
configure:3782: checking for suffix of object files
configure:3804: /foo/gcc/build/./gcc/xgcc -B/foo/gcc/build/./gcc/ -B/opt/gcc-cross-11.1.0/aarch64-none-elf/bin/ -B/opt/gcc-cross-11.1.0/aarch64-none-elf/lib/ -isystem /opt/gcc-cross-11.1.0/aarch64-none-elf/include -isystem /opt/gcc-cross-11.1.0/aarch64-none-elf/sys-include -c -g -O2 conftest.c >&5
/foo/gcc/build/./gcc/as: line 106: exec: -E: invalid option
exec: usage: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
configure:3808: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "GNU C Runtime Library"
| #define PACKAGE_TARNAME "libgcc"
| #define PACKAGE_VERSION "1.0"
| #define PACKAGE_STRING "GNU C Runtime Library 1.0"
| #define PACKAGE_BUGREPORT ""
| #define PACKAGE_URL "http://www.gnu.org/software/libgcc/"
| /* end confdefs.h. */
|
| int
| main ()
| {
|
| ;
| return 0;
| }
configure:3822: error: in `/foo/gcc/build/aarch64-none-elf/libgcc':
configure:3824: error: cannot compute suffix of object files: cannot compile
See `config.log' for more details
Was your logfile similar?
It's my belief that the gcc compilation/installation process will take the various includes, run them through fixincludes to fix problems and tailor them to the target arch. The expected file is not present.
Referring to the Prerequisites page, I believe this section is relevant (emphasis mine):
C standard library and headers
In order to build GCC, the C standard library and headers must be present for all
target variants for which target libraries will be built (and not only the variant
of the host C++ compiler).
This affects the popular ‘x86_64-pc-linux-gnu’ platform (among other multilib
targets), for which 64-bit (‘x86_64’) and 32-bit (‘i386’) libc headers are usually
packaged separately. If you do a build of a native compiler on ‘x86_64-pc-linux-gnu’,
make sure you either have the 32-bit libc developer package properly installed (the
exact name of the package depends on your distro) or you must build GCC as a 64-bit
only compiler by configuring with the option --disable-multilib. Otherwise, you may
encounter an error such as ‘fatal error: gnu/stubs-32.h: No such file’
I believe that the solution is to obtain headers for the TARGET platform.
The problem is the assembler, "as" is missing. Build and install binutils for the target first.
In my case it was:
export LD_LIBRARY_PATH=/usr/mpc-082/lib:/usr/gmp501/lib:/usr/libelf0812/lib
Whereas each of the above library is the destination of what additional libraries you installed appended with /lib at the end.
Example: Lib-MPC:
1) Downloaded onto /usr/src/libmpc-src
2) cd into /usr/src/mpc-082
3) ../configure --prefix=/usr/mpc-082
4) make
5) make install
6) once installed, verify that you have the new libs installed under /usr/mpc-082-lib
7) add it to your LD_LIBRARY_PATH by doing:
export LD_LIBRARY_PATH=/usr/mpc-082/lib:$LD_LIBDADY_PATH
8) Repeat the same with your LibELF, and LibGMP
9) Go back and compile your GCC, should work after this.
Cheers
H

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