8

Let's assume we would like to use boost::file_system library in our cmake multiplatform project (ios, macos, android, windows, linux). One way to do it is to directly copy boost source code into our project. It increases project size and add a lot of maintenance problems, patching, updating and etc. What if we download boost sources during cmake configure step. So I add minimal example (file - main.cxx):

    #include <boost/filesystem.hpp>

    #include <iostream>

    int main(int, char**)
    {
        std::cout << boost::filesystem::current_path() << std::endl;
        return std::cout.fail();
    }

Next is full CMakeLists.txt file to build this minimal example from source without installing boost into system.

cmake_minimum_required(VERSION 3.20...3.23)

project(19-boost-file-system CXX)

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

set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
set(CMAKE_ENABLE_EXPORTS OFF)

include(FetchContent)

fetchcontent_declare(
    BoostAssert GIT_REPOSITORY https://github.com/boostorg/assert.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostConfig GIT_REPOSITORY https://github.com/boostorg/config.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostContainerHash
    GIT_REPOSITORY https://github.com/boostorg/container_hash.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostCore GIT_REPOSITORY https://github.com/boostorg/core.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostDetail GIT_REPOSITORY https://github.com/boostorg/detail.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostInteger GIT_REPOSITORY https://github.com/boostorg/integer.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostStaticAssert
    GIT_REPOSITORY https://github.com/boostorg/static_assert.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostThrowException
    GIT_REPOSITORY https://github.com/boostorg/throw_exception.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostTypeTraits GIT_REPOSITORY https://github.com/boostorg/type_traits.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostPreprocessor
    GIT_REPOSITORY https://github.com/boostorg/preprocessor.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostIterator GIT_REPOSITORY https://github.com/boostorg/iterator.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(BoostIo GIT_REPOSITORY https://github.com/boostorg/io.git
                     GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostConceptCheck
    GIT_REPOSITORY https://github.com/boostorg/concept_check.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostConversion GIT_REPOSITORY https://github.com/boostorg/conversion.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostFunctionTypes
    GIT_REPOSITORY https://github.com/boostorg/function_types.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostFusion GIT_REPOSITORY https://github.com/boostorg/fusion.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(BoostMpl GIT_REPOSITORY https://github.com/boostorg/mpl.git
                     GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostOptional GIT_REPOSITORY https://github.com/boostorg/optional.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostSmartPtr GIT_REPOSITORY https://github.com/boostorg/smart_ptr.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostUtility GIT_REPOSITORY https://github.com/boostorg/utility.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostTypeof GIT_REPOSITORY https://github.com/boostorg/typeof.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostTuple GIT_REPOSITORY https://github.com/boostorg/tuple.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostPredef GIT_REPOSITORY https://github.com/boostorg/predef.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostMove GIT_REPOSITORY https://github.com/boostorg/move.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostAtomic GIT_REPOSITORY https://github.com/boostorg/atomic.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostVariant2 GIT_REPOSITORY https://github.com/boostorg/variant2.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostAlign GIT_REPOSITORY https://github.com/boostorg/align.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostMp11 GIT_REPOSITORY https://github.com/boostorg/mp11.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostWinapi GIT_REPOSITORY https://github.com/boostorg/winapi.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostSystem GIT_REPOSITORY https://github.com/boostorg/system.git
    GIT_TAG boost-1.79.0)
fetchcontent_declare(
    BoostFileSystem GIT_REPOSITORY https://github.com/boostorg/filesystem.git
    GIT_TAG boost-1.79.0)

fetchcontent_makeavailable(
    BoostAssert
    BoostConfig
    BoostInteger
    BoostStaticAssert
    BoostThrowException
    BoostTypeTraits
    BoostPreprocessor
    BoostIo
    BoostIterator
    BoostConceptCheck
    BoostConversion
    BoostFunctionTypes
    BoostFusion
    BoostMpl
    BoostOptional
    BoostSmartPtr
    BoostUtility
    BoostTypeof
    BoostTuple
    BoostPredef
    BoostMove
    BoostAlign
    BoostMp11
    BoostWinapi
    BoostContainerHash
    BoostCore
    BoostDetail
    BoostAtomic
    BoostVariant2
    BoostSystem
    BoostFileSystem)

add_executable(main_boost main.cxx)
target_link_libraries(main_boost PRIVATE Boost::filesystem)

May be you know more simpler solution? How can one compile and link with Boost libs without any hussle directly from GitHub using cmake?

