How to cross compile CMake for ARM with CMake - cmake

In short I'm trying to cross compile CMake with CMake, and I don't think I'm linking libraries correctly. What I want to do may not be possible, but I'd at least like to know why it isn't possible if that's the case.
System: The host is a Linux box with a Cavium ARM9 CPU. It's currently running version 2.6.24.4 of the Linux kernel and Debian 5.0 (Lenny). My workstation is a Core i5 running Ubuntu 12.04 LTS (Precise Pangolin).
My overall goal is to get ROS running on the Linux box. I have to compile from source rather than use apt since Debian 6.0 (Squeeze) binaries require thumb support that the Cavium does not give, and not many of the needed packages are available for Debian 5.0 (Lenny). I'd made progress installing the various libraries needed, but when I got to step 1.3.1 and tried to run CMake, I got the error
CMake 2.8 or higher is required. You are running version 2.6.0
Next I tried to download and build CMake 2.8.8 on the Linux box itself, but it was too much for the system. When that failed, I downloaded the toolchain suggested on the manufacturer's website and used the cross-compiling guide at [www.cmake.org/Wiki/CMake_Cross_Compiling] to build the CMake executables. Here is my toolchain file:
# This one is important
SET(CMAKE_SYSTEM_NAME Linux)
# Specify the cross compiler
SET(CMAKE_C_COMPILER /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu/bin/arm-unknown-linux-gnu-g++)
# Where is the target environment
SET(CMAKE_FIND_ROOT_PATH /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu /pathto/crosstool-linux-gcc-4.5.2-gclibc-2.9-oabi/arm-unknown-linux-gnu/arm-unknown-linux-gnu)
# Search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# For libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
However, use of the binary on the Linux box gives the error
cmake: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by cmake)
Sure enough, the library is not there:
prompt# strings /usr/lib/libstdc++.so.6 | grep GLIBC
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBC_2.3
GLIBC_2.0
GLIBC_2.3.2
GLIBC_2.1
GLIBC_2.1.3
GLIBC_2.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH
I've never cross-compiled before, but I can see one of two scenarios happening: either the binary got created with a link to a higher version of glibcxx on the host machine or the manufacturer's toolchain is more modern than their image. I don't know how to check which is happening or if something else is happening that I don't know about.
My last effort involved trying to statically cross-compile CMake to hopefully get rid of the linking error with
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-technologic.cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS_RELEASE="-static" ..
I got build errors, and that binary didn't work either. I got:
FATAL: kernel too old
Segmentation fault
I'd try installing glibcxx 3.4.14 on the Linux box, but it doesn't look like it's available for this processor.
I've tried searching for CMake dependencies or system requirements and can't find anything. I've also searched on how to build CMake, but most searches turn up how to build other things with CMake rather than building CMake itself.

I do cross-compile a lot for ARM9 devices using CMake, and indeed this looks like you're not linking to the same libs you have on your target device. You shouldn't need to build CMake yourself to get this done, since it does have good support for cross-compiling since version 2.6. Just make sure you set the CMAKE_FIND_ROOT_PATH variable to a path where you have an exact copy of the root filesystem you have on your target device (with libraries and binaries pre-compiled for the target processor). That should solve your problems.
As a sidenote, I like to use crosstool-ng for building my cross-compilers. It is a really nice tool which helps you to build them from scratch, so I try to match the compiler version and glibc to the ones originally used to build the root filesystem (I usually start with a ready made root filesystem from ARMedslack, since I use Slackware for my development box and ARMedslack for my ARM targets).

Related

Why won't find_library find libgmp

