CMake doesn't find Boost libraries while using android-cmake toolchain file
Asked Answered
O

5

10

I am trying to make a CMake project for code that uses Boost libraries. I want to build it for Android, and I am using this project as a reference: https://code.google.com/p/android-cmake/.

I want to use Boost static libraries that I previously built for android and not make them part of the project to compile.

This is my CMakeLists.txt for the project part that uses Boost

#BOOST

set(BOOST_ROOT /home/neb/workspace/SDLActivityCMAKE/jni/boost)

set(Boost_INCLUDE_DIR /home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53)
set(BOOST_INCLUDEDIR /home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53)
set(Boost_LIBRARY_DIR /home/neb/workspace/SDLActivityCMAKE/jni/boost/lib)
set(BOOST_LIBRARYDIR /home/neb/workspace/SDLActivityCMAKE/jni/boost/lib)

set(Boost_USE_STATIC_LIBS ON)
set(USE_STATIC_BOOST ON)
set(Boost_USE_STATIC_RUNTIME ON)
set(BOOST_COMPILER gcc)

find_package(Boost COMPONENTS "thread-gcc-mt-1_53" "date_time-gcc-mt-1_53" REQUIRED)

include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})
#BOOSTEND

add_executable(main main.cpp)
target_link_libraries( main ${Boost_LIBRARIES} )

When I run regular cmake command (cmake .. from subdir of the jni folder in android project) there is no problem, cmake finds libraries. When I am making cmake to use android.toolchain.cmake provided by the project mentioned above I get this (I am using -DBoost_DEBUG option).

