views:

260

answers:

1

I have C++ project that are built using Boost.Build. The project consists of 3 subprojects.

    . [root]
    \-- source
        \-- common
            \-- config
                \-- config.cpp
        \-- project_1
            \-- Jamfile.jam
        \-- project_2
            \-- Jamfile.jam
        \-- project_3
            \-- Jamfile.jam
    \-- Jamroot.jam

Jamroot.jam:

    project my_project 
        : requirements 
          multi 
          debug:DEBUG
        : default-build
          static
        : build-dir bin
        ;

    alias project_1 : source/project_1 ;
    alias project_2 : source/project_2 ;
    alias project_3 : source/project_3 ;

    install dist : project_1 project_2 project_3
        : on EXE
        ;

Each project has Jamfile.jam according to this template:

    project project_N
      : requirements 
          CONFIG_DEFINE_1=
          CONFIG_DEFINE_2=
      ; 

    lib config : [ glob ../common/config/*.cpp ] ;

    exe project_N 
        : [ glob *.cpp ]  config
        :  
        ;

config.cpp uses defines CONFIG_DEFINE_1 and CONFIG_DEFINE_2 for conditional compilation (actually they are simply constants), so there's a separate version of config library per project.

The problem is that such approach causes the config library to be rebuilt each time the whole project is built regardless of were the files changed or not. I.e. building the first time everything is compiled and linked, building the second time without doing any modifications - only the config library is built for each project_N. How should I properly setup the building so no redundand compilation occur?

+1  A: 

As I understand it, your config library is shared over different projects and uses different defines for each project.

It's not possible to overcome recompilation in that case, irrespective of boost build.or any other build system. In between compiles of the cpp files the preprocessed files have changed.

If you want to avoid recompilation one option is to split of the config library into different libraries for each project, but depending on what config looks like, having a lot of code duplication is rarely desireable either...

The only other option I can think of is reducing the amount of code that needs to be recompiled every time.

e.g. you have a sourcefile LargeFunction.cpp with

 #if CONFIG_DEFINE_1
     void VeryLargeFunction() {
        ...
     }
 #elif CONFIG_DEFINE_2
     void VeryLargeFunction() {
        ...
     }
 #endif

Split it into three files, one containing the VeryLargeFunction as defined for DEFINE_1, one as defined for DEFINE_2, and one which simply includes these two based on the values of the defines.

 #if CONFIG_DEFINE_1
    #include "definitionFileFor1"
 #elif CONFIG_DEFINE_2
    #include "definitionFileFor2"
 #endif

This file still needs to be recompiled every time, but the object files which contain the 'real' code, will not.

You'll effectively only relink existing object files on every compile, i.s.o. recompiling everything.

The disadvantage is more maintenance though, and the different function definitions reside in different files, so the code becomes a bit harder to read.

Pieter
I suppose that a target (I assume target = .cpp + dependent .h + defines) should not be rebuilt if nothing of the dependency list is changed. Moreover there is a separate resulting object file per project built. Also I am using MS Visual Studio as an IDE with correcponding solution and it does not do redundant rebuilding.
pingw33n
no, if .cpp + dependent.h + defines doesn't change, nothing should be rebuilt, from your "there's a separate version of config library per project." I got that the defines are different for each project...
Pieter
for the record, I use Boost.Build too for various projects, but never had problems like that
Pieter