I'm trying to build a cmake project, and the repo I have been given has the lines
find_library(gmp gmp)
if(NOT gmp)
message(FATAL_ERROR "gmp not found")
endif()
which cause CMake configuration to fail.
I have been told this CMake works on Redhat Enterprise Linux 7.3.
I have also been told this repo should build in any Linux environment with the correct libraries installed, and an Ubuntu environment has been specifically referenced.
I am building in Debian 9.4.0, I have installed gmp, libgmp.so is located at /usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines/libgmp.so
and I also have a libgmp.so.10 at /usr/lib/x86_64-linux-gnu/libgmp.so.10.
So, to recap, I have been handed a repo I have been told builds, but it does not build, it fails at this specific step, and I can't get google to give me any relevant results on how to fix the issue/what I am doing wrong.
libgmp is installed, but the development libraries are not.
Cmake find_libraries looks for the files required for software development, and while the libgmp package is installed, the libgmp-dev package is not.
Install libgmp-dev.
CMake doesn't search "so-version" files:
If find_library is called for "gmp" library name, CMake searches libgmp.so file, but not libgmp.so.10 one.
Normally, the library file without so-version is just a soft link to the newest so-version file. If your Linux distro doesn't create such link, you may create it manually:
ln -s libgmp.so libgmp.so.10
If you want CMake to find /usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines/libgmp.so file, which is not under directory normally searched by CMake, you need to hint CMake about it. E.g. with PATHS option:
find_library(gmp gmp PATHS "/usr/lib/x86_64-linux-gnu/openssl-1.0.2/engines")

Anyone use GMP on Xeon Phi?