-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:566 ] _boost_TEST_VERSIONS = 1.56.0;1.56;1.55.0;1.55;1.54.0;1.54;1.53.0;1.53;1.52.0;1.52;1.51.0;1.51;1.50.0;1.50;1.49.0;1.49;1.48.0;1.48;1.47.0;1.47;1.46.1;1.46.0;1.46;1.45.0;1.45;1.44.0;1.44;1.43.0;1.43;1.42.0;1.42;1.41.0;1.41;1.40.0;1.40;1.39.0;1.39;1.38.0;1.38;1.37.0;1.37;1.36.1;1.36.0;1.36;1.35.1;1.35.0;1.35;1.34.1;1.34.0;1.34;1.33.1;1.33.0;1.33
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:568 ] Boost_USE_MULTITHREADED = TRUE
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:570 ] Boost_USE_STATIC_LIBS = ON
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:572 ] Boost_USE_STATIC_RUNTIME = ON
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:574 ] Boost_ADDITIONAL_VERSIONS = 
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:576 ] Boost_NO_SYSTEM_PATHS = 
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:644 ] Declared as CMake or Environmental Variables:
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:646 ]   BOOST_ROOT = /home/neb/workspace/SDLActivityCMAKE/jni/boost
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:648 ]   BOOST_INCLUDEDIR = /home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:650 ]   BOOST_LIBRARYDIR = /home/neb/workspace/SDLActivityCMAKE/jni/boost/lib
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:652 ] _boost_TEST_VERSIONS = 1.56.0;1.56;1.55.0;1.55;1.54.0;1.54;1.53.0;1.53;1.52.0;1.52;1.51.0;1.51;1.50.0;1.50;1.49.0;1.49;1.48.0;1.48;1.47.0;1.47;1.46.1;1.46.0;1.46;1.45.0;1.45;1.44.0;1.44;1.43.0;1.43;1.42.0;1.42;1.41.0;1.41;1.40.0;1.40;1.39.0;1.39;1.38.0;1.38;1.37.0;1.37;1.36.1;1.36.0;1.36;1.35.1;1.35.0;1.35;1.34.1;1.34.0;1.34;1.33.1;1.33.0;1.33
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:734 ] location of version.hpp: /home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53/boost/version.hpp
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:754 ] version.hpp reveals boost 1.53.0
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:786 ] guessed _boost_COMPILER = -gcc46
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:796 ] _boost_MULTITHREADED = -mt
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:839 ] _boost_RELEASE_ABI_TAG = -s
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:841 ] _boost_DEBUG_ABI_TAG = -sd
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:884 ] _boost_LIBRARY_SEARCH_DIRS = /home/neb/workspace/SDLActivityCMAKE/jni/boost/lib;/home/neb/workspace/SDLActivityCMAKE/jni/boost/lib;/home/neb/workspace/SDLActivityCMAKE/jni/boost/stage/lib;/home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53/lib;/home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53/../lib;/home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53/stage/lib;C:/boost/lib;C:/boost;/boost/boost_1_53_0/lib;/boost/boost_1_53/lib;/boost/lib;/boost;/sw/local/lib
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:962 ] Searching for THREAD-GCC-MT-1_53_LIBRARY_RELEASE: boost_thread-gcc-mt-1_53-gcc46-mt-s-1_53;boost_thread-gcc-mt-1_53-gcc46-mt-s;boost_thread-gcc-mt-1_53-mt-s-1_53;boost_thread-gcc-mt-1_53-mt-s;boost_thread-gcc-mt-1_53
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:994 ] Searching for THREAD-GCC-MT-1_53_LIBRARY_DEBUG: boost_thread-gcc-mt-1_53-gcc46-mt-sd-1_53;boost_thread-gcc-mt-1_53-gcc46-mt-sd;boost_thread-gcc-mt-1_53-mt-sd-1_53;boost_thread-gcc-mt-1_53-mt-sd;boost_thread-gcc-mt-1_53-mt;boost_thread-gcc-mt-1_53
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:962 ] Searching for DATE_TIME-GCC-MT-1_53_LIBRARY_RELEASE: boost_date_time-gcc-mt-1_53-gcc46-mt-s-1_53;boost_date_time-gcc-mt-1_53-gcc46-mt-s;boost_date_time-gcc-mt-1_53-mt-s-1_53;boost_date_time-gcc-mt-1_53-mt-s;boost_date_time-gcc-mt-1_53
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:994 ] Searching for DATE_TIME-GCC-MT-1_53_LIBRARY_DEBUG: boost_date_time-gcc-mt-1_53-gcc46-mt-sd-1_53;boost_date_time-gcc-mt-1_53-gcc46-mt-sd;boost_date_time-gcc-mt-1_53-mt-sd-1_53;boost_date_time-gcc-mt-1_53-mt-sd;boost_date_time-gcc-mt-1_53-mt;boost_date_time-gcc-mt-1_53
-- [ /usr/share/cmake-2.8/Modules/FindBoost.cmake:1108 ] Boost_FOUND = FALSE
CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1195 (message):
  Unable to find the requested Boost libraries.

  Boost version: 1.53.0

  Boost include path:
  /home/neb/workspace/SDLActivityCMAKE/jni/boost/include/boost-1_53

  The following Boost libraries could not be found:

          boost_thread-gcc-mt-1_53
          boost_date_time-gcc-mt-1_53

  No Boost libraries were found.  You may need to set BOOST_LIBRARYDIR to the
  directory containing Boost libraries or BOOST_ROOT to the location of
  Boost.
Call Stack (most recent call first):
  src/CMakeLists.txt:15 (find_package)


-- Configuring incomplete, errors occurred!

So I see that CMake is searching for libraries in this exact directory: /home/neb/workspace/SDLActivityCMAKE/jni/boost/lib In which there are compiled static libraries:

