Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMAKE cross compile libraries are not found

I'm having strange problems with my cmake cross-compiler projects.

My own libraries are found but not the (system) libraries from my toolchain.

Previously I was using KDevelop on debian squeeze machine. now on my new machine with debian wheezy the configuring fails. It does not find the system libraries like m or pthread.

On my old machine the following was working perfectly, but I do not remember that I did something special to make this work.

Here is one of my CMakeLists.txt files

cmake_minimum_required(VERSION 2.8)
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 2.6.36.4)
SET(CMAKE_C_COMPILER arm-angstrom-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER arm-angstrom-linux-gnueabi-g++)
include_directories(../include
  ../../../sample/include)

project(testmain)

add_executable(testmain
   some_c-source-file.c)

set(CMAKE_LIBRARY_PATH ../lib/arm-26/lib
  ../../../sample/lib/arm-26/lib)
find_library(LIBS_TEST NAMES akku)
find_library(LIBS_M NAMES m)
find_library(LIBS_PTHREAD NAMES pthread )
target_link_libraries(akkumain
  ${LIBS_TEST}
  ${LIBS_M}
  ${LIBS_PTHREAD})

set(CMAKE_C_FLAGS "-Wall -Werror")
set(CMAKE_C_FLAGS_DEBUG "-g3 -O2 -rdynamic")
set(CMAKE_C_FLAGS_RELEASE "-g0 -O0")
set(CMAKE_CXX_FLAGS "-Wall -Werror")
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -O2 -rdynamic")
set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O0")

This is the message displayed when trying to compile using KDevelop: (to repeat myself: this was working on my old machine)

/home/user/testmain/build> /usr/bin/cmake -DCMAKE_BUILD_TYPE=Debug /home/user/testmain/
-- The C compiler identification is GNU 4.3.3
-- The CXX compiler identification is GNU 4.3.3
-- Check for working C compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-gcc
-- Check for working C compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-g++
-- Check for working CXX compiler: /usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
LIBS_M
    linked by target "akkumain" in directory /home/user/testmain
LIBS_PTHREAD
    linked by target "akkumain" in directory /home/user/testmain

So LIBS_TEST is found. But not libm or libpthread. I tried this with different projects: All of my libraries are found, but none of the "system" libraries.

I already tried different things like

set(CMAKE_FIND_LIBRARY_PREFIXES lib )
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )

and some more things I do not remember.

The only thing what IS WORKING is when I specify the directory manually:

find_library(ASTLIBS_M NAMES m PATHS /usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib)

After specifying this to my CMakeLists.txt the library is found and I can compile my project without any errors.

BUT: This is not what I want, because I have a LOT of projects and many libraries and I don't want to edit all my CMakeLists.txt... :(

Does anybody know what made my old machine find the system-libs without specifying anything special inside my IDE/CMake files?

Edit: I just noticed for one of my executables that on Linker stage it throws some errors that it cannot find some symbols from glibc - seems there is something more wrong with my debian wheezy system. - I hope I can figure it out...

Edit:

Maybe I should give a short summary: My code compiles well, but all libraries from my toolchain are not found, but if I add the path to the libs of my toolchain manually it compiles but fails on linker stage.

like image 824
Meister Schnitzel Avatar asked Jul 18 '13 11:07

Meister Schnitzel


People also ask

How does CMake know which compiler to use?

CMake needs a way to determine which compiler to use to invoke the linker. This is determined by the LANGUAGE property of source files of the target , and in the case of static libraries, the LANGUAGE of the dependent libraries. The choice CMake makes may be overridden with the LINKER_LANGUAGE target property.

What is Cmake_toolchain_file?

It is the path to a file which is read early in the CMake run and which specifies locations for compilers and toolchain utilities, and other target platform and compiler related information.

What is Cmake_sysroot?

The CMAKE_SYSROOT content is passed to the compiler in the --sysroot flag, if supported. The path is also stripped from the RPATH / RUNPATH if necessary on installation. The CMAKE_SYSROOT is also used to prefix paths searched by the find_* commands.


2 Answers

Have you ever tried using a toolchain file? I also cross-compile to ARM and AVR a LOT and it works very well with no hassle (I also use KDevelop and it works beautifully along with CMake). The main point is specifying the path to your toolchain root filesystem through the CMAKE_FIND_ROOT_PATH variable. Try putting all this in a file, which I usually name after the architecture I'm cross-compiling to (in this case I called it arm-unknown-linux-gnueabi.cmake):

# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Linux)

# which C and C++ compiler to use
SET(CMAKE_C_COMPILER   arm-unknown-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER arm-unknown-linux-gnueabi-g++) 

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH  /home/claudio/TS-7400/rootfs) 

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search 
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)

Note the variables CMAKE_FIND_ROOT_PATH_MODE_xxx variables control where CMake will look for binaries, libraries and header files. I usually set PROGRAM to NEVER so it never uses binaries from your cross-architecture root filesystem, since they will not run on your host machine anyway. For libraries and header files BOTH means it will search first your specified ROOT_PATH and then if it doesn't find something it will go through your host machine system dirs.

That way, whenever you want to cross-compile a project all you have to do is to create a build directory (so it doesn't mix your sources with files created during build) and then run cmake from there specifying the toolchain file you want to use (I'm supposing your CMakeLists.txt is together with your toolchain file on the same dir your sources are located - project_sources_dir in my example):

cd project_sources_dir
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=../arm-unknown-linux-gnueabi.cmake ..

The whole point of using a toolchain file is that, if you want to compile the exact same project for your host machine, you don't have to change a single line in your CMakeLists.txt. Just run cmake without specifying the toolchain file:

cd project_sources_dir
mkdir build
cd build
cmake ..

and your project is ready for compiling native for your host machine instead. If all that isn't enough, you can look for more details here on CMake Cross Compiling

like image 131
Claudio Avatar answered Sep 30 '22 09:09

Claudio


There are certain default paths where CMake's find_library module searches. If your system libs on your old machine happen to be located in one such place, they will be found without any additional work needing to be done.

However, as your new machine's path to these libs seems to be "/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib", you'll need to tell CMake about this.

One such way, is as you have shown (adding the path explicitly). But in this case, the path is probably specific to just that machine - so you'd be better to only set that path when you invoke CMake on that machine. You can add it to CMAKE_PREFIX_PATH for example:

cmake . -DCMAKE_PREFIX_PATH=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr

(Note: the path in this case get "lib" appended when find_library is called).

Or if you only want to affect the find_library search paths, and not all find_xxx modules, set CMAKE_LIBRARY_PATH

cmake . -DCMAKE_LIBRARY_PATH=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib
like image 42
Fraser Avatar answered Sep 30 '22 07:09

Fraser