While refactoring the test Jamfile for Boost.System, I wrote this rule: rule system-run- ( sources + ) { local result ; result += [ run $(sources) : : : <link>static : $(sources[1]:B)_static ] ; result += [ run $(sources) : : : <link>shared : $(sources[1]:B)_shared ] ; result += [ run $(sources) : : : -<library>/boost/system//boost_system <define>BOOST_ERROR_CODE_HEADER_ONLY : $(sources[1]:B)_header ] ; return $(result) ; } to avoid repeating each test three times. The inconsistency is somewhat annoying. We could normalize the third line by introducing a third link type, <link>header, in response to which the library can switch to header-only mode. This is more or less the same suggestion as Niall's _hl targets from the CMake discussion, but it fits Boost.Build better, because the <link> property is automatically propagated to dependencies. Furthermore, after thinking about it a bit, I think that we might even have room for a fourth link type, <link>source, in response to which the library target would pass an appropriate <source> usage-requirement upwards. (<source>error_code.cpp in Boost.System's case.) <link>source is kind of best of both worlds, as it doesn't reparse the source code each time the library is used, and at the same time is not prone to the ODR violations introduced by inadvertently compiling the library and the executable with different, ABI-incompatible options. Comments?
AMDG On 01/21/2018 08:17 PM, Peter Dimov via Boost wrote:
While refactoring the test Jamfile for Boost.System, I wrote this rule:
rule system-run- ( sources + ) { local result ;
result += [ run $(sources) : : : <link>static : $(sources[1]:B)_static ] ; result += [ run $(sources) : : : <link>shared : $(sources[1]:B)_shared ] ; result += [ run $(sources) : : : -<library>/boost/system//boost_system <define>BOOST_ERROR_CODE_HEADER_ONLY : $(sources[1]:B)_header ] ;
return $(result) ; }
to avoid repeating each test three times.
The inconsistency is somewhat annoying. We could normalize the third line by introducing a third link type, <link>header, in response to which the library can switch to header-only mode.
This is more or less the same suggestion as Niall's _hl targets from the CMake discussion, but it fits Boost.Build better, because the <link> property is automatically propagated to dependencies.
So the question is what should <link>header do for libraries that do not have a header-only mode?
Furthermore, after thinking about it a bit, I think that we might even have room for a fourth link type, <link>source, in response to which the library target would pass an appropriate <source> usage-requirement upwards. (<source>error_code.cpp in Boost.System's case.)
You don't need usage requirements for this, and it's not quite the right thing either, as it will continue to propagate up past any linking steps. What you're describing sounds like it should be: alias boost_system : error_code.cpp : <link>source ;
<link>source is kind of best of both worlds, as it doesn't reparse the source code each time the library is used,
This isn't exactly true. It will reparse the source once in each project that uses it. It will also reparse it in each test case that uses it, since test cases get independent build directories.
and at the same time is not prone to the ODR violations introduced by inadvertently compiling the library and the executable with different, ABI-incompatible options.
At least you won't get silent errors, but this is highly likely to cause errors from Boost.Build if you use a source library in two different executables in the same project. (Boost.Build will attempt to share the object file, but if any defines or cxxflags are different it will fail). It should be pretty easy to try this out: feature.extend link : header ; feature.extend link : source ; lib boost_system : error_code.cpp ; alias boost_system : : <link>header : : <define>BOOST_SYSTEM_HEADER_ONLY ; alias boost_system : error_code.cpp : <link>source ; In Christ, Steven Watanabe
Steven Watanabe wrote:
So the question is what should <link>header do for libraries that do not have a header-only mode?
Fall back to <link>static, I suppose.
Furthermore, after thinking about it a bit, I think that we might even have room for a fourth link type, <link>source, in response to which the library target would pass an appropriate <source> usage-requirement upwards. (<source>error_code.cpp in Boost.System's case.)
You don't need usage requirements for this, and it's not quite the right thing either, as it will continue to propagate up past any linking steps.
I think that it's exactly what I want (although I haven't yet tried it out.) If we take the example at which you hint later: exe x1 : x1.cpp boost_system : <cxxflags>-std=c++03 <define>FOO ; exe x2 : x2.cpp boost_system : <cxxflags>-std=c++11 <define>BAR ; a <source>error_code.cpp usage requirement will result in x1 and x2 getting their own copy of error_code.cpp, each compiled with the respective cxxflags and defines. Right?
AMDG On 01/22/2018 05:31 AM, Peter Dimov via Boost wrote:
Steven Watanabe wrote:
So the question is what should <link>header do for libraries that do not have a header-only mode?
Fall back to <link>static, I suppose.
Okay. So that means that a library with a header-only mode has to look like: lib boost_xxx : source.cpp ; alias boost_xxx : : <link>header : : <define>HEADER_ONLY ; # If you leave out the alias, <link>header becomes # equivalent to <link>static. It will still create # a separate build directory and propagate <link>header # to dependencies. and not: lib boost_xxx : source.cpp : : : <link>header:<define>HEADER_ONLY ; # This seems like the obvious extension of the # way <link>shared is handled, but it won't quite work. # If we allow this, and the library does not support # header-only, it will silently disappear, because # Boost.Build has no way to identify whether header-only # is actually supported or not.
Furthermore, after thinking about it a bit, I think that we might even > have room for a fourth link type, <link>source, in response to which the > library target would pass an appropriate <source> usage-requirement > upwards. (<source>error_code.cpp in Boost.System's case.)
You don't need usage requirements for this, and it's not quite the right thing either, as it will continue to propagate up past any linking steps.
I think that it's exactly what I want (although I haven't yet tried it out.) If we take the example at which you hint later:
exe x1 : x1.cpp boost_system : <cxxflags>-std=c++03 <define>FOO ; exe x2 : x2.cpp boost_system : <cxxflags>-std=c++11 <define>BAR ;
This will fail with a hard error. Duplicate name of actual target: bin/gcc-n.n.n/debug/error_code.o added properties: <cxxflags>-std=c++11 <define>BAR removed properties: <cxxflags>-std=c++03 <define>FOO (Note: I think that attempting to share object files between main targets is a mistake, but fixing it would require adding yet another directory to the target paths, even though it's usually not needed)
a <source>error_code.cpp usage requirement will result in x1 and x2 getting their own copy of error_code.cpp, each compiled with the respective cxxflags and defines. Right?
What I was talking about here is: # This also sees error_code.cpp as a source stage install : x1 : <location>stage/bin ; In Christ, Steven Watanabe
Steven Watanabe wrote:
On 01/22/2018 05:31 AM, Peter Dimov via Boost wrote:
Steven Watanabe wrote:
So the question is what should <link>header do for libraries that do not have a header-only mode?
Fall back to <link>static, I suppose.
Okay. So that means that a library with a header-only mode has to look like:
lib boost_xxx : source.cpp ; alias boost_xxx : : <link>header : : <define>HEADER_ONLY ; # If you leave out the alias, <link>header becomes # equivalent to <link>static. It will still create # a separate build directory and propagate <link>header # to dependencies.
It looks like this is exactly what we want. If we have the graph lib a ; lib b : a ; exe c : a b ; and `b` doesn't support header-only, we still want the two `a`s to both use header-only mode, to avoid ODR violations. I wonder whether <link>inline is not a better name though.
participants (2)
-
Peter Dimov
-
Steven Watanabe