Is it possible to build Boost with CMake? [closed]
Asked Answered
O

2

62

Rather than include static libraries in my source tree in a cross-compiled project I'd like to add boost directly into cmake and build it. Is this available?

Overall answered 21/8, 2013 at 10:0 Comment(9)
Why cmake, what's wrong with bjam?Boatright
Hi, nothing is wrong with bjam. It is just that CMake would integrate smoothly with all the other libraries I have. when (and that is not often) i find a lib that has no cmakefile, i get it from the web or write it myself. But in the case of boost, 1 the libs relationships are not trivial. 2 Some people seems to be working on this already so i would prefer to use the proper way (also the git modularized would be great, but that would only be a bonus).Overall
Why do you need a cmakefile for boost? Isn't it just... compile and forget?Abduct
you could use an external project to build boost with bjam. like here: cmake.org/pipermail/cmake/2012-June/050775.htmlCannot
Hey could you elaborate what the 'XXXX' should be standing for in this setting as I'm having similar issue.Roarke
32 upvotes, 14 stars, and this question was closed?? The accepted answer was vital in helping us integrate Boost into our project's CMake-based build. Can you explain why you closed this question, @bluefeet ?Raspberry
@EmileCormier Votes and favorites don't indicate the on-topic nature of a question. This question is off-topic for SO, feel free to edit it to bring it inline with what's on-topic and it will go into the reopen queue for review.Southwards
@bluefeet, I was going to edit the question as you suggested, and I now see how subjective it was. Sorry about my complaint. :-)Raspberry
@bluefeet, I did what I could to try to salvage the question. I'm pretty sure I captured the motivation of the original poster, and have rephrased the question to not be subjective.Raspberry
T
46

We've struggled with this a fair bit too at my workplace. While I certainly can't claim to know the "best" way, I can offer the following thoughts on my experiences.

We initially just required devs to install boost separately and had CMake do its normal checks in the form of a find_package(Boost...) call. This was easy, but not automated, and caused problems for devs with older versions of boost already installed.

We then changed tack and added a copy of the boost sources which we cloned from one of the projects you mentioned above. I can't recall the specifics, but I think it was a precursor to the one currently being worked on in the Ryppl project. The main point was that it already had support for CMake; the boost libraries were actual CMake targets added via add_library calls, which made them easier to work with in the CMake code.

While this solved the previous problems by automating the use of boost in our project, it ultimately became a maintenance nightmare. The boost project we had cloned from changed radically and is now very dependent on Ryppl-specific CMake functions. We didn't want to add Ryppl as a dependency, so we changed tack again!

We looked at the projects you mentioned in your question, and likewise found none of them to be usable.

Our current setup makes use of CMake's ExternalProject module. This allows us to download and build boost to our build tree.

Advantages:

  • Low maintenance
  • Automated, so all devs use the same version built with the same flags
  • Keeps our own source tree free from third-party code
  • Multiple copies of boost can happily co-exist (so no chance of accidentally linking to a copy built with a different compiler/stdlib combination)

