biicode / boost

Experimental support for the Boost libraries on biicode
MIT License
15 stars 7 forks source link

boost-biicode Build Status Build Status

Experimental support for the Boost libraries on biicode 2.0

Contents

This project contains a set of blocks to test different boost libraries. These are blocks of the form examples/boost-[BOOST_LIB] containing examples extracted from Boost docs or other web resources available, along with some other blocks using my biicode account to test more use cases of Boost (Depending on multiple Boost-related blocks, checking global linking setup, etc).

Each example depends on the biicode/boost block, a CMake-only block with a hook which configures the required version of Boost.

Running a Boost-related block, minimal example

The idea is to hide all the complexity to the user. Using Boost was never this easy!

$ bii cpp:configure -G "Visual Studio 12"
  INFO: Processing changes...

                            BLOCK biicode/boost
  =====================================================================
  ...
                      BLOCK manu343726/boost_example
  =====================================================================
  -- Setting up biicode Boost...
  -- Downloading Boost 1.57.0...
  ... (Trust your ADSL vendor...) ...
  -- Extracting Boost...
  -- Bootstrapping Boost...
  -- Building Boost 1.57.0 with toolset msvc-12.0...
  -- Building lib library...
  ... (Go for churros) ...
  -- BOOST_ROOT: /home/manu343726/.biicode/boost/1.57.0
  -- BOOST_INCLUDEDIR: /home/manu343726/.biicode/boost/1.57.0
  -- BOOST_LIBRARYDIR: /home/manu343726/.biicode/boost/1.57.0/stage/lib
  -- Boost 1.57.0
  -- Found the following Boost libraries
         lib

To use Boost in a block, just include biicode/boost/setup.cmake in the block CMakeLists.txt and run bii_find_boost() function:

INIT_BIICODE_BLOCK()
ADD_BIICODE_TARGETS()

#Include biicode Boost setup
include(biicode/boost/setup)

set(Boost_USE_STATIC_LIBS OFF) #Link with dynamic version of Boost (Just an example, use whatever you need)

#Use `bii_find_boost()`, our wrapper of `find_package(Boost)`:
bii_find_boost(COMPONENTS boost_lib another_boost_lib REQUIRED)

target_include_directories(${BII_BLOCK_TARGET} INTERFACE ${Boost_INCLUDE_DIRS})
target_link_libraries(${BII_BLOCK_TARGET} INTERFACE ${Boost_LIBRARIES})

bii_find_boost()

The bii_find_boost() function is a wrapper of CMake's find_package() to be used to find and configure Boost components automatically.

It's designed with an interface very similar to the usual call to find_package(Boost). The idea is to write almost exactly the same CMake code as usually to use Boost, with all the setup done under the hood.

bii_find_boost([COMPONENTS components...] [REQUIRED])

Note there's no version parameter. To set the required Boost version, go to the biicode.conf of your block and select the proper biicode/boost track.

bii_find_boost() will download and build the required Boost libraries if needed (Not set up previously). Then calls find_package(Boost COMPONENTS ...) after setup.

Note even if the whole Boost distribution will be downloaded if it's not currently available in the biicode environment, bii_find_boost() will build only the Boost components passed, and only if those were not built previously with the current toolset. That means header only Boost libraries, which are configured via a simple call like bii_find_boost(), do not build any component, but only download and set up the Boost distro inside the biicode environment.

Testing with this repo

  1. Clone this repo
  2. Do bii init on it.
  3. Run generate.py (See "Block generation" bellow)
  4. Run bii cpp:build
  5. Go for churros
  6. Come back and see if the blocks were built successfully

Contributing

Please never forget to update the docs here at this readme file, the readme file of the biicode/boost block (Edit the one from the template of course), and the biicode docs here.

Note the block which really does the work is boost/install, biicode/boost just "inherits" from it. All the scripts are located in that block, which is not part of block generation and is always located at blocks/ directory of this project.

