I would like to share my experience with building proton version 0.6 as a
static library.

First create a directory somewhere sensible to put the code and do the
build.  I put mine in $HOME/external/proton.  Lets call that BUILD_HOME.
Unarchive the proton v0.6 source code into that directory.

export BUILD_HOME=$HOME/external/proton
mkdir -p $BUILD_HOME && cd $BUILD_HOME && tar xf
~/Downloads/qpid-proton-0.6.tar.gz

I use git to manage my builds, so instead of having version-specific source
directories, I rename them to src and manage source versioning via SCM.

mv qpid-proton-0.6 src

I like to keep my external src directories pristine (just upstream, no
local changes) and apply customizations via patch.  Now we want to build
proton statically and since we'll want to support linking this against
modules and/or dynamic libraries, we want to build using
position-independent code (PIC), so we create a patch file.  The way I do
this is create two directories, new and old, then copy the pristine source
into both and modify the code in new until I have what I want, then use
diff to create the patch.

mkdir -p $BUILD_HOME/patches $BUILD_HOME/old $BUILD_HOME/new
for t in old new; do cp -a $BUILD_HOME/src $BUILD_HOME/$t/build; done
cd $BUILD_HOME/new/build

Now make all the customizations in new/build that are needed.  In this case
I've modified the new/build/proton-c/CMakeLists.txt to build statically,
with PIC and I repaired the ARCHIVE DESTINATION (where the .a file gets
installed to).  I also repaired the pkg-config file to include openssl and
uuid as requirements.  After making customizations, then create your patch.

cd $BUILD_HOME
diff -Naur old new >patches/static_link.patch

Here is the content of my patch (between the --- CUT --- labels):

