diff --git a/TODO.txt b/TODO.txt index c68bfe6..22ece68 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,3 +1,17 @@ -* Shall I replace boost_contract_link with Boost's linkage build option? I think yes, do what chrono and thread do (but are those built ad dll by default?) +* How do I make Boost build script automatically copy //libs/contract/include/boost/contract_macro.hpp to //boost/contract_macro.hpp (this is automatically done for //boost/contract/ and //boost/contract.hpp, but not for //boost/contract_macro.hpp)? Maybe ask Boost... + + $ bjam + ... + mklink-or-dir ..\..\..\boost\contract + Junction created for ..\..\..\boost\contract <<===>> ..\include\boost\contract + ...patience... + link.hardlink ..\..\..\boost\contract.hpp + Hardlink created for ..\..\..\boost\contract.hpp <<===>> ..\include\boost\contract.hpp + ... + +* Make sure build/, example/, and test/ all compile even if include/ is removed after symlink are created to //boost/... +* Recompile all examples/tests with all compilers, boost_contract_no, link, boost_contract_header_only, etc. (after fully integrated w/ Boost build system) +* Update the docs (especially, the Getting Started section) to fit within Boost (how about .pdf doc generation? what do I need to do for that?) +* Inspect chrono/build/Jamfile.v2 and chrono/doc/Jamfile.v2 closely to see if some of that configuration should be adopted fro Boost.Contract build and docs. diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 723b9a5..6797913 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -4,14 +4,22 @@ # file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). # See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html -import boost_contract_build ; - -lib boost_contract : ../src/contract.cpp : - shared - /boost/system//boost_system +project boost/contract + : source-location ../src + : requirements + shared:BOOST_CONTRACT_DYN_LINK + static:BOOST_CONTRACT_STATIC_LINK + single:BOOST_CONTRACT_DISABLE_THREADS + : usage-requirements # Independent from requirements above (need to repeat). + shared:BOOST_CONTRACT_DYN_LINK + static:BOOST_CONTRACT_STATIC_LINK + single:BOOST_CONTRACT_DISABLE_THREADS + /boost/system//boost_system ; -lib boost_contract : ../src/contract.cpp : static ; - -# Build nothing for boost_contract_link=header (ignore Bjam warnings). +lib boost_contract : contract.cpp : + shared + /boost/system//boost_system +; +lib boost_contract : contract.cpp : static ; diff --git a/build/boost_contract_build.jam b/build/boost_contract_build.jam index 05593de..6579364 100644 --- a/build/boost_contract_build.jam +++ b/build/boost_contract_build.jam @@ -4,16 +4,52 @@ # file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). # See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html +# Usage: bjam [OPTION]... DIR[-CPP_FILE_NAME] +# Build and run Boost.Contract tests and examples. +# +# Options: +# boost_contract_header_only=no,yes if yes, do not build Boost.Contract +# library, use it as header-only instead +# (by default, no) +# link=shared,static build Boost.Contract library as shared or static, has no +# effect if boost_contract_header_only=yes (by default, +# shared) +# boost_contract_no= turn contract checking off (by default, all_yes) +# all_yes,entryinv,pre,exitinv,post,except,check,entryinv_pre,entryinv_exitinv,entryinv_post,entryinv_except,entryinv_check,pre_exitinv,pre_post,pre_except,pre_check,exitinv_post,exitinv_except,exitinv_check,post_except,post_check,except_check,entryinv_pre_exitinv,entryinv_pre_post,entryinv_pre_except,entryinv_pre_check,entryinv_exitinv_post,entryinv_exitinv_except,entryinv_exitinv_check,entryinv_post_except,entryinv_post_check,entryinv_except_check,pre_exitinv_post,pre_exitinv_except,pre_exitinv_check,pre_post_except,pre_post_check,pre_except_check,exitinv_post_except,exitinv_post_check,exitinv_except_check,post_except_check,entryinv_pre_exitinv_post,entryinv_pre_exitinv_except,entryinv_pre_exitinv_check,entryinv_pre_post_except,entryinv_pre_post_check,entryinv_pre_except_check,entryinv_exitinv_post_except,entryinv_exitinv_post_check,entryinv_exitinv_except_check,entryinv_post_except_check,pre_exitinv_post_except,pre_exitinv_post_check,pre_exitinv_except_check,pre_post_except_check,exitinv_post_except_check,entryinv_pre_exitinv_post_except,entryinv_pre_exitinv_post_check,entryinv_pre_exitinv_except_check,entryinv_pre_post_except_check,entryinv_exitinv_post_except_check,pre_exitinv_post_except_check,entryinv_pre_exitinv_post_except_check +# +# Examples (on Linux-based bash): +# Build just "test/public_function/smoke.cpp" and "example/introduction.cpp": +# [test]$ bjam public_function-smoke +# [example]$ bjam features-introduction +# Build all tests with all linkages (incl header-only) on multiple compilers: +# [test]$ bjam -q toolset=msvc,gcc,clang link=static,header +# [test]$ bjam -q toolset=msvc,gcc,clang boost_contract_header_only=yes +# Build all tests with no postconditions and exception guarantees first, and +# then again with no class invariants at exit: +# [test]$ time bjam -q boost_contract_no=post_except,exitinv + import boost_contract_no ; -import testing ; import feature ; +import testing ; + +# Iff "no", link to boost_contract (else, no lib build so don't link to it). +feature.feature boost_contract_header_only : no yes : + composite propagated link-incompatible ; + +# This is boost_contract_no=all_yes,pre,pre_post,... +feature.feature boost_contract_no : all_yes [ boost_contract_no.conds ] : + composite propagated link-incompatible ; +for local cond in [ boost_contract_no.conds ] { + feature.compose $(cond) : + [ boost_contract_no.defs_$(cond) ] ; +} module boost_contract_build { rule subdir-compile-fail ( subdir : cpp_fname : requirements * ) { compile-fail $(subdir)/$(cpp_fname).cpp : - shared:../build//boost_contract - static:../build//boost_contract + no:../build//boost_contract + yes:/boost/system//boost_system $(subdir) $(requirements) : @@ -23,9 +59,8 @@ rule subdir-compile-fail ( subdir : cpp_fname : requirements * ) { rule subdir-run ( subdir : cpp_fname : requirements * ) { run $(subdir)/$(cpp_fname).cpp : : : - shared:../build//boost_contract - static:../build//boost_contract - /boost/system//boost_system + no:../build//boost_contract + yes:/boost/system//boost_system $(subdir) $(requirements) : @@ -35,8 +70,8 @@ rule subdir-run ( subdir : cpp_fname : requirements * ) { rule subdir-lib ( subdir : cpp_fname : requirements * ) { lib $(subdir)-$(cpp_fname) : $(subdir)/$(cpp_fname).cpp : - shared:../build//boost_contract - static:../build//boost_contract + no:../build//boost_contract + yes:/boost/system//boost_system $(subdir) $(requirements) ; @@ -44,21 +79,3 @@ rule subdir-lib ( subdir : cpp_fname : requirements * ) { } # module -feature.feature boost_contract_link : shared static header : - composite propagated link-incompatible ; -feature.compose shared : shared ; -feature.compose static : - static - BOOST_CONTRACT_STATIC_LINK -; -feature.compose header : - BOOST_CONTRACT_HEADER_ONLY -; - -feature.feature boost_contract_no : all_yes [ boost_contract_no.conds ] : - composite propagated link-incompatible ; -for local cond in [ boost_contract_no.conds ] { - feature.compose $(cond) : - [ boost_contract_no.defs_$(cond) ] ; -} - diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index c538034..82a64d7 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -51,13 +51,13 @@ doxygen reference xml contract : main.qbk : reference ; -boostbook doc : contract +boostbook boostdoc : contract : html boost.defaults=Boost - boost.root=../../ - admon.graphics.path=../../doc/src/images/ - html.stylesheet=../../doc/src/boostbook.css + boost.root=../../../.. + #admon.graphics.path=../../doc/src/images/ + #html.stylesheet=../../doc/src/boostbook.css toc.max.depth=1 ; diff --git a/include/boost/contract/core/config.hpp b/include/boost/contract/core/config.hpp index 7d0d96f..bdb4263 100644 --- a/include/boost/contract/core/config.hpp +++ b/include/boost/contract/core/config.hpp @@ -18,14 +18,49 @@ Configure this library compile-time and run-time behaviours. #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN /** - Define this macro to compile this library as a static (instead of shared) - library (undefined by default). + Define this macro to compile this library as a shared library (recommended). + + If this macro is defined, this library is compiled so it can be linked + dynamically to user code. + This library will automatically define this macro if the Boost libraries + are being built as dynamic libraries. + + This library will define this macro unless users define + @RefMacro{BOOST_CONTRACT_STATIC_LINK} or + @RefMacro{BOOST_CONTRACT_HEADER_ONLY} (this macro is not a configuration + macro and this library will generate a compile-time error if users try to + define it directly). + Programmers should rarely, if ever, need to use this macro directly. + + @warning In general this library will correctly check contracts at + run-time only when compiled as a shared library, unless user + code checks contracts in a single program unit (e.g., a single + program with only statically linked libraries that check + contracts). + Therefore, it is recommended to build and use this library as + a dynamic library by defining this macro (or by building all + Boost libraries as dynamic libraries). + + @see @RefSect{getting_started.install_and_compile, Install and Compile} + */ + #define BOOST_CONTRACT_DYN_LINK +#elif defined(BOOST_CONTRACT_DYN_LINK) && defined(BOOST_CONTRACT_STATIC_LINK) + #error "DYN_LINK defined with STATIC_LINK" +#endif + +#ifdef BOOST_CONTRACT_DETAIL_DOXYGEN + /** + Define this macro to compile this library as a static library (not + recommended). If this macro is defined, this library is compiled so it can be linked - statically to user code (and not as a shared library as by default). + statically to user code. + This library will automatically define this macro if the Boost libraries + are being built as static libraries. @warning This library is not guaranteed to always work correctly at - run-time when this macro is defined. + run-time when this macro is defined (define + @RefMacro{BOOST_CONTRACT_DYN_LINK instead). However, this macro can be defined and this library can be safely used as a static library for user code that checks contracts in a single program unit (e.g., a single program with @@ -34,40 +69,8 @@ Configure this library compile-time and run-time behaviours. @see @RefSect{getting_started.install_and_compile, Install and Compile} */ #define BOOST_CONTRACT_STATIC_LINK -#elif defined(BOOST_CONTRACT_STATIC_LINK) && \ - ( \ - defined(BOOST_CONTRACT_HEADER_ONLY) || \ - defined(BOOST_ALL_DYN_LINK) \ - ) - #error "STATIC_LINK defined with HEADER_ONLY and/or ALL_DYN_LINK" -#endif - -#ifdef BOOST_CONTRACT_DETAIL_DOXYGEN - /** - Define this macro to use this library as a header-only library (undefined by - default). - - If this macro is defined, this library does not have to be compiled - separately from user code. - This library headers are simply included and compiled as part of the user - program. - - @warning This library is not guaranteed to always work correctly at - run-time when this macro is defined. - However, this macro can be defined and this library can be - safely used as a header-only library for user code that checks - contracts in a single program unit (e.g., a single program with - only statically linked libraries that check contracts). - - @see @RefSect{getting_started.install_and_compile, Install and Compile} - */ - #define BOOST_CONTRACT_HEADER_ONLY -#elif defined(BOOST_CONTRACT_HEADER_ONLY) && \ - ( \ - defined(BOOST_CONTRACT_STATIC_LINK) || \ - defined(BOOST_ALL_DYN_LINK) \ - ) - #error "HEADER_ONLY defined with STATIC_LINK and/or ALL_DYN_LINK" +#elif defined(BOOST_CONTRACT_STATIC_LINK) && defined(BOOST_CONTRACT_DYN_LINK) + #error "STATIC_LINK defined with DYN_LINK" #endif #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN @@ -194,15 +197,15 @@ Configure this library compile-time and run-time behaviours. /** Code block to execute if contracts are not assigned to a @RefClass{boost::contract::check} variable (undefined by default and - executes @c assert(false)). + executes @c BOOST_ASSERT(false)). In general, there is a logic error in the program when contracts are not assigned to a local variable of type @RefClass{boost::contract::check}. Therefore, by default (i.e., when this macro is not defined) this library - calls assert(false) in those cases. + calls BOOST_ASSERT(false) in those cases. If this macro is defined, this library will execute the code expanded by the - macro instead of calling @c assert(false) (if programmers prefer to throw an - exception, etc.). + macro instead of calling @c BOOST_ASSERT(false) (if programmers prefer to + throw an exception, etc.). This macro can be defined to be any block of code (including @c {} to generate no error), for example (on GCC): @@ -679,35 +682,33 @@ Configure this library compile-time and run-time behaviours. #define BOOST_CONTRACT_NO_ALL #endif -#ifdef BOOST_CONTRACT_DYN_LINK - #error "define STATIC_LINK or HEADER_ONLY instead" -#elif defined(BOOST_CONTRACT_DETAIL_DOXYGEN) || \ - defined(BOOST_ALL_DYN_LINK) || \ - ( \ - !defined(BOOST_CONTRACT_STATIC_LINK) && \ - !defined(BOOST_CONTRACT_HEADER_ONLY) \ - ) +#ifdef BOOST_CONTRACT_HEADER_ONLY + #error "leave DYN_LINK and STATIC_LINK undefined instead" +#elif !defined(BOOST_CONTRACT_DYN_LINK) && \ + !defined(BOOST_CONTRACT_STATIC_LINK) /** - Automatically defined when this library is being compiled as a shared - library (defined by default). - - This library will define this macro unless users define - @RefMacro{BOOST_CONTRACT_STATIC_LINK} or - @RefMacro{BOOST_CONTRACT_HEADER_ONLY} (this macro is not a configuration - macro and this library will generate a compile-time error if users try to - define it directly). - Programmers should rarely, if ever, need to use this macro directly. + Automatically defined by this library when it is being used as a header-only + library (not recommended). - @warning In general this library will correctly check contracts at - run-time only when compiled as a shared library (i.e., this - macro will be automatically defined by default), unless user - code checks contracts in a single program unit (e.g., a single - program with only statically linked libraries that check - contracts). + This library will define this macro when users do not define + @RefMacro{BOOST_CONTRACT_DYN_LINK} and + @RefMacro{BOOST_CONTRACT_STATIC_LINK}. + If this macro is defined, this library does not have to be compiled + separately from user code. + This library headers are simply included and compiled as part of the user + program. + + @warning This library is not guaranteed to always work correctly at + run-time when this macro is defined (define + @RefMacro{BOOST_CONTRACT_DYN_LINK instead). + However, this macro can be defined and this library can be + safely used as a header-only library for user code that checks + contracts in a single program unit (e.g., a single program with + only statically linked libraries that check contracts). @see @RefSect{getting_started.install_and_compile, Install and Compile} */ - #define BOOST_CONTRACT_DYN_LINK + #define BOOST_CONTRACT_HEADER_ONLY #endif #endif // #include guard diff --git a/include/boost/contract/core/exception.hpp b/include/boost/contract/core/exception.hpp index 7fd355e..76616b2 100644 --- a/include/boost/contract/core/exception.hpp +++ b/include/boost/contract/core/exception.hpp @@ -12,6 +12,7 @@ Handle contract assertion failures. */ // IMPORTANT: Included by contract_macro.hpp so trivial headers only. +#include #include // No compile-time overhead. #include #include @@ -421,7 +422,7 @@ namespace exception_ { } } // namespace /** @cond */ -#if BOOST_CONTRACT_HEADER_ONLY +#ifdef BOOST_CONTRACT_HEADER_ONLY // NOTE: This header must be included in the middle of this file (because // its impl depends on both from and assert_failure types). This is not // ideal, but it is better than splitting this file into multiple diff --git a/include/boost/contract/detail/checking.hpp b/include/boost/contract/detail/checking.hpp index c436505..9d0ac44 100644 --- a/include/boost/contract/detail/checking.hpp +++ b/include/boost/contract/detail/checking.hpp @@ -68,7 +68,7 @@ private: } } } // namespace -#if BOOST_CONTRACT_HEADER_ONLY +#ifdef BOOST_CONTRACT_HEADER_ONLY #include #endif diff --git a/include/boost/contract/detail/condition/cond_base.hpp b/include/boost/contract/detail/condition/cond_base.hpp index b55afb9..3a8f109 100644 --- a/include/boost/contract/detail/condition/cond_base.hpp +++ b/include/boost/contract/detail/condition/cond_base.hpp @@ -24,10 +24,10 @@ #include #endif #include -#include #ifndef BOOST_CONTRACT_ON_MISSING_CHECK_DECL - #include + #include #endif +#include namespace boost { namespace contract { namespace detail { @@ -80,7 +80,7 @@ protected: #else // Cannot use a macro instead of this ERROR_... directly here // because assert will not expand it in the error message. - assert(BOOST_CONTRACT_ERROR_missing_check_object_declaration); + BOOST_ASSERT(BOOST_CONTRACT_ERROR_missing_check_object_declaration); #endif } diff --git a/include/boost/contract/detail/config.hpp b/include/boost/contract/detail/config.hpp index 3163499..6027cd6 100644 --- a/include/boost/contract/detail/config.hpp +++ b/include/boost/contract/detail/config.hpp @@ -12,7 +12,7 @@ // Export symbols when compiling as shared lib (for internal use only). // BOOST_CONTRACT_DETAIL_SOURCE -// Turn off assert(...) in lib's implementation. +// Turn off BOOST_ASSERT(...) in lib's implementation (always on by default). // BOOST_CONTRACT_DETAIL_NDEBUG #ifndef BOOST_CONTRACT_DETAIL_NAME_INFIX diff --git a/include/boost/contract/detail/debug.hpp b/include/boost/contract/detail/debug.hpp index 6215403..5a278ea 100644 --- a/include/boost/contract/detail/debug.hpp +++ b/include/boost/contract/detail/debug.hpp @@ -11,9 +11,9 @@ #ifdef BOOST_CONTRACT_DETAIL_NDEBUG #define BOOST_CONTRACT_DETAIL_DEBUG(cond) /* nothing */ #else - #include - // Extra parenthesis around assert because that is also a macro. - #define BOOST_CONTRACT_DETAIL_DEBUG(cond) (assert(cond)) + #include + // Extra parenthesis around BOOST_ASSERT to be safe because its is a macro. + #define BOOST_CONTRACT_DETAIL_DEBUG(cond) (BOOST_ASSERT(cond)) #endif #endif // #include guard diff --git a/include/boost/contract/detail/declspec.hpp b/include/boost/contract/detail/declspec.hpp index 9264c4b..74347c6 100644 --- a/include/boost/contract/detail/declspec.hpp +++ b/include/boost/contract/detail/declspec.hpp @@ -15,7 +15,10 @@ // IMPORTANT: In general, this library should always and only be compiled and // used as a shared library. Otherwise, lib's state won't be shared among -// different user programs and user libraries. +// different user programs and user libraries. However, this library can be +// safely compiled and used as a static or header-only library only when it is +// being used by a single program unit (e.g., a single program with only +// statically linked libraries that check contracts). #ifdef BOOST_CONTRACT_DYN_LINK #ifdef BOOST_CONTRACT_DETAIL_SOURCE #define BOOST_CONTRACT_DETAIL_DECLSPEC BOOST_SYMBOL_EXPORT diff --git a/src/contract.cpp b/src/contract.cpp index a1a1dc7..1f2eebf 100644 --- a/src/contract.cpp +++ b/src/contract.cpp @@ -4,6 +4,7 @@ // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html +#include #ifndef BOOST_CONTRACT_HEADER_ONLY // This is not an #include guard. // For shared (default) and static lib only. #define BOOST_CONTRACT_DETAIL_SOURCE diff --git a/test/disable/lib_a.cpp b/test/disable/lib_a.cpp index 465c8e8..df027ff 100644 --- a/test/disable/lib_a.cpp +++ b/test/disable/lib_a.cpp @@ -6,6 +6,7 @@ #define BOOST_CONTRACT_TEST_LIB_A_SOURCE #include "lib_a.hpp" +#include #ifndef BOOST_CONTRACT_HEADER_ONLY #include "lib_a_inlined.hpp" #endif diff --git a/test/disable/lib_a.hpp b/test/disable/lib_a.hpp index 05b24ff..4623fa7 100644 --- a/test/disable/lib_a.hpp +++ b/test/disable/lib_a.hpp @@ -8,6 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html #include "../detail/counter.hpp" +#include #include #include