The examples are always of the form examples/boost-[LIBRARY] and you are not allowed to publish changes to the biicode cloud (Actually, you don't have the passwords, only the biicode team). The idea is to test all changes locally using this project, send us your changes via git pull-request/whatever, and then we will update the blocks on the cloud. This policy is just to minimize possible broken publications, remember there are devs relying on the blocks on the cloud.

Block generation

This repo maintains the biicode Boost blocks and some example blocks as templates inside the blocktemplates/ folder. Then a generate.py script takes the configuration written on settings.py generating the final blocks located at blocks/.

Templates

The templates are just usual files with <VARIABLE> tags on it's content. generate.py takes the blocks and variables specified in settings.py substituting that tags with the variables value.

Take for example the biicode.conf of biicode/boost template:

[parent]
  <BIICODE_BOOST_BLOCK>:<LATEST_BLOCK_VERSION>

after block generation, that entry will be expanded to something like:

[parent]
  biicode/boost(1.57.0):4

settings.py

There is a settings() function supposed to return a BiiBoostSettings instance. BiiBoostSettings constructor takes three parameters:

I know, the settings are a bit cumbersome to write and read. I will be using some form of YAML in the future.

Currently the settings() function parses arguments from command line using Python's argsparse. So the call to generate.py should be:

generate.py track [--no-publish] [--publish-examples] [--tag tag] [--ci-build] [--passwords passwords] [--exclude "blocks"]

Generation example:

biicode/boost biicode.conf file:

[parent]
  biicode/boost(<TRACK>): <LATEST_BLOCK_VERSION>

biicode/boost/setup.cmake:

include(boost/install/install)

set(BII_BOOST_GLOBAL_OVERRIDE_VERSION <BOOST_VERSION>)

settings.py:

def settings():
    # cli args parsing omitted...

    boost_version = args.track if args.track != "master" else "1.57.0"

    variables = {"BOOST_VERSION":
                 lambda block, block_track, file: boost_version,
                 "TRACK":
                 lambda block, block_track, file: args.track,
                 "LATEST_BLOCK_VERSION":
                 lambda block, block_track, file: latest_block_version(block, block_track)}

    packages = {"biicode/boost": (version, [("biicode.conf", ["TRACK", "LATEST_BLOCK_VERSION"]), ("setup.cmake", ["BOOST_VERSION"])])}

    passwords = ast.literal_eval(args.passwords.replace('->', ':'))

    return BiiBoostSettings(packages, variables, passwords)

generate.py call:

$ python generate.py 1.57.0 --publish-examples --ci-build --passwords "{'biicode': 'what's my password?'}"

This will generate the biicode/boost(1.57.0) block and publish it to biicode cloud automatically.

Continuous integration

Here at biicode we love Travis CI, I'm using that CI service to test all the biicode/boost tracks with 48 different build jobs.

The build matrix includes:

Current status: Build Status

Internal setup

The scripts inside biicode/booost block set up a Boost installation in the biicode environment. Multiple Boost versions are supported, with different compilers and toolsets.

Configuration variables

biicode/boost/setup.cmake reads gets the configuration of variables to configure the Boost setup requested by the user:

Extra variables

Boost setup pipeline

  1. Setup: The internal variables of the hook are configured, and all the directories required for installation are created.
  2. Download and extract: Boost is downloaded on a temporary directory inside the biicode environment directory, only if the Boost package was not downloaded previously. The package is extracted to .biicode/boost/BOOST_VERSION/.
  3. Bootstrap: Boost bootstrap is done to configure the b2 file for build. If b2 already exists, this step is skipped except BII_BOOST_BOOTSTRAP_FORCE variable is enabled.
  4. Build: Boost components specified with BII_BOOST_LIBS are built. You can set up BII_BOOST_BUILD_J for parallel build. If no component was specified, this step is skipped (The default behavior for header-only Boost libraries).
  5. Configure: FindBoost is configured to track the biicode Boost installation. This step prints some info like the BOOST_ROOT, BOOST_INCLUDEDIR, and BOOST_LIBRARYDIR.

Steps 2 to 4 are performed only if the required setup Boost-version + toolset (compiler) was not configured and built previously. The call to Boost's b2 is still done, but that tool is smart enough to skip the already-compiled targets.

Issues

MinGW

To compile Boost.Context, MinGW depends on the Microsoft assembler. Be sure you have ml or ml64 (Depending on your platform) in your PATH. Those executables are usually shipped within Visual Studio, check the Visual Studio Directory/VC/bin/ folder.

CMake configure

Seems that CMake has problems with long-running configures. In some cases, even if the libraries were built successfully, find_package() is not able to find the Boost components. Just rerun bii cpp:configure.