Search code examples
c++boostsoftware-distributionamalgamation

Simple and efficient distribution of C++/Boost source code (amalgamation)


My job mostly consists of engineering analysis, but I find myself distributing code more and more frequently among my colleagues. A big pain is that not every user is proficient in the intricacies of compiling source code, and I cannot distribute executables.

I've been working with C++ using Boost, and the problem is that I cannot request every sysadmin of every network to install the libraries. Instead, I want to distribute a single source file (or as few as possible) so that the user can g++ source.c -o program.

So, the question is: can you pack the Boost libraries with your code, and end up with a single file? I am talking about the Boost libraries which are "headers only" or "templates only".

As an inspiration, please look at the distribution of SQlite or the Lemon Parser Generator; the author amalgamates the stuff into a single source file which is trivial to compile.

Thank you.

Edit:

A related question in SO is for Windows environment. I work in Linux.


Solution

  • There is a utility that comes with boost called bcp, that can scan your source and extract any boost header files that are used from the boost source. I've setup a script that does this extraction into our source tree, so that we can package the source that we need along with our code. It will also copy the boost source files for a couple of boost libraries that we use that are no header only, which are then compiled directly into our applications.

    This is done once, and then anybody who uses the code doesn't even need to know that it depends on boost. Here is what we use. It will also build bjam and bcp, if they haven't been build already.

    #!/bin/sh
    BOOST_SRC=.../boost_1_43_0
    DEST_DIR=../src/boost
    TOOLSET=
    if ( test `uname` = "Darwin") then
        TOOLSET="--toolset=darwin"
    fi
    
    # make bcp if necessary
    if ( ! test -x $BOOST_SRC/dist/bin/bcp ) then
        if ( test -x $BOOST_SRC/tools/jam/*/bin.*/bjam ) then
            BJAM=$BOOST_SRC/tools/jam/*/bin.*/bjam
        else
            echo "### Building bjam"
            pushd $BOOST_SRC/tools/jam
            ./build_dist.sh
            popd
            if ( test -x $BOOST_SRC/tools/jam/*/bin.*/bjam ) then
                BJAM=$BOOST_SRC/tools/jam/*/bin.*/bjam
            fi
    
        fi
        echo "BJAM: $BJAM"
        pushd $BOOST_SRC/tools/bcp
        echo "### Building bcp"
        echo "$BJAM $TOOLSET"
        $BJAM $TOOLSET
        if [ $? == "0" ]; then
            exit 1;
        fi
        popd
    fi
    
    if ( ! test -x $BOOST_SRC/dist/bin/bcp) then
        echo "### Couldn't find bpc"
        exit 1;
    fi
    
    mkdir -p $DEST_DIR
    
    echo "### Copying boost source"
    MAKEFILEAM=$DEST_DIR/libs/Makefile.am
    rm $MAKEFILEAM
    # Signals
    # copy source libraries
    mkdir -p $DEST_DIR/libs/signals/src
    cp $BOOST_SRC/libs/signals/src/* $DEST_DIR/libs/signals/src/.
    echo -n "boost_sources += " >> $MAKEFILEAM
    for f in `ls $DEST_DIR/libs/signals/src | fgrep .cpp`; do
        echo -n "boost/libs/signals/src/$f " >> $MAKEFILEAM
    done
    echo >> $MAKEFILEAM
    
    echo "### Extracting boost includes"
    $BOOST_SRC/dist/bin/bcp --scan --boost=$BOOST_SRC ../src/*/*.[Ch] ../src/boost/libs/*/src/*.cpp ../src/smart_assert/smart_assert/priv/fwd/*.hpp $DEST_DIR
    if [ $? != "0" ]; then
        echo "### bcp failed"
        rm -rf $DEST_DIR
        exit 1;
    fi