leanid.chaika
  • 2,143
  • 2
  • 27
  • 30
  • Some repos (like math and multiprecision) have standalones that can be consumed from the releases tab. However, `boost::filesystem` will no longer be receiving updates as it has been absorbed into C++17. – user14717 Jul 08 '22 at 15:09
  • Perhaps you can bootstrap all repos recursively: `git pull -r && git submodule update --recursive && ./bootstrap.sh --with-libraries=all ...` – Ted Lyngmo Jul 08 '22 at 15:10
  • 1
    learn to use Conan. Nice easy and soles this problem in proper way. It can be integrated with cmake (in fact it is main use case). – Marek R Jul 08 '22 at 15:22
  • 2
    I would seriously recommend just using `find_package(Boost)` and [vcpkg](https://vcpkg.io) – Alex Reinking Jul 08 '22 at 15:30
  • 1
    I'm with all the commenters. Use a package manager (conan, vcpkg, build2 or even biicode and some others). Some integrate nicely with CMake. If you must, use the `git clone --recurse-submodules https://github.com/boostorg/boost` approach. 99% of the time it will be quicker to download the release tarball – sehe Jul 08 '22 at 19:59
  • vcpkg - not supporting ios and android, conan - large, slow, complex integration with android, build2 - not found android example, biicode - win, mac, linux only, simple `find_package(Boost)` - not working if you need exact version of library or add patch to it. – leanid.chaika Jul 08 '22 at 21:45

3 Answers3

9

This is what I used:

cmake_minimum_required(VERSION 3.24)
project(p)

set(BOOST_INCLUDE_LIBRARIES thread filesystem system program_options)
set(BOOST_ENABLE_CMAKE ON)

include(FetchContent)
FetchContent_Declare(
  Boost
  GIT_REPOSITORY https://github.com/boostorg/boost.git
  GIT_TAG boost-1.80.0
)
FetchContent_MakeAvailable(Boost)

add_executable(boost_test boost_test.cpp)
target_link_libraries(boost_test PRIVATE Boost::filesystem
                                         Boost::program_options)

This is not exactly clear why, but in your case you can reduce version to:

cmake_minimum_required(VERSION 3.24)
project(p)

set(BOOST_INCLUDE_LIBRARIES thread filesystem system)
set(BOOST_ENABLE_CMAKE ON)

include(FetchContent)
FetchContent_Declare(
  Boost
  GIT_REPOSITORY https://github.com/boostorg/boost.git
  GIT_TAG boost-1.74.0
)
FetchContent_MakeAvailable(Boost)

add_executable(boost_test boost_test.cpp)
target_link_libraries(boost_test PRIVATE Boost::filesystem)

See also:

malat
  • 12,152
  • 13
  • 89
  • 158
4

It's also possible to download a zip archive from a boost release on GitHub. This will be the fastest option for download (considering the size of ~90 MB) and you can be sure that you definitively have all sources / no dependencies are missing.

cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 14)

# Add boost lib sources
set(BOOST_INCLUDE_LIBRARIES thread filesystem system)
set(BOOST_ENABLE_CMAKE ON)

# Download and extract the boost library from GitHub
message(STATUS "Downloading and extracting boost library sources. This will take some time...")
include(FetchContent)
Set(FETCHCONTENT_QUIET FALSE) # Needed to print downloading progress
FetchContent_Declare(
    Boost
    URL https://github.com/boostorg/boost/releases/download/boost-1.81.0/boost-1.81.0.7z # downloading a zip release speeds up the download
    USES_TERMINAL_DOWNLOAD TRUE 
    GIT_PROGRESS TRUE   
    DOWNLOAD_NO_EXTRACT FALSE
)
FetchContent_MakeAvailable(Boost)

# Test
add_executable(test test.cpp)
target_link_libraries(test PRIVATE Boost::filesystem)
steffensc
  • 79
  • 5
2

You can try using GIT_SUBMODULES of FetchContent_Declare command. There is an example below that adds Boost::thread library to the test project

include(FetchContent)

# BOOST

set(BOOST_REQD_SUBMODULES
    "tools/cmake;"
    "libs/assert;libs/exception;libs/throw_exception;libs/static_assert;"
    "libs/bind;libs/function_types;libs/function;"
    "libs/chrono;libs/date_time;"
    "libs/concept_check;"
    "libs/config;libs/container;libs/container_hash;"
    "libs/iterator;libs/utility;libs/type_traits;libs/algorithm;;libs/conversion;libs/numeric/conversion;libs/regex;libs/unordered;libs/tokenizer;libs/move;libs/ratio;libs/lexical_cast;"
    "libs/tuple;libs/variant2;libs/typeof;libs/detail;libs/array;libs/type_index;libs/range;libs/optional;libs/smart_ptr;libs/integer;libs/rational;"
    "libs/intrusive;libs/io;"
    "libs/core;libs/align;libs/predef;libs/preprocessor;libs/system;libs/winapi;libs/atomic;"
    "libs/mpl;libs/fusion;libs/mp11;"
    "libs/thread"
)

Set(FETCHCONTENT_QUIET FALSE)
FetchContent_Declare(
    boost
    GIT_REPOSITORY "https://github.com/boostorg/boost.git"
    GIT_TAG master
    GIT_SUBMODULES ${BOOST_REQD_SUBMODULES}
    GIT_PROGRESS TRUE
    CONFIGURE_COMMAND ""  # tell CMake it's not a cmake project
)

FetchContent_MakeAvailable(boost)

# TEST

ADD_EXECUTABLE(test test.cpp)
TARGET_LINK_LIBRARIES(test PRIVATE Boost::thread gtest gmock gtest_main)

I also found an example with BOOST_INCLUDE_LIBRARIES here https://hreniuc.dev/use-boost-without-conan-only-with-cmake . But I haven't used that approach, so don't know whether it actually works.

malat
  • 12,152
  • 13
  • 89
  • 158
  • Unless absolutely necessary I would suggest not specifying library by library. There are a lot of dependencies and it takes a very long time to sort things out even when CMake gives the exact missing ones. – rbaleksandar Oct 19 '22 at 19:50
  • The above example shows appeding boost::thread library to the project. If some of the dependencies are missing boost::thread will not compile. Dependent libraries have their own dependencies and etc.. How to make boost::library compilable unless listing all the required dependencies? – Коля Кобец Oct 20 '22 at 13:24
  • Yes, you need to list those. All I'm saying is that the listing part can be very, very tedious and you either need to sift through the documentation or do a run-and-fix by obtaining missing modules and gradually adding those. You example, while correct, demonstrates exactly that - for just linking `Boost::thread` you had to manually enter 20-30 dependencies. – rbaleksandar Oct 20 '22 at 13:50