Home > Blockchain >  Cmake build with extern libraires
Cmake build with extern libraires

Time:11-30

I am beginner in arm build. I want to build this code for armel platform. I have a code:

#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <nlohmann/json.hpp>
int main() 
{
    return 0;
}

Also I have Cmake file:

cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
project(test CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g  -10)

set(SRC_FILES test.cpp)

add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
add_definitions(-DBOOST_SYSTEM_NO_DEPRECATED)
add_definitions(-DBOOST_ALL_NO_LIB)
add_definitions(-DBOOST_NO_RTTI)
add_definitions(-DBOOST_NO_TYPEID)
add_definitions(-DBOOST_ASIO_DISABLE_THREADS)

add_executable(${PROJECT_NAME} ${SRC_FILES})

I install nlohmann library into:

/usr/local/include/nlohmann/json.hpp

After I generate make and make:

/home/test-machine/project-dir/test/test.cpp:3:10: fatal error: nlohmann/json.hpp: No such file or directory
    3 | #include <nlohmann/json.hpp>
      |          ^~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/test.dir/build.make:82: CMakeFiles/test.dir/test.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:103: all] Error 2

Why I have this error. Help me pls!!!

CodePudding user response:

With non native compilers, you must configure the whole environment.

In fact, when doing so, I would highly suggest using a toolchain file.

Using that you can setup your toolchain, or even multiple toolchain.

Then, for the environment, I would suggest installing the libraries using their installer and let CMake find it. Take nlohmann json for example:

nlohmann_json$ mkdir build
nlohmann_json$ cd build
nlohmann_json/build$ cmake .. -DCMAKE_INSTALL_PREFIX=/home/youruser/arm-prefix -DCMAKE_TOOLCHAIN_FILE=yourtoolchain.cmake
nlohmann_json/build$ cmake --build . --target install

Those command will setup nlohmann json with your toolchain, and will install it in a new prefix.

Then, in your project, you can have such toolchain and such CMakeLists.txt file:

toolchain.cmake:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g  -10)
set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc-10)
set(CMAKE_STAGING_PREFIX /home/youruser/arm-prefix)
set(CMAKE_SYSTEM_PREFIX_PATH /home/youruser/arm-prefix)

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)

CMakeLists.txt:

project(test CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(test)

find_package(nlohmann_json REQUIRED)

target_sources(test PRIVATE test.cpp)
target_link_libraries(test PUBLIC nlohmann_json::nlohmann_json)

The magic lies in the prefix path. When you set an install prefix to install libraries into and you set the same prefix path when building your project, find_package suddenly works. If you use the same toolchain between those two projects, then CMake will detect those two packages as compatible.

Notice that I also explicitly didn't used variables in the CMakeLists file. This is because variables are a pain point of CMake and results in unexpected behaviour. In normal CMake file to define a project, their usage should be rare.

Also, stay away from add_definitions, link_directories, include_directories and all of those. Always prefer target_compile_definitions, target_link_libraries, target_include_directories and other target based commands.


As for boost I don't know their build system very well. There might be ways to cross compile the library and install it, but my knowledge ends here.

CodePudding user response:

It seems to me that the more correct way would be to properly install library and then use the find_package directive.

# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)

Example above is a part of nlohmann Cmake documentation.

CodePudding user response:

There are some problems with your code. If you don't mind I'll be using newer CMake.

# CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(test LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(foobar)

target_sources(foobar PRIVATE
    test.cpp
)

target_compile_definitions(foobar PRIVATE
    BOOST_ERROR_CODE_HEADER_ONLY
    BOOST_SYSTEM_NO_DEPRECATED
    BOOST_ALL_NO_LIB
    BOOST_NO_RTTI
    BOOST_NO_TYPEID
    BOOST_ASIO_DISABLE_THREADS
)

To specify your ARM compiler use a CMAKE_TOOLCHAIN_FILE. If you specify your compiler in your CMake code it might be nice at first but will cause issues later down the road.

# arm.cmake

set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g  -10)

set(CMAKE_C_COMPILER arm-linux-gnueabi-g-10)

Now when you make your project do the following:

cd <your-project>
cmake -S . -B build/ -D CMAKE_TOOLCHAIN_FILE=arm.cmake

Now the issue remaining with your code is that you have no way to find your third party dependencies.

You need to add code to find/link boost. And find/link nlohmann/json

Boost

How do you add Boost libraries in CMakeLists.txt?

nlohmann/json

This repo actually has pretty good docs on how to add the library to your CMake project.

https://github.com/nlohmann/json#cmake

TLDR:

To use this library from a CMake project, you can locate it directly with find_package() and use the namespaced imported target from the generated package configuration:

# CMakeLists.txt
find_package(nlohmann_json 3.2.0 REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
  • Related