neb@neb-VirtualBox:~/workspace/SDLActivityCMAKE/jni/boost/lib$ ls -l
total 24440
-rwxrwxrwx 1 neb neb   557190 sie 27 12:36 libboost_date_time-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb  1348474 sie 27 12:36 libboost_filesystem-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb   827216 sie 27 12:36 libboost_iostreams-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb  6813972 sie 27 12:36 libboost_program_options-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb 12927086 sie 27 12:37 libboost_regex-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb  1197696 sie 27 12:37 libboost_signals-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb   159462 sie 27 12:36 libboost_system-gcc-mt-1_53.a
-rwxrwxrwx 1 neb neb  1177994 sie 27 12:37 libboost_thread-gcc-mt-1_53.a`

I set all variables pointing to BOOST directories I could find, I set variables saying that Boost libraries should be static, but it still doesn't find them. What else can I do?

Oboe answered 10/9, 2013 at 9:50 Comment(0)
B
8

Finding Boost using CMake

Let me start by saying getting CMake to find Boost can be difficult because the automagic in FindBoost.cmake will bite you and KitWare the makers of CMake have some of the worst documentation of any popular project I've ever encountered. You'll have to walk through the source of FindBoost.cmake to debug it if it fails.

Cross-compiled Boost

The directory you installed cross-compiled boost looks like this assuming 1.62.0

boost-arm-build/include
boost-arm-build/include/boost-1_62
boost-arm-build/lib

The call to CMake from Project-Build directory

cmake \
   -DBoost_NO_SYSTEM_PATHS=TRUE \
   -DBoost_ADDITIONAL_VERSIONS="1.62" \
   -DCMAKE_TOOLCHAIN_FILE=../android.toolchain \
   -DBOOST_ROOT="../boost-arm-build" \
   ../Project/

-DBoost_ADDITIONAL_VERSIONS - CMake looks for Boost using a hardcoded list of strings, if your CMake is older than the Boost version you're building it won't know where to look in the include directory so you'll need to pass it along. Although the version is actually 1.62.0, boost put the includes in boost-1_62 so I use 1.62 instead. In FindBoost.cmake you'll find each version is added twice, as in "1.62.0" "1.62" for this very reason.

You should also inspect the file names of the libraries you built, for my example let's look at system:

libboost_system-gcc-mt-1_62.a
libboost_system-gcc-mt-1_62.so    # Symbolic link to libboost_system-gcc-mt-1_62.so.1.62.0
libboost_system-gcc-mt-1_62.so.1.62.0
libboost_system-gcc-mt-d-1_62.a
libboost_system-gcc-mt-d-1_62.so  # Symbolic link to libboost_system-gcc-mt-d-1_62.so.1.62.0
libboost_system-gcc-mt-d-1_62.so.1.62.0
  • gcc - the compiler used
  • mt - multithreaded
  • d - debug
  • 1_62 - the version of boost, obviously

If you see libboost_system.a instead it means you failed to build boost with --with-layout=versioned and should probably check out my SO Answer on building boost using the NDK. If you see clang instead of gcc it's great you've built boost with clang, but you'll probably need to inform CMake that clang exists using the Boost_COMPILER flag.

-DBoost_COMPILER="-clang"

android.toolchain file

set(CMAKE_SYSTEM_NAME Android)

set(CROSS_COMPILER_DIR /opt/ndk-R13-standalone)
set(CMAKE_C_COMPILER ${CROSS_COMPILER_DIR}/bin/arm-linux-androideabi-gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILER_DIR}/bin/arm-linux-androideabi-g++)

set(ANDROID_NATIVE_API_LEVEL android-19)
set(ANDROID_ABI armeabi-v7a)
set(ANDROID_STL gnustl_static)

set(CMAKE_SYSROOT ${CROSS_COMPILER_DIR}/sysroot)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})

# search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
Bettyebettzel answered 14/10, 2016 at 10:5 Comment(4)
This is very helpful and elaborate answer to a question that I asked over 3 years and 4 jobs ago :D. Thank you!Oboe
I just spent the last many hours solving this problem for myself and wanted to document it somewhere!Bettyebettzel
This is great, I hope someone else benefits from it in the future.Oboe
where to download the 'boost-arm-build' ?Lodging
A
4

I had the very same issue. Using find_host_package(Boost COMPONENTS ..) instead of find_package(Boost COMPONENTS ..) solved the problem for me.

(Found here: http://code.google.com/p/android-cmake/issues/detail?id=16)

Actino answered 9/12, 2013 at 17:6 Comment(0)
M
2

There are a few issues here.

It looks like your boost libraries have been built without runtime-link=static ie they aren't linked statically to the C++ Standard Library. If they had been, their names' postfixes should contain an s (see the boost docs on library naming)

Another issue is that CMake's FindBoost module expects the COMPONENTS arguments to be of the form "date_time", "thread" rather than the full name as you have provided.

Another more minor point is that you shouldn't need to set Boost_INCLUDE_DIR or Boost_LIBRARY_DIR; these are set by the CMake module if successful. Setting them shouldn't cause any problems however, it's just unnecessary clutter.

Also, for BOOST_ROOT, BOOST_INCLUDEDIR, and BOOST_LIBRARYDIR, these would normally be set via the command line using the -D option, or set as environment variables in order to avoid hard-coding paths specific to your machine into the CMakeLists.txt.

The final point is that you should remove the link_directories call. Its own documentation discourages its use, and it's not needed since you're already passing the full paths to the boost libs in the target_link_libraries call.

So, the final version should be more like:

#BOOST
set(Boost_USE_STATIC_LIBS ON)
set(USE_STATIC_BOOST ON)  # Not sure if you really need this later.  If not, delete.
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_COMPILER -gcc)

find_package(Boost COMPONENTS thread date_time REQUIRED)

include_directories(${Boost_INCLUDE_DIRS})
#BOOSTEND

add_executable(main main.cpp)
target_link_libraries(main ${Boost_LIBRARIES})

and you can invoke CMake like this:

cmake . -DBOOST_ROOT=<path to root> -DBOOST_INCLUDEDIR=... -DBOOST_LIBRARYDIR=...
Mistrustful answered 10/9, 2013 at 12:42 Comment(8)
Is it necessary to build these libraries with runtime-link=static? I compliled this code with bare ndk-build using the same libraries and it worked fine. Also, thanks for info about -D option, I plan to use it while I get all other files up and running.Oboe
Also, I tried your proposal and it doesn't help. It sticks with guessed _boost_COMPILER var, which is set to -gcc46. Is it correct? In cmake file there is set(BOOST_COMPILER gcc), shouldn't it be gcc instead?Oboe
Ah - let me just update my answer. It should be Boost_COMPILER rather than BOOST_COMPILER. Sorry!Mistrustful
Still no luck, although I think it should be set(Boost_COMPILER -gcc) instead of set(Boost_COMPILER gcc).Oboe
Yes, you're right about the "-gcc" - updated now thanks. Can you paste the updated debug output?Mistrustful
It's here: pastebin.com/550T4Xeb . I didn't notice anything to change too much from the original.Oboe
It all looks right. CMake's looking for boost_thread-gcc-mt-1_53, which really means libboost_thread-gcc-mt-1_53.a since Boost_USE_STATIC_LIBS is ON; and it's looking in "/home/neb/workspace/SDLActivityCMAKE/jni/boost/lib" which is where the lib is located. Assuming you still have a file called "/home/neb/workspace/SDLActivityCMAKE/jni/boost/lib/libboost_thread-gcc-mt-1_53.a", it should find it. I'm afraid I'm out of ideas here - sorry. You could try the CMake mailing list.Mistrustful
Thanks for your efforts. I guess it's something NDK specific. I will try the list tomorrow.Oboe
S
0

I faced the same problem. I built boost by using this repository Boost for android and I only got static libraries.

I don't think you really need to use cmake's find_package. This how I simply use it in my CMakeList.txt

add_library(boost_system-gcc-mt-1_55  STATIC IMPORTED  GLOBAL)
set_target_properties( # Specifies the target library.
                       boost_system-gcc-mt-1_55

                       # Specifies the parameter you want to define.
                       PROPERTIES IMPORTED_LOCATION

                       # Provides the path to the library you want to import.
                       ${CMAKE_SOURCE_DIR}/src/main/jni/boost/lib/libboost_system-gcc-mt-1_55.a )
SET(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR} boost_system-gcc-mt-1_55)
# You can make this include just once
include_directories("src/main/jni/boost/include/boost-1_55")
target_link_libraries(${MyNDKSampleLibs}
                   ${Boost_LIBRARY_DIR}
                   ${log-lib} 

The only thing I can mention here is not to forget the cmake var ${CMAKE_SOURCE_DIR} in set_target_properties function.

Scrimp answered 5/4, 2017 at 18:41 Comment(0)
P
0

Sharing to help people that want to use Boost with Android (using Android Studio), with a couple of tricks to debug efficiently cmake FindBoost script.

  1. clone repo at

    git clone https://github.com/moritz-wundke/Boost-for-Android.git

  2. build boost with (check readme for windows)

    ./build-android.sh $(NDK_ROOT)

  3. add on buuild.gradle variables pointing to your path, similar as:

externalNativeBuild {
   cmake {
       cppFlags '-std=c++17' // not needed but common
       DBOOST_PATH="+"/Users/bloom/sw_develop/Libraries/Boost-for-Android/build/out/"
   }
}
  1. add on Cmakelist a section similar to this one:
    set(CMAKE_FIND_DEBUG_MODE FALSE)
    set(Boost_DEBUG 0)
    set(CMAKE_SYSROOT_OLD ${CMAKE_SYSROOT})
    set(CMAKE_SYSROOT "")
    set(BOOST_ROOT ${BOOST_PATH}/${CMAKE_ANDROID_ARCH_ABI})
    message("LOOKING FOR BOOST ROOT IN " ${BOOST_ROOT})
    set(BOOST_INCLUDEDIR ${BOOST_PATH}/${CMAKE_ANDROID_ARCH_ABI}/include/boost-1_82)
    set(BOOST_LIBRARYDIR ${BOOST_PATH}/${CMAKE_ANDROID_ARCH_ABI}/lib)
    set(Boost_LIB_PREFIX lib)

    set(Boost_ADDITIONAL_VERSIONS "1.82.0" "1.82")
    set(Boost_NO_SYSTEM_PATHS TRUE)
    set(Boost_COMPILER "-clang-darwin")
    set(Boost_USE_STATIC_LIBS        ON)
    set(Boost_USE_MULTITHREADED      ON)
    set(Boost_USE_STATIC_RUNTIME    OFF)
    find_package( Boost 1.82.0 COMPONENTS serialization )

    if(Boost_FOUND)
        message("Boost_FOUND is True")
        include_directories(${Boost_INCLUDE_DIRS})
    else()
        message(FATAL_ERROR "Boost_FOUND is False")
    endif()
    set(CMAKE_SYSROOT ${CMAKE_SYSROOT_OLD})

    #and after defining the target don't forget the line
    target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})


Very useful to turn on for debugging the CMAKE_FIND_DEBUG_MODE and Boost_DEBUG. The first will show the paths where includes and libraries are searched. FindBoost looks for a common header and the libraries to determine if boost is found or not. The second one prints debug info for FindBoost. I had to remove the word STATUS from this line on the script to make it work: message(STATUS "[ ${file}:${line} ] ${text}"). To open the findboost.cmake script trigger an error with set(Boost_ROOT "pippo") and click on the link on the error message.

I had to use a trick and set the set(CMAKE_SYSROOT "") because the paths passed were weirdly appended to an ndk path, and this triggered the notfound errors. This was reported to the ndk google groups and may be fixed in the future.

The rest of the settings are pretty explanatory.

Don't forget to vote this answer and click subscribe. Ah no, that is on youtube :)

Propagandism answered 14/12, 2023 at 18:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.