From 758b3799a8afca1bcfcc80f1863d99417a8de1eb Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 5 Aug 2016 17:46:11 +0200 Subject: Initial take on build2-based build Only C++11 is supported with GCC 4.8 and up and VC 14 and up. This change also introduces the ODB_THREADS_CXX11 threading model. It is the default for the build2 build but can be disabled with a global ODB_THREADS_NONE define (global means that it should be in effect both when building and using the library). --- .gitignore | 6 +- build/bootstrap.build | 18 ++++++ build/export.build | 10 ++++ build/root.build | 14 +++++ buildfile | 9 +++ odb/buildfile | 125 ++++++++++++++++++++++++++++++++++++++++ odb/details/build2/config-vc.h | 24 ++++++++ odb/details/build2/config.h | 20 +++++++ odb/details/condition.hxx | 25 +++++++- odb/details/config.hxx | 6 +- odb/details/export.hxx | 39 +++++++++++++ odb/details/lock.hxx | 14 ++++- odb/details/mutex.hxx | 10 +++- odb/details/posix/condition.hxx | 4 +- odb/details/posix/condition.ixx | 2 +- odb/details/thread.cxx | 23 ++++++++ odb/details/thread.hxx | 42 ++++++++++++++ odb/details/tls.hxx | 40 ++++++++++++- odb/details/win32/condition.cxx | 2 +- odb/details/win32/condition.hxx | 4 +- tests/basics/buildfile | 7 +++ tests/basics/driver.cxx | 30 ++++++++++ tests/build/bootstrap.build | 9 +++ tests/build/root.build | 14 +++++ tests/buildfile | 7 +++ 25 files changed, 494 insertions(+), 10 deletions(-) create mode 100644 build/bootstrap.build create mode 100644 build/export.build create mode 100644 build/root.build create mode 100644 buildfile create mode 100644 odb/buildfile create mode 100644 odb/details/build2/config-vc.h create mode 100644 odb/details/build2/config.h create mode 100644 odb/details/thread.cxx create mode 100644 tests/basics/buildfile create mode 100644 tests/basics/driver.cxx create mode 100644 tests/build/bootstrap.build create mode 100644 tests/build/root.build create mode 100644 tests/buildfile diff --git a/.gitignore b/.gitignore index 3b9998d..cfb7ae0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ # Compiler/linker output. # +*.d *.o -*.o.d +*.obj *.so +*.dll *.a +*.lib + *.l *.l.cpp-options diff --git a/build/bootstrap.build b/build/bootstrap.build new file mode 100644 index 0000000..e0c79ce --- /dev/null +++ b/build/bootstrap.build @@ -0,0 +1,18 @@ +# file : build/bootstrap.build +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +project = libodb +version = 2.5.0-a8 +revision = 0 + +using build@0.4.0-a1 +using config +using dist +using test +using install + +dist.package = $project-$version + +if ($revision != 0) + dist.package += +$revision diff --git a/build/export.build b/build/export.build new file mode 100644 index 0000000..e6e2410 --- /dev/null +++ b/build/export.build @@ -0,0 +1,10 @@ +# file : build/export.build +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +$out_root/: +{ + include odb/ +} + +export $out_root/odb/lib{odb} diff --git a/build/root.build b/build/root.build new file mode 100644 index 0000000..44b2195 --- /dev/null +++ b/build/root.build @@ -0,0 +1,14 @@ +# file : build/root.build +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +using cxx + +hxx{*}: extension = hxx +ixx{*}: extension = ixx +txx{*}: extension = txx +cxx{*}: extension = cxx + +cxx.std = 11 + +tests/: install = false # Don't install tests. diff --git a/buildfile b/buildfile new file mode 100644 index 0000000..554e881 --- /dev/null +++ b/buildfile @@ -0,0 +1,9 @@ +# file : buildfile +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +d = odb/ tests/ +./: $d doc{GPLv2 INSTALL LICENSE NEWS README version} file{manifest} +include $d + +doc{INSTALL}@./: install = false diff --git a/odb/buildfile b/odb/buildfile new file mode 100644 index 0000000..e2e73f2 --- /dev/null +++ b/odb/buildfile @@ -0,0 +1,125 @@ +# file : odb/buildfile +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +lib{odb}: \ + {hxx }{ cache-traits } \ + {hxx cxx}{ callback } \ + {hxx ixx txx cxx}{ connection } \ + {hxx }{ container-traits } \ + {hxx }{ core } \ + {hxx ixx txx cxx}{ database } \ + {hxx }{ exception } \ + {hxx cxx}{ exceptions } \ + {hxx }{ forward } \ + {hxx }{ function-table } \ + {hxx }{ lazy-pointer-traits } \ + {hxx ixx txx }{ lazy-ptr } \ + {hxx ixx txx cxx}{ lazy-ptr-impl } \ + {hxx }{ nested-container } \ + {hxx txx }{ no-id-object-result } \ + {hxx }{ no-op-cache-traits } \ + {hxx }{ nullable } \ + {hxx }{ object-result } \ + {hxx }{ pointer-traits } \ + {hxx }{ polymorphic-info } \ + {hxx ixx txx }{ polymorphic-map } \ + {hxx txx }{ polymorphic-object-result } \ + {hxx }{ post } \ + {hxx }{ pre } \ + {hxx cxx}{ prepared-query } \ + {hxx ixx txx cxx}{ query-dynamic } \ + {hxx }{ query } \ + {hxx txx cxx}{ result } \ + {hxx cxx}{ schema-catalog } \ + {hxx }{ schema-catalog-impl } \ + {hxx }{ schema-version } \ + {hxx cxx}{ section } \ + {hxx ixx txx cxx}{ session } \ + {hxx txx }{ simple-object-result } \ + {hxx cxx}{ statement } \ + {hxx }{ statement-processing-common } \ + { cxx}{ statement-processing } \ + {hxx }{ std-array-traits } \ + {hxx }{ std-deque-traits } \ + {hxx }{ std-forward-list-traits } \ + {hxx }{ std-list-traits } \ + {hxx }{ std-map-traits } \ + {hxx }{ std-set-traits } \ + {hxx }{ std-unordered-map-traits } \ + {hxx }{ std-unordered-set-traits } \ + {hxx }{ std-vector-traits } \ + {hxx cxx}{ tracer } \ + {hxx }{ traits } \ + {hxx ixx cxx}{ transaction } \ + {hxx ixx }{ vector } \ + {hxx ixx cxx}{ vector-impl } \ + {hxx txx }{ vector-traits } \ + {hxx }{ version } \ + {hxx }{ view-image } \ + {hxx txx }{ view-result } \ + {hxx }{ wrapper-traits } \ + details/{hxx cxx}{ buffer } \ + details/{hxx }{ condition } \ + details/{hxx }{ config } \ + details/{hxx }{ c-string } \ + details/{hxx }{ exception } \ + details/{hxx }{ export } \ + details/{hxx ixx txx }{ function-wrapper } \ + details/{hxx }{ lock } \ + details/{hxx }{ mutex } \ + details/{hxx }{ shared-ptr-fwd } \ + details/{hxx }{ shared-ptr } \ + details/{hxx cxx}{ thread } \ + details/{hxx }{ tls } \ + details/{hxx }{ transfer-ptr } \ + details/{hxx }{ type-info } \ + details/{hxx }{ unique-ptr } \ + details/{hxx }{ unused } \ + details/{hxx }{ wrapper-p } \ + details/build2/{h }{ config } \ + details/build2/{h }{ config-vc } \ + details/meta/{hxx }{ answer } \ + details/meta/{hxx }{ class-p } \ + details/meta/{hxx }{ polymorphic-p } \ + details/meta/{hxx }{ remove-const } \ + details/meta/{hxx }{ remove-const-volatile } \ + details/meta/{hxx }{ remove-pointer } \ + details/meta/{hxx }{ remove-volatile } \ + details/meta/{hxx }{ static-assert } \ +details/shared-ptr/{hxx ixx txx cxx}{ base } \ +details/shared-ptr/{hxx }{ counter-type } \ +details/shared-ptr/{hxx }{ exception } \ + details/win32/{hxx }{ windows } + +cxx.poptions =+ -I$src_root -DLIBODB_BUILD2 +obja{*}: cxx.poptions += -DLIBODB_STATIC_BUILD +objs{*}: cxx.poptions += -DLIBODB_SHARED_BUILD + +lib{odb}: cxx.export.poptions = -I$src_root -DLIBODB_BUILD2 +liba{odb}: cxx.export.poptions += -DLIBODB_STATIC +libs{odb}: cxx.export.poptions += -DLIBODB_SHARED + +# Install into the odb/ subdirectory of, say, /usr/include/. +# +install.include = $install.include/odb +install.include.subdirs = true # Recreate subdirectories. + +if ($cxx.target.class != "windows") + details/win32/: install = false + +# We want these to be picked up even when LIBODB_BUILD2 is not defined. +# +details/build2/: +{ + if ($cxx.id == "msvc") + { + h{config}@./: install = false + h{config-vc}@./: install = $install.include/details + } + else + { + h{config}@./: install = $install.include/details + h{config-vc}@./: install = false + } +} diff --git a/odb/details/build2/config-vc.h b/odb/details/build2/config-vc.h new file mode 100644 index 0000000..4245931 --- /dev/null +++ b/odb/details/build2/config-vc.h @@ -0,0 +1,24 @@ +/* file : odb/details/build2/config-vc.h + * copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC + * license : GNU GPL v2; see accompanying LICENSE file + */ + +/* Configuration file for Windows/VC++ for the build2 build. */ + +#ifndef ODB_DETAILS_CONFIG_VC_H +#define ODB_DETAILS_CONFIG_VC_H + +/* Define LIBODB_BUILD2 for the installed case. */ +#ifndef LIBODB_BUILD2 +# define LIBODB_BUILD2 +#endif + +#ifndef ODB_THREADS_NONE +# if _MSC_VER >= 1900 +# define ODB_THREADS_CXX11 +# else +# error Unsupoprted MSVC version (no thread_local) +# endif +#endif + +#endif /* ODB_DETAILS_CONFIG_VC_H */ diff --git a/odb/details/build2/config.h b/odb/details/build2/config.h new file mode 100644 index 0000000..9393846 --- /dev/null +++ b/odb/details/build2/config.h @@ -0,0 +1,20 @@ +/* file : odb/details/build2/config.h + * copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC + * license : GNU GPL v2; see accompanying LICENSE file + */ + +/* Static configuration file for the build2 build. */ + +#ifndef ODB_DETAILS_CONFIG_H +#define ODB_DETAILS_CONFIG_H + +/* Define LIBODB_BUILD2 for the installed case. */ +#ifndef LIBODB_BUILD2 +# define LIBODB_BUILD2 +#endif + +#ifndef ODB_THREADS_NONE +# define ODB_THREADS_CXX11 +#endif + +#endif /* ODB_DETAILS_CONFIG_H */ diff --git a/odb/details/condition.hxx b/odb/details/condition.hxx index cf22a70..1baa81b 100644 --- a/odb/details/condition.hxx +++ b/odb/details/condition.hxx @@ -17,6 +17,8 @@ namespace odb namespace details { class mutex; + class lock; + class LIBODB_EXPORT condition { public: @@ -26,7 +28,7 @@ namespace odb signal () {} void - wait () {} + wait (lock&) {} private: condition (const condition&); @@ -35,6 +37,27 @@ namespace odb } } +#elif defined(ODB_THREADS_CXX11) +# include +# include + +namespace odb +{ + namespace details + { + class mutex; + + class condition: public std::condition_variable + { + public: + condition (mutex&) {} + + void + signal () {notify_one ();} + }; + } +} + #elif defined(ODB_THREADS_POSIX) #include #elif defined(ODB_THREADS_WIN32) diff --git a/odb/details/config.hxx b/odb/details/config.hxx index 36875fa..91efcea 100644 --- a/odb/details/config.hxx +++ b/odb/details/config.hxx @@ -65,7 +65,11 @@ # define ODB_THREADS_NONE # define LIBODB_STATIC_LIB #elif defined(LIBODB_BUILD2) -# include +# if defined(_MSC_VER) +# include +# else +# include +# endif #elif defined(_MSC_VER) # include #else diff --git a/odb/details/export.hxx b/odb/details/export.hxx index 8b36cae..51d6849 100644 --- a/odb/details/export.hxx +++ b/odb/details/export.hxx @@ -9,6 +9,43 @@ #include +// Normally we don't export class templates (but do complete specializations), +// inline functions, and classes with only inline member functions. Exporting +// classes that inherit from non-exported/imported bases (e.g., std::string) +// will end up badly. The only known workarounds are to not inherit or to not +// export. Also, MinGW GCC doesn't like seeing non-exported function being +// used before their inline definition. The workaround is to reorder code. In +// the end it's all trial and error. + +#ifdef LIBODB_BUILD2 + +#if defined(LIBODB_STATIC) // Using static. +# define LIBODB_EXPORT +#elif defined(LIBODB_STATIC_BUILD) // Building static. +# define LIBODB_EXPORT +#elif defined(LIBODB_SHARED) // Using shared. +# ifdef _WIN32 +# define LIBODB_EXPORT __declspec(dllimport) +# else +# define LIBODB_EXPORT +# endif +#elif defined(LIBODB_SHARED_BUILD) // Building shared. +# ifdef _WIN32 +# define LIBODB_EXPORT __declspec(dllexport) +# else +# define LIBODB_EXPORT +# endif +#else +// If none of the above macros are defined, then we assume we are being used +// by some third-party build system that cannot/doesn't signal the library +// type. Note that this fallback works for both static and shared but in case +// of shared will be sub-optimal compared to having dllimport. +// +# define LIBODB_EXPORT // Using static or shared. +#endif + +#else // LIBODB_BUILD2 + #ifdef LIBODB_STATIC_LIB # define LIBODB_EXPORT #else @@ -35,6 +72,8 @@ # endif #endif +#endif // LIBODB_BUILD2 + #include #endif // ODB_DETAILS_EXPORT_HXX diff --git a/odb/details/lock.hxx b/odb/details/lock.hxx index 26ab4a8..28f3ede 100644 --- a/odb/details/lock.hxx +++ b/odb/details/lock.hxx @@ -10,12 +10,23 @@ #include #include +#ifdef ODB_THREADS_CXX11 +# include namespace odb { namespace details { - struct LIBODB_EXPORT lock + using lock = std::unique_lock; + } +} +#else +namespace odb +{ + namespace details + { + class LIBODB_EXPORT lock { + public: lock (mutex& m) : mutex_ (&m) { @@ -43,6 +54,7 @@ namespace odb }; } } +#endif #include diff --git a/odb/details/mutex.hxx b/odb/details/mutex.hxx index 6bdfd21..2508f68 100644 --- a/odb/details/mutex.hxx +++ b/odb/details/mutex.hxx @@ -33,7 +33,15 @@ namespace odb }; } } - +#elif defined(ODB_THREADS_CXX11) +# include +namespace odb +{ + namespace details + { + using std::mutex; + } +} #elif defined(ODB_THREADS_POSIX) #include #elif defined(ODB_THREADS_WIN32) diff --git a/odb/details/posix/condition.hxx b/odb/details/posix/condition.hxx index 6a86741..7a9dd2d 100644 --- a/odb/details/posix/condition.hxx +++ b/odb/details/posix/condition.hxx @@ -16,6 +16,8 @@ namespace odb { namespace details { + class lock; + class LIBODB_EXPORT condition { public: @@ -26,7 +28,7 @@ namespace odb signal (); void - wait (); + wait (lock&); private: condition (const condition&); diff --git a/odb/details/posix/condition.ixx b/odb/details/posix/condition.ixx index 9ebd60e..0aa504b 100644 --- a/odb/details/posix/condition.ixx +++ b/odb/details/posix/condition.ixx @@ -30,7 +30,7 @@ namespace odb } inline void condition:: - wait () + wait (lock&) { if (int e = pthread_cond_wait (&cond_, &mutex_.mutex_)) throw posix_exception (e); diff --git a/odb/details/thread.cxx b/odb/details/thread.cxx new file mode 100644 index 0000000..d00f498 --- /dev/null +++ b/odb/details/thread.cxx @@ -0,0 +1,23 @@ +// file : odb/details/thread.cxx +// copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +// We might be compiled with ODB_THREADS_NONE. +// +#ifdef ODB_THREADS_CXX11 + +namespace odb +{ + namespace details + { + void thread:: + thunk (void* (*f) (void*), void* a, std::promise p) + { + p.set_value (f (a)); + } + } +} + +#endif diff --git a/odb/details/thread.hxx b/odb/details/thread.hxx index 858263d..79c1b62 100644 --- a/odb/details/thread.hxx +++ b/odb/details/thread.hxx @@ -8,9 +8,51 @@ #include #include +#include #ifdef ODB_THREADS_NONE # error no thread support available +#elif defined(ODB_THREADS_CXX11) +# include +# include +# include // move() + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT thread + { + public: + thread (void* (*thread_func) (void*), void* arg = 0) + { + std::promise p; + f_ = p.get_future (); + t_ = std::thread (thunk, thread_func, arg, std::move (p)); + } + + void* + join () + { + f_.wait (); + t_.join (); + return f_.get (); + } + + thread (const thread&) = delete; + thread& operator= (const thread&) = delete; + + private: + static void + thunk (void* (*) (void*), void*, std::promise); + + private: + std::thread t_; + std::future f_; + }; + } +} + #elif defined(ODB_THREADS_POSIX) #include #elif defined(ODB_THREADS_WIN32) diff --git a/odb/details/tls.hxx b/odb/details/tls.hxx index 684823a..aae148e 100644 --- a/odb/details/tls.hxx +++ b/odb/details/tls.hxx @@ -30,7 +30,45 @@ namespace odb // template inline void - tls_free (T& x) + tls_free (T&) + { + } + + template + inline T* + tls_get (T* p) + { + return p; + } + + template + inline void + tls_set (T*& rp, T1* p) + { + rp = p; + } + } +} + +#elif defined(ODB_THREADS_CXX11) + +# define ODB_TLS_POINTER(type) thread_local type* +# define ODB_TLS_OBJECT(type) thread_local type + +namespace odb +{ + namespace details + { + template + inline T& + tls_get (T& x) + { + return x; + } + + template + inline void + tls_free (T&) { } diff --git a/odb/details/win32/condition.cxx b/odb/details/win32/condition.cxx index 6e22823..05402ef 100644 --- a/odb/details/win32/condition.cxx +++ b/odb/details/win32/condition.cxx @@ -28,7 +28,7 @@ namespace odb } void condition:: - wait () + wait (lock&) { // When we enter this functions the mutex is locked. When we // return from this function the mutex must be locked. diff --git a/odb/details/win32/condition.hxx b/odb/details/win32/condition.hxx index 56eebf6..be06557 100644 --- a/odb/details/win32/condition.hxx +++ b/odb/details/win32/condition.hxx @@ -18,6 +18,8 @@ namespace odb { namespace details { + class lock; + class LIBODB_EXPORT condition { public: @@ -28,7 +30,7 @@ namespace odb signal (); void - wait (); + wait (lock&); private: condition (const condition&); diff --git a/tests/basics/buildfile b/tests/basics/buildfile new file mode 100644 index 0000000..a871a6e --- /dev/null +++ b/tests/basics/buildfile @@ -0,0 +1,7 @@ +# file : tests/basics/buildfile +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +import libs = libodb%lib{odb} + +exe{driver}: cxx{driver} $libs diff --git a/tests/basics/driver.cxx b/tests/basics/driver.cxx new file mode 100644 index 0000000..8994429 --- /dev/null +++ b/tests/basics/driver.cxx @@ -0,0 +1,30 @@ +// file : tests/basics/driver.cxx +// copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +// Basic test to make sure the library is usable. Functionality testing +// is done in the odb-tests package. + +#include + +#include +#include + +using namespace odb; + +int +main () +{ + // Transaction. + // + { + assert (!transaction::has_current ()); + + try + { + transaction::current (); + assert(false); + } + catch (const not_in_transaction&) {} + } +} diff --git a/tests/build/bootstrap.build b/tests/build/bootstrap.build new file mode 100644 index 0000000..2f8aad2 --- /dev/null +++ b/tests/build/bootstrap.build @@ -0,0 +1,9 @@ +# file : tests/build/bootstrap.build +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +project = # Unnamed subproject. + +using config +using dist +using test diff --git a/tests/build/root.build b/tests/build/root.build new file mode 100644 index 0000000..c731d60 --- /dev/null +++ b/tests/build/root.build @@ -0,0 +1,14 @@ +# file : tests/build/root.build +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +using cxx + +hxx{*}: extension = hxx +cxx{*}: extension = cxx + +cxx.std = 11 + +# Every exe{} in this subproject is by default a test. +# +exe{*}: test = true diff --git a/tests/buildfile b/tests/buildfile new file mode 100644 index 0000000..0341b61 --- /dev/null +++ b/tests/buildfile @@ -0,0 +1,7 @@ +# file : tests/buildfile +# copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +d = basics/ +./: $d +include $d -- cgit v1.1