Disadvantages

  • Deleting your build tree means having to download and build boost from scratch. This could be ameliorated by e.g. downloading to a fixed location (say, system temp dir), so the download/unzip step could be skipped if an existing copy of the boost sources is found.
  • The boost libraries are not proper CMake targets (i.e. they haven't been added via add_library calls)

Here's a link to our CMake code. There are a few ways in which this needs improved, but it currently works reasonably well for us.

I hope that soon this answer becomes out of date and a decent, modularised, CMake-compatible solution becomes available.

Tripping answered 21/8, 2013 at 12:46 Comment(9)
Thank you I will give it a try, I encountered the same issue with installed versions, so for now that is what I doo, limited to filesystem (i.e. less than 10 src files) so rebuilding is not a big issue, but the modules i ve seen on git/ryppl would be better as it would help me to not redo this on aother project and just build what i need.Overall
Yes - it's just a pity that the CMake version depends on Ryppl modules. We'd really rather not have another 3rd party dependency. I think in your case I'd be tempted to investigate just adding Boost.Filesystem and its dependent (e.g. Boost.System) source files to your repo and using add_library. BTW, I think Boost.Filesystem was being looked at with a view to being added to the Standard Library. From what I recall, it's not one of the changes scheduled for C++14, but I think the Committee is pushing for a faster uptake of new libs into the Standard. You may not need Boost at all then.Tripping
yes, i know but even if it is already in VC2012, it is not in xcode 5 (DP5) from what i ve seen, so i decided to use boost.filesystem. And yes for now i ve directly added the sources of filesystem and sytem to my pproject but if in future i want to use more of boost that would be best. About the cmake modularized of boost i could build most of it on windows, using the boost-zero repository and submodules but it is neither really mature for production, neither up to date on boost 1.54 from what i ve seen but i m not expert in boost.Overall
also about your cmake it is great ut i even have trouble to launch bootstrat.bat, i don t know if bjam will work (i m sure this is a problem on my side as this is a well tested tool)Overall
Yeah - sorry - I meant at some point in the future you might not need Boost.Filesystem. As for the problem running bootstrap.bat, I'd probably have to see the error message to be able to help. You could try just running bootstrap.bat from an MSVC command prompt on a freshly-downloaded copy of Boost to check it works.Tripping
That is what I did, and it failed, It looks like my PATH does not include the right variables, I don t know why. (I was using visual command, I also tried to run the .bat that sets those variables but it fails too...)Overall
I added Windows/system32 to my PATH (it has been removed I don't know how) and the bootstrap + b2 works fineOverall
Fraser, I had a look at your cmake code, it works like a charm under Visual Studio 12, but it fails to build under Linux("no rule to make the target boost_1_55_0_GNU_4_8_2/stage/lib/..."). Any ideas? i'm using cmake 3.0.1. Should i file a bug in your project?Kondon
@Tripping Thanks for such an awesome post.Fourwheeler
D
5

I found Fraser's answer above to be a good starting point, but ran into some issues using Boost 1.55.0 on our system.

First we wanted to have a self-contained source code package for our applications, so preferred not to use the CMake ExternalProject. We were only using the thread and date_time libraries from Boost, so we used bcp to create a subset of Boost with the build tools, thread and other dependent libraries:

$ bcp tools/build thread system date_time ../boost_1_55_0_threads_only

and checked this into our svn repository.

Next, I was able to adapt Fraser's CMake file to build on Linux, but ran into problems running the bootstrap.bat file on Windows with CMake's execute_process command. To run bootstrap.bat we first needed to run the relevant Visual Studio vcvarsall.bat script to set environment variables (we could probably figure out which individual variables need to be set, but it was easier to run the whole script). To run two .bat files in the same shell using execult_process, we used cmd /c and listed the files separated by a & as the argument.

Also bootstrap.bat did not set the exit code to non-zero in case of failure, so using the execute_process RESULT_VARIABLE to check for success didn't work. Instead we checked that the b2.exe executable had been created after the command was run.

One last issue: bootstrap.sh supports the --prefix= option, which bootstrap.bat does not. I also found that specifying the --prefix option for b2.exe on windows worked, but using the --prefix option for b2 on Linux, without specifying it for bootstrap.sh gave errors. (I haven't understood why yet).

So the relevant part of our CMake file looks like:

  #
  # run bootstrap
  #
  if(WIN32)
    if(MSVC10)
      set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 10.0\\VC\\vcvarsall.bat")
    elseif(MSVC11)
      set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 11.0\\VC\\vcvarsall.bat")
    elseif(MSVC12)
      set(VCVARS_CMD "C:\\Program^ Files^ ^(x86^)\\Microsoft^ Visual^ Studio^ 12.0\\VC\\vcvarsall.bat")
    # elseif(...)
     # add more options here
    endif(MSVC10)
    set(BOOTSTRAP_CMD "${VCVARS_CMD} & bootstrap.bat")
    message("Executing command: ${BOOTSTRAP_CMD}")
    execute_process(COMMAND cmd /c "${BOOTSTRAP_CMD}" WORKING_DIRECTORY ${APT_BOOST_SRC}
                  RESULT_VARIABLE BS_RESULT OUTPUT_VARIABLE BS_OUTPUT ERROR_VARIABLE BS_ERROR)
    if(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
      message(FATAL_ERROR "Failed running cmd /c ${BOOTSTRAP_CMD} in ${APT_BOOST_SRC}:\n${BS_OUTPUT}\n${BS_ERROR}\n")
    else(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
      message("bootstrap output:\n${BS_OUTPUT}")
    endif(NOT EXISTS ${APT_BOOST_SRC}/b2.exe)
  else(WIN32)
    set(BOOTSTRAP_CMD "./bootstrap.sh")
    set(BOOTSTRAP_ARGS "--prefix=${APT_BOOST_BIN}")
    message("Executing command: ${BOOTSTRAP_CMD} ${BOOTSTRAP_ARGS}")
    execute_process(COMMAND "${BOOTSTRAP_CMD}" ${BOOTSTRAP_ARGS} WORKING_DIRECTORY ${APT_BOOST_SRC}
                  RESULT_VARIABLE BS_RESULT OUTPUT_VARIABLE BS_OUTPUT ERROR_VARIABLE BS_ERROR)
    if(NOT BS_RESULT EQUAL 0)
      message(FATAL_ERROR "Failed running ${BOOTSTRAP_CMD} ${BOOTSTRAP_ARGS} in ${APT_BOOST_SRC}:\n${BS_OUTPUT}\n${BS_ERROR}\n")
    endif()
  endif(WIN32)
  #
  # run b2
  #
  set(B2_ARGS "link=static" "threading=multi" "runtime-link=static" "variant=release")
  foreach(COMP IN LISTS APT_BOOST_COMPONENTS)
    set(B2_ARGS "--with-${COMP}" ${B2_ARGS})
  endforeach(COMP IN LISTS APT_BOOST_COMPONENTS)
  if(WIN32)
    if(MSVC11)
      set(B2_ARGS "--toolset=msvc-11.0" ${B2_ARGS})
    elseif(MSVC12)
      set(B2_ARGS "--toolset=msvc-12.0" ${B2_ARGS})
    endif(MSVC11)
    file(TO_NATIVE_PATH ${APT_BOOST_BIN} APT_BOOST_BIN_WIN)
    set(B2_ARGS "--prefix=${APT_BOOST_BIN_WIN}" ${B2_ARGS} "architecture=x86" "address-model=64")
  endif(WIN32)
  set(B2_ARGS ${B2_ARGS} install)
  set(B2_CMD "./b2")
  message("Executing command: ${B2_CMD} ${B2_ARGS}")
  execute_process(COMMAND ${B2_CMD} ${B2_ARGS} WORKING_DIRECTORY ${APT_BOOST_SRC}
                  RESULT_VARIABLE B2_RESULT OUTPUT_VARIABLE B2_OUTPUT ERROR_VARIABLE B2_ERROR)
  if(NOT B2_RESULT EQUAL 0)
    message(FATAL_ERROR "Failed running ${B2_CMD} in ${APT_BOOST_SRC}:\n${B2_OUTPUT}\n${B2_ERROR}\n")
  endif()

In the above APT_BOOST_SRC is the location of the Boost subdirectory in our source directory, APT_BOOST_BIN is the location we use to store the libraries in our CMake build directory, and APT_BOOST_COMPONENTS is a list of the Boost libraries we are using.

Degreeday answered 28/7, 2014 at 19:42 Comment(2)
True. I looked at this a little, but the problem I ran into was the spaces and parenthesis in the path which needed to be escaped. Quoting the path was and passing it to cmd.exe in an execute_process command was awkward, so it seemed easier to set the path explicitly and use the ^ to escape the characters. I could use some of CMake's string functions to manipulate the path from VS*COMNTOOLS.Degreeday
This should be the answer. Please see CMaker_Boost, build the Boost with the CMake at a configure time. Now it is tested on the Linux and Android, gcc and clang. Other systems are not tested. I hope this helps.Hegarty

© 2022 - 2024 — McMap. All rights reserved.