I want to compile a number of libraries for Android using the NDK toolchain. I'm having trouble compiling libiconv, libtiff, libxml2 for example and validate they are built correctly for each target architecture. How can I for example compile a trivial project like libiconv and validate that it was built correctly?
Example by cross-compiling libiconv
You can find these files on GitHub
Build a standalone toolchain
When compiling using Automake you'll need a standalone toolchain that embodies one target architecture and a specific platform revision. The procedure is outlined in the following script.
generate-standalone.sh
#!/bin/bash
ANDROID_NDK_DIR=/opt/android-ndk-r13b
ANDROID_API=19
ANDROID_STL=gnustl
INSTALL_PREFIX=/opt/standalone-r13b
declare -a COMPILE_ARCHITECTURES=("arm" "x86")
pushd ${ANDROID_NDK_DIR}
for ARCH in "${COMPILE_ARCHITECTURES[#]}"
do
INSTALL_DIR=${INSTALL_PREFIX}-${ARCH}
build/tools/make_standalone_toolchain.py \
--arch ${ARCH} \
--api ${ANDROID_API} \
--stl ${ANDROID_STL} \
--install-dir ${INSTALL_DIR}
done
popd
Replace config.sub and config.guess
On some older projects you'll find that the config.guess and config.sub files won't recognize the Android NDK toolchain so you'll need to grab a newer one from automake. In this project I copied the files from Automake 1.15 and just overwrote the ones in the libiconv project.
Compiling for 3 architectures
Flags chosen for the architectures come from Google's ABI Management and Standalone Toolchain pages.
Note: I haven't compiled 64-bit targets in this example. I would need to raise the Android API to 21 to add ARM64 and x86_64.
ANDROID_NDK_DIR=/opt/standalone-r13b
LIBICONV_INSTALL_DIR=${HOME}/Development/libiconv
declare -a COMPILE_ARCHITECTURES=("arm" "armv7a" "x86")
SAVED_PATH="${PATH}"
for ARCH in "${COMPILE_ARCHITECTURES[#]}"
do
COMPILER_GROUP=""
COMPILER_PREFIX=""
case ${ARCH} in
"arm" )
COMPILER_GROUP=arm
;;
"armv7a" )
COMPILER_GROUP=arm
;;
"x86" )
COMPILER_GROUP=x86
;;
esac
export ANDROID_NDK_ROOT="${ANDROID_NDK_DIR}-${COMPILER_GROUP}"
ANDROID_NDK_BIN="${ANDROID_NDK_ROOT}/bin"
ANDROID_SYSROOT_DIR="${ANDROID_NDK_ROOT}/sysroot"
export PATH="${ANDROID_NDK_BIN}:${SAVED_PATH}"
export CFLAGS="--sysroot=${ANDROID_SYSROOT_DIR}"
export LDFLAGS=""
case ${ARCH} in
"arm" )
ABI_NAME=armeabi
COMPILER_PREFIX=arm-linux-androideabi
;;
"armv7a" )
ABI_NAME=armeabi-v7a
COMPILER_PREFIX=arm-linux-androideabi
CFLAGS="${CFLAGS} -march=armv7-a -mfpu=neon -mfloat-abi=softfp -mthumb"
LDFLAGS="${LDFLAGS} -march=armv7-a -Wl,--fix-cortex-a8"
;;
"x86" )
ABI_NAME=x86
COMPILER_PREFIX=i686-linux-android
CFLAGS="${CFLAGS} -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
;;
esac
export CC=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-gcc
export CPP=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-cpp
export CXX=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-g++
export LD=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-ld
export AR=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-ar
export RANLIB=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-ranlib
export STRIP=${ANDROID_NDK_BIN}/${COMPILER_PREFIX}-strip
echo "---- Compiling for ${ARCH}"
./configure --enable-static --host="${COMPILER_PREFIX}" --prefix="${LIBICONV_INSTALL_DIR}/${ABI_NAME}"
make clean
make -j4
make install
done
export PATH="${SAVED_PATH}"
Validating the libraries target the desired architecture
From the NDK you can find arm-linux-androideabi-readelf to determine if for example I'm using Thumb-1 or Thumb-2 instructions in armeabi and armeabi-v7a respectively.
arm-linux-androideabi-readelf -A libiconv.so.2.5.1.so
armeabi
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "5TE"
Tag_CPU_arch: v5TE
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_enum_size: int
Tag_ABI_optimization_goals: Aggressive Speed
armeabi-v7a
If your project has support for advanced features like NEON you'll definitely want to validate that you've compiled the library with the correct options.
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "ARM v7"
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_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: int
Tag_ABI_HardFP_use: Deprecated
Tag_ABI_optimization_goals: Aggressive Speed
Tag_CPU_unaligned_access: v6
Related
I am building a program with the riscv compiler and, when the linking process start, I have the following problem:
/home/luna/noelv-buildroot/output/images/riscv64-buildroot-linux-musl_sdk-buildroot/bin/../lib/gcc/riscv64-buildroot-linux-musl/8.3.0/../../../../riscv64-buildroot-linux-musl/bin/ld: /home/luna/noelv-buildroot/output/images/riscv64-buildroot-linux-musl_sdk-buildroot/bin/../lib/gcc/riscv64-buildroot-linux-musl/8.3.0/libgcc.a(_clzsi2.o): can't link double-float modules with soft-float modules
I am using the compiler to compile and linker my code. This is my compiler:
$ riscv64-linux-gcc --verbose
COLLECT_GCC=/home/luna/noelv-buildroot/output/images/riscv64-buildroot-linux-musl_sdk-buildroot/bin/riscv64-linux-gcc.br_real
COLLECT_LTO_WRAPPER=/home/luna/noelv-buildroot/output/images/riscv64-buildroot-linux-musl_sdk-buildroot/bin/../libexec/gcc/riscv64-buildroot-linux-musl/8.3.0/lto-wrapper
Configured with ./configure --prefix=/home/luna/noelv-buildroot/output/host --sysconfdir=/home/luna/noelv-buildroot/output/host/etc --enable-static --target=riscv64-buildroot-linux-musl --with-sysroot=/home/luna/noelv-buildroot/output/host/riscv64-buildroot-linux-musl/sysroot --enable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --disable-decimal-float --with-gmp=/home/luna/noelv-buildroot/output/host --with-mpc=/home/luna/noelv-buildroot/output/host --with-mpfr=/home/luna/noelv-buildroot/output/host --with-pkgversion='Buildroot 2020.02' --with-bugurl=http://bugs.buildroot.net/ --disable-libmpx --disable-libquadmath --disable-libsanitizer --enable-tls --enable-threads --without-isl --without-cloog --with-arch=rv64imafd --with-abi=lp64d --enable-languages=c,c++ --with-build-time-tools=/home/luna/noelv-buildroot/output/host/riscv64-buildroot-linux-musl/bin --enable-shared --disable-libgomp
Modelo de hilos: posix
gcc version 8.3.0 (Buildroot 2020.02)
Your compiler was build with disable-multilib and for rv64imafd arch. So basically all the libraries provided with the compiler are compiled for this arch.
If you try to compile some code with an other arch , you will not be able to link against it by default. Also, if you provide a library, you will need to be sure it was compiled for this arch to use it in the same time with the libraries provided by the tool chain.
You can see the exact arch and abi of your library with readelf -h.
Can't comment since too low rep,
but have you tried adding the -msoft-float flag
also where are you running that command/program, like hardware specs?
depending on your hardware specs it may be the complete opposite and therefore you should try to avoid the double keyword
Could you also share some code?
I am cross-compiling a go (golang) program to armhf. The program compiles successfully, but when I try to run it on an ARM board, it crashes with 'Illegal instruction' error.
Chasing down the problem, I am almost sure this is due to fact that glib.so.6 has inconsistent architecture.
Facts:
Host: ubuntu 18 (bionic), amd64
GCC: gcc version 7.5.0 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)
I am using multiarch (armhf)
My Cortex-a5 ARM processor:
$ cat /proc/cpuinfo
Processor : ARMv7 Processor rev 1 (v7l)
BogoMIPS : 262.96
Features : swp half thumb fastmult vfp edsp vfpv3 vfpv3d16 tls vfpv4 <br>
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc05
CPU revision : 1
<br>
Hardware : SAMA5D3X-EK
Revision : 0000
Serial : 0000000000000000
All my armhf shared libraries have the following architecture:
$ readelf -A /lib/arm-linux-gnueabihf/ld-2.27.so
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-D16
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_ABI_optimization_goals: Aggressive Speed
Tag_CPU_unaligned_access: v6
However, the armhf libc.so.6 is:
$ readelf -A /lib/arm-linux-gnueabihf/libc-2.27.so
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_user_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: int
Tag_ABI_VFP_args: VFP registers
Tag_CPU_unaligned_access: v6
If I understand things correctly, this is wrong, as my processor does not support neon.
An old version of libc.so.6 on the ARM board looks as follows:
$ readelf -A /media/marek/sd/board/libc.so.6
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-D16
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_HardFP_use: Deprecated
Tag_ABI_VFP_args: VFP registers
Tag_CPU_unaligned_access: v6
Tag_DIV_use: Not allowed
Which looks consistent with the rest.
I wrote a trivial hello world program, and it crashes, too. But when I replace the armhf libc.so.6 with the old version on the board, it runs OK. However, I need a new version of libc (>= 2.25). Thus, it looks like it is sufficient to cross compile it from sources.
I am using configure with the following options:
../configure arm-linux-gnueabihf --prefix=pwd CFLAGS='-march=armv7-a -mfpu=vfpv3-d16 -g -O2 -w' LDFLAGS='-march=armv7-a -mfpu=vfpv3-d16 -g -w'
(also tried without LDFLAGS). All static libraries have the desired architecture but libc.so still has the wrong one (as above) - VFPv3 and NEONv1 are set). What am I doing wrong?
I have a number of libraries built using either CMake or Automake and I'd like to make sure they are compiled correctly for the various architectures. Specifically I'd like to make sure the libraries I targeted for armeabi and armeabi-v7a are compiled with ARM v5 or ARM v7-a instructions.
I have found that readelf on linux provides a degree of certainty that the library was compiled with the desired options and you don't need to be on Linux, because the tool is in the NDK. The following examples were compiled with Clang using NDK r13b.
# -h option instead of -A is helpful if you're inspecting x86 binaries
arm-linux-androideabi-readelf -A library.so
readelf is in the NDK toolchain so even if you're on macOS you can still use it.
armeabi
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "5TE"
Tag_CPU_arch: v5TE
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_enum_size: int
Tag_ABI_optimization_goals: Aggressive Speed
armeabi-v7a
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "ARM v7"
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_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: int
Tag_ABI_HardFP_use: Deprecated
Tag_ABI_optimization_goals: Aggressive Speed
Tag_CPU_unaligned_access: v6
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?
+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.