I compiled GMP with icc and -mmic option, but can't install on MIC. How should I install?
I wrote a demo program, compiled with icc. It says can't find gmp.h.
How should I install GMP library on MIC and where to place gmp.h?
Build GMP with Intel Compiler:
cd /home/
wget https://gmplib.org/download/gmp/gmp-6.0.0.tar.bz2
tar -xf gmp-6.0.0.tar.bz2
rm -f gmp-6.0.0.tar.bz2
cd gmp-6.0.0
mkdir mic
cd mic
../configure CC=icc CFLAGS="-mmic" --host=x86_64 --disable-assembly --prefix /home/gmp-6.0.0/mic/
make
make install
Use the Intel Compiler with environment variables for mic development:
GMP_INCDIR=/home/gmp-6.0.0/mic/include
GMP_LIBDIR=/home/gmp-6.0.0/mic/lib
Though I don't have any expertize on Xeon Phi or even ICC if you are running on Unix-like environment, then you might to try to step through normal configure/make procedure on GMP sources pointing on ICC compiler instead of default GCC in order to build static and/or shared library along with generated gmp.h header, that you can then link with your application. You might want to see GMP documentation on that. Here are some advices, that I stepped to trying to compile it for NVIDIA CUDA:
Supply ./configure with CC and CFLAGS variables to point to desired compiler and its whatever options that you want
Be sure that there is no ABI incompability between your host and Xeon Phi device, especially between 32 and 64 bit architecture.
Consider adding --disable-assembly option to generate "pure-C" build (I am not familiar with Xeon Phi assembly and if/how it is compatibile with x86)
Don't forget to run make check (possibly with -j parameter) after you compiled GMP in order to check if tests are passing, it's very important step if you want use it for some professional purpose.
The library is installed in OS by make install command, for default under /usr/local directory (you might add --prefix option if you want it somewhere else), specifically:
/usr/local/include for gmp.h header file
/usr/local/lib for static and/or shared libgmp binaries
You might also try to compile your application with mini-gmp package, which is contained within GMP sources (it's located under mini-gmp directory). It's a subset of mpz_* and mpn_* routines, not as sophisticated and fast as normal GMP (and it doesn't have as much serious tests coverage), but it could make the job done with small footprint (it's contained in one header and C-source file). For such option be sure to obtain most recent version of GMP (or even get it from their repository).

Building a cross-platform application (using Rust)

I started to learn Rust programming language and I use Linux. I'd like to build a cross-platform application using this language.
The question might not be related to Rust language in particular, but nonetheless, how do I do that? I'm interested in building a "Hello World" cross-platform application as well as for more complicated ones. I just need to get the idea.
So what do I do?
UPDATE:
What I want to do is the ability to run a program on 3 different platforms without changing the sources. Do I have to build a new binary file for each platform from the sources? Just like I could do in C
To run on multiple platforms you need to build an executable for each as #huon-dbauapp commented.
This is fairly straightforward with Rust. You use "--target=" with rustc to tell it what you want to build. The same flag works with Cargo.
For example, this builds for an ARM target:
cargo build --target=arm-unknown-linux-gnueabihf
See the Rust Flexible Target Specification for more about targets.
However, Rust doesn't ship with the std Crate compiled for ARM (as of June 2015). If this is the case for your target, you'll first need to compile the std Crates for the target yourself, which involves compiling the Rust compiler from source, and specifying the target for that build!
For information, most of this is copied from: https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md
The following instructions are for gcc, so if you don't have this you'll need to install it. You'll also need the corresponding cross compiler tools, so for gcc:
sudo apt-get install gcc-arm-linux-gnueabihf
Compile Rust std Crate For ARM
The following example assumes you've already installed the current Rust Nightly, so we'll just get the sources and compile for ARM. If you are using a different version of the compiler, you'll need to get that to ensure your ARM libraries match the version of the compiler you're using to build your projects.
mkdir ~/toolchains
cd ~/toolchains
git clone https://github.com/rust-lang/rust.git
cd rust
git update
Build rustc for ARM
cd ~/toolchains/rust
./configure --target=arm-unknown-linux-gnueabihf,x86_64-unknown-linux-gnu
make -j4
sudo make install
Note "-j4" needs at least 8GB RAM, so if you hit a problem above try "make" instead.
Install ARM rustc libraries In native rustc build
sudo ln -s $HOME/src/rust/arm-unknown-linux-gnueabihf /usr/lib/rustlib/arm-unknown-linux-gnueabihf
Create hello.rs containing:
pub fn main() {
println!("Hello, world!");
}
Compile hello.rs, and tell rustc the name of the cross-compiler (which must be in your PATH):
rustc -C linker=arm-linux-gnueabihf-gcc-4.9 --target=arm-unknown-linux-gnueabihf hello.rs
Check that the produced binary is really an ARM binary:
$ file hello
hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), (..)
SUCCESS!!!:
Check: the binary should work on an ARM device
$ scp hello me#arm:~
$ ssh me#arm ./hello
Hello, world!
I've used this to build and link a Rust project with a separate C library as well. Instructions similar to the above on how to do this, dynamically or statically are in a separate post, but I've used my link quota up already!
The best way to figure this out is to download the source code for Servo and explore it on your own. Servo is absolutely a cross-platform codebase, so it will have to address all of these questions, whether they be answered in build/configuration files, or the Rust source itself.
It looks like the rust compiler might not be ready to build standalone binaries for windows yet (see the windows section here), so this probably can't be done yet.
For posix systems it should mostly Just Work unless you're trying to do GUI stuff.
Yes, you won't need to change the source, unless you are using specific libraries that are not cross-platform.
But as #dbaupp said native executables are different on each platform, *nix uses ELF, Windows PE, and OSX Mach-O. So you will need to compile it for each platform.
I don't know the state of cross-compiling in rust, but if they already implemented it, then you should be able to build all the binaries in the same platform, if not, you will have to build each binary on it's platform.

Cross-compiling - retrieve target CPU and version