--- CUT ---
diff -Naur old/build/proton-c/CMakeLists.txt
new/build/proton-c/CMakeLists.txt
--- old/build/proton-c/CMakeLists.txt   2013-12-19 13:22:51.000000000 -0500
+++ new/build/proton-c/CMakeLists.txt   2014-01-16 13:49:10.775278002 -0500
@@ -265,18 +265,18 @@
 set_source_files_properties (
   ${qpid-proton-core}
   PROPERTIES
-  COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS}"
+  COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS} -fPIC
-DPIC"
   )

 set_source_files_properties (
   ${qpid-proton-platform}
   PROPERTIES
-  COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_PLATFORM_FLAGS}"
+  COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_PLATFORM_FLAGS} -fPIC
-DPIC"
   COMPILE_DEFINITIONS "${PLATFORM_DEFINITIONS}"
   )

 add_library (
-  qpid-proton SHARED
+  qpid-proton STATIC

   ${qpid-proton-core}
   ${qpid-proton-platform}
@@ -325,12 +325,12 @@
 # Install executables and libraries
 install (TARGETS proton proton-dump
   RUNTIME DESTINATION bin
-  ARCHIVE DESTINATION bin
+  ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
   LIBRARY DESTINATION ${LIB_INSTALL_DIR})
 install (TARGETS qpid-proton
   EXPORT  proton
   RUNTIME DESTINATION bin
-  ARCHIVE DESTINATION bin
+  ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
   LIBRARY DESTINATION ${LIB_INSTALL_DIR})

 # Install header files
diff -Naur old/build/proton-c/src/libqpid-proton.pc.innew/build/proton-c/src/
libqpid-proton.pc.in
--- old/build/proton-c/src/libqpid-proton.pc.in 2012-10-26
09:42:54.000000000 -0400
+++ new/build/proton-c/src/libqpid-proton.pc.in 2014-01-16
13:21:53.554415327 -0500
@@ -25,6 +25,7 @@
 Name: Proton
 Description: Qpid Proton C library
 Version: @PN_VERSION@
+Requires: openssl uuid
 URL: http://qpid.apache.org/proton/
 Libs: -L${libdir} -lqpid-proton
 Cflags: -I${includedir}
--- CUT ---

Satisfied with the patch, you can now remove the old and new directories.

rm -rf $BUILD_HOME/old $BUILD_HOME/new

Now you'll want to create a build script to generate the custom source tree
and build from it.  My build script is $BUILD_HOME/build.sh.   Here is the
contents of mine:

--- CUT ---
#!/usr/bin/env bash

set -o errexit -o pipefail
pushd . >/dev/null && cd $(dirname $(readlink -e $0))

PROJECT=${PROJECT:-$(basename $PWD)}
CURRENT_VERSION=$(git describe --always --long --dirty)
STAMP_VERSION=$(cat STAMP 2>/dev/null || true)

if [[ "$CURRENT_VERSION" = "$STAMP_VERSION" ]]; then
    echo "Build of '$PROJECT' already up to date" 1>&2
else
    # Build dependencies.
    test -x ./buildDeps.sh && ./buildDeps.sh
    # Copy pristine source to fresh build directory
    rm -rf build
    cp -a src build
    # Apply any patches in the patches directory to the build directory.
    if [[ -d patches ]]; then
        PATCH_TOOL=${PATCH_TOOL:-$(which patch 2>/dev/null)} || \
            (echo "ERROR: 'patch' tool not found in PATH" 1>&2; exit 1)
        test -x $PATCH_TOOL || \
            (echo "ERROR: patch tool '$PATCH_TOOL' not executable" 1>&2 &&
exit 1)
        # Patches are applied in sorted order by filename.
        for patch in $(find patches/ -maxdepth 1 -type f -name '*.patch' |
sort); do
            set -x
            $PATCH_TOOL -p1 <$patch
            set +x
        done
    fi
    INSTALLDIR=${INSTALLDIR:-$PWD/$PROJECT}
    echo "Building $PROJECT ..." 1>&2
    # The CMAKE_INSTALL_PREFIX does not affect the language bindings,
    # so use make install with DESTDIR for these.  For the c library,
    # use CMAKE_INSTALL_PREFIX (not DESTDIR) to get a properly
    # populated pkgconfig file (libqpid-proton.pc).
    disable_lang=""
    for lang in JAVA PERL PHP PYTHON RUBY; do
        disable_lang="$disable_lang -DBUILD_${lang}=OFF"
    done
    set -x
    rm -rf build_proton-c build_proton-bindings
    mkdir -p build_proton-c build_proton-bindings
    cd build_proton-bindings && cmake ../build && make -j4 all && make
install DESTDIR="$(readlink -e ../)/$PROJECT" && \
        cd ../build_proton-c && cmake -j4 $disable_lang
-DCMAKE_INSTALL_PREFIX="$(readlink -e ../)/$PROJECT" ../build && make all
docs && make install && \
        cd .. && echo "$CURRENT_VERSION" >STAMP
    set +x
fi

popd >/dev/null
--- CUT ---

Make adjustments to taste and make it executable.

chmod 755 $BUILD_HOME/build.sh

At this point you should have src directory with pristine sources, a
patches directory with the customizations and repairs we did and a build.sh
file to put it all together.  Now that all the pieces are in place, lets
check it in.  I use git for this.

cd $BUILD_HOME
git init
git add -A .
git commit -a -m'proton v0.6 build'

Now its (finally) time to build!

cd $BUILD_HOME && ./build.sh

What this will do is copy the pristine upstream source in $BUILD_HOME/src
to $BUILD_HOME/build and apply our patch(es) to it, then it will create two
additional directories build_proton-c and build_proton-bindings for doing
our two out-of-source builds (this is some cmake coolness).  Each build
(bindings and the c core) will install its build artefacts into
$BUILD_HOME/proton.  Finally it will create a STAMP file which will include
the git commit hash for this build so that we can run build.sh idempotently
(useful when proton is a component in an even larger build system, as it is
in my case).  The stuff in $BUILD_HOME/proton is now ready for use.

Hope this is useful to someone else out there!

-- 
Davin Shearer

Reply via email to