I'm cross-compiling for VxWorks using cmake. When I run cmake the first time I have to provide informations about compiler, target OS etc..
In the cross-compile dialogue there are three target system settings I set:
Operating System
Version
Processor
(followed by compiler etc.)
While I can retrieve the first one using CMAKE_SYSTEM_NAME, i can't get the version and the processor.
Both return an empty string.
Here's an example:
MESSAGE("CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
MESSAGE("CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}")
Output:
CMAKE_SYSTEM_PROCESSOR:
CMAKE_SYSTEM_VERSION:
My Cmake Version is 2.8.10.2 and target OS is VxWorks (if this matters - compiler are WindRiver GNU).
How can I get the version and processor I've set in the beginning? Or is this impossible if I cross-compile to an OS that's unknown to cmake?
(Btw. Compiling works fine)
It seems this is not possible so far. I'm getting empty strings all the time.
However, there's a working solution, and i guess it's the better way:
Before:
I specified cross-compile settings (Compiler and target system, see question), then it runs over VxWorks specific parts in the CMake list (checked with if( VxWorks ) to ensure it's not executed when other systems are used).
Now (Solution):
I wrote a toolchain file and platform files for VxWorks and required processors.
Cons:
I have to write some extra files:
Toolchain file
Platform file for VxWorks
Further Platform files for each Processor (and processor type, Gnu and Diab)
Pros:
CMake list is much cleaner now
Separate Project and Target settings
Separate System and processor settings - easy to add new Processors in a very clear way but keep System settings
I write some settings in the toolchain file and CMake loads related system / processor settings
...

armadillo C++ matrix library -- how to enable use of ATLAS or LAPACK?

When i compile example2.cpp with armadillo makefile and run it i am getting an error message
error: det(): use of ATLAS or LAPACK needs to be enabled
How do i fix that? I have similar errors when i try to use solve. Details of my setup are:
Ubuntu Lucid Lynx 10.04
Armadillo version: 2.4.2 (Loco Lounge Lizard)
ATLAS 3.9.51
BOOST 1.48.0
g++ (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
Atlas was installed before armadillo was, armadillo installation was configured with Cmake. I am far from an expert in cmake, but i thought that it was supposed to find ATLAS when i generated makefiles with it. Armadillo documentation seem to say that if i install with cmake i don't need to do any manual enabling of ATLAS. I tried to manually hack example2.cpp by inserting
#define ARMA_USE_ATLAS
before the headers, but it just generates a bunch of errors regarding missing stuff on Cblas. Maybe there is a step missing to allow cmake to find ATLAS. It feels i am missing something simple but key. Any help would be greatly appreciated.
Additional Detail:
Edit: for whatever reason i cannot add comment anymore, so i am posting a reply to #Appleman1234 answer below here.
I compiled armadillo and ATLAS from source. I thought that ATLAS has LAPACK and BLAS bundled in and optimized. When i compiled it, i passed a location to lapack tar like
./configure --shared --with-netlib-lapack-tarfile=/<path>/lapack-3.3.1.tgz
I also see in atlas lib directory the following files:
libatlas.a, libcblas.a, libf77blas.a, liblapack.a, libptcblas.a, libptf77blas.a libsatlas.so, libtatlas.so
which seem to indicate that blas, cblas, and lapack are installed on the system. However, CMakeCache.txt in armadillo seem to indicate that cmake didn't find BLAS, CBLAS, CLAPACK as follows
BLAS_LIBRARY:FILEPATH=BLAS_LIBRARY-NOTFOUND
There is no notion of ATLAS in CMakeCache.txt, so i assume that it wasn't found either. Maybe i am mistaken, but it seems that i somehow need to point cmake to ATLAS, i just don't know how. I could also be at error assuming that ATLAS has BLAS, LAPACK and CBLAS. I thought i compiled them as a part of ATLAS, but i could be wrong. Would appreciate your comments.
Solution to the problem:
What Dirk suggested almost worked. The problem as i mentioned in one of the replies to his post was cmake was balking. I misdiagnosed that as a problem with cmake not finding clapack. In fact, after looking more carefully at cmake output i realised it had problems with not finding good compiler or rather dragging its feet when it decided to use as compiler /usr/bin/c++. So i did CXX=g++ and then cmake again which worked fine. After that armadillo compiled fine.
Did you install armadillo from source ?
What did cmake output when running cmake . or ./configure ?
The latter just calls cmake ..
Did it output the values below ?
-- CLAPACK_FOUND = YES
-- CBLAS_FOUND = YES
If they are not YES, then according to CMakeLists.txt, ARMA_USE_ATLAS is set to false and ATLAS isn't used.
In order to use det or solve, install CLAPACK and CBLAS if you want to use ATLAS or just install LAPACK.
As armadillo exists in Debian / Ubuntu, you could simply install all the known build-dependencies to ensure you have all the -dev packages you need:
edd#max:~$ sudo apt-get build-dep armadillo
Reading package lists... Done
Building dependency tree
Reading state information... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
edd#max:~$
Appears that my system in complete in that regard.