diff options
Diffstat (limited to 'libbuild2/bin/target.cxx')
-rw-r--r-- | libbuild2/bin/target.cxx | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/libbuild2/bin/target.cxx b/libbuild2/bin/target.cxx new file mode 100644 index 0000000..dd8a947 --- /dev/null +++ b/libbuild2/bin/target.cxx @@ -0,0 +1,474 @@ +// file : libbuild2/bin/target.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <libbuild2/bin/target.hxx> + +#include <libbuild2/context.hxx> + +using namespace std; + +namespace build2 +{ + namespace bin + { + const target_type objx::static_type + { + "objx", + &file::static_type, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + const target_type bmix::static_type + { + "bmix", + &file::static_type, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + const target_type hbmix::static_type + { + "hbmix", + &bmix::static_type, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + const target_type libx::static_type + { + "libx", + &mtime_target::static_type, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + const target_type libux::static_type + { + "libux", + &file::static_type, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + // Note that we link groups during the load phase since this is often + // relied upon when setting target-specific variables (e.g., we may set a + // common value for lib{} and then append liba/libs-specific values to + // it). While sure inelegant, this is MT-safe since during load we are + // running serial. For the members it is also safe to set the group during + // creation. + + // obj*{} and [h]bmi*{} member factory. + // + template <typename M, typename G> + static target* + m_factory (context& ctx, + const target_type&, dir_path dir, dir_path out, string n) + { + const G* g (ctx.targets.find<G> (dir, out, n)); + + M* m (new M (ctx, move (dir), move (out), move (n))); + m->group = g; + + return m; + } + + const target_type obje::static_type + { + "obje", + &objx::static_type, + &m_factory<obje, obj>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type bmie::static_type + { + "bmie", + &bmix::static_type, + &m_factory<bmie, bmi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type hbmie::static_type + { + "hbmie", + &hbmix::static_type, + &m_factory<hbmie, hbmi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type obja::static_type + { + "obja", + &objx::static_type, + &m_factory<obja, obj>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type bmia::static_type + { + "bmia", + &bmix::static_type, + &m_factory<bmia, bmi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type hbmia::static_type + { + "hbmia", + &hbmix::static_type, + &m_factory<hbmia, hbmi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type objs::static_type + { + "objs", + &objx::static_type, + &m_factory<objs, obj>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type bmis::static_type + { + "bmis", + &bmix::static_type, + &m_factory<bmis, bmi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type hbmis::static_type + { + "hbmis", + &hbmix::static_type, + &m_factory<hbmis, hbmi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type libue::static_type + { + "libue", + &libux::static_type, + &target_factory<libue>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type libua::static_type + { + "libua", + &libux::static_type, + &m_factory<libua, libul>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + const target_type libus::static_type + { + "libus", + &libux::static_type, + &m_factory<libus, libul>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &target_search, // Note: not _file(); don't look for an existing file. + false + }; + + // obj{}, [h]bmi{}, and libu{} group factory. + // + template <typename G, typename E, typename A, typename S> + static target* + g_factory (context& ctx, + const target_type&, dir_path dir, dir_path out, string n) + { + // Casts are MT-aware (during serial load). + // + E* e (ctx.phase == run_phase::load + ? const_cast<E*> (ctx.targets.find<E> (dir, out, n)) + : nullptr); + A* a (ctx.phase == run_phase::load + ? const_cast<A*> (ctx.targets.find<A> (dir, out, n)) + : nullptr); + S* s (ctx.phase == run_phase::load + ? const_cast<S*> (ctx.targets.find<S> (dir, out, n)) + : nullptr); + + G* g (new G (ctx, move (dir), move (out), move (n))); + + if (e != nullptr) e->group = g; + if (a != nullptr) a->group = g; + if (s != nullptr) s->group = g; + + return g; + } + + const target_type obj::static_type + { + "obj", + &target::static_type, + &g_factory<obj, obje, obja, objs>, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + const target_type bmi::static_type + { + "bmi", + &target::static_type, + &g_factory<bmi, bmie, bmia, bmis>, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + const target_type hbmi::static_type + { + "hbmi", + &target::static_type, + &g_factory<hbmi, hbmie, hbmia, hbmis>, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + // The same as g_factory() but without E. + // + static target* + libul_factory (context& ctx, + const target_type&, dir_path dir, dir_path out, string n) + { + libua* a (ctx.phase == run_phase::load + ? const_cast<libua*> (ctx.targets.find<libua> (dir, out, n)) + : nullptr); + libus* s (ctx.phase == run_phase::load + ? const_cast<libus*> (ctx.targets.find<libus> (dir, out, n)) + : nullptr); + + libul* g (new libul (ctx, move (dir), move (out), move (n))); + + if (a != nullptr) a->group = g; + if (s != nullptr) s->group = g; + + return g; + } + + const target_type libul::static_type + { + "libul", + &libx::static_type, + &libul_factory, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false + }; + + // What extensions should we use? At the outset, this is platform- + // dependent. And if we consider cross-compilation, is it build or + // host-dependent? Feels like it should be host-dependent so that + // we can copy things between cross and native environments. So + // these will have to be determined based on what we are building. + // As if this is not complicated enough, the bin module doesn't + // know anything about building. So perhaps the extension should + // come from a variable that is set not by bin but by the module + // whose rule matched the target (e.g., cxx::link). + // + const target_type liba::static_type + { + "liba", + &file::static_type, + &m_factory<liba, lib>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &file_search, + false + }; + + const target_type libs::static_type + { + "libs", + &file::static_type, + &m_factory<libs, lib>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &file_search, + false + }; + + // lib + // + group_view lib:: + group_members (action) const + { + static_assert (sizeof (lib_members) == sizeof (const target*) * 2, + "member layout incompatible with array"); + + return a != nullptr || s != nullptr + ? group_view {reinterpret_cast<const target* const*> (&a), 2} + : group_view {nullptr, 0}; + } + + static target* + lib_factory (context& ctx, + const target_type&, dir_path dir, dir_path out, string n) + { + // Casts are MT-aware (during serial load). + // + liba* a (ctx.phase == run_phase::load + ? const_cast<liba*> (ctx.targets.find<liba> (dir, out, n)) + : nullptr); + libs* s (ctx.phase == run_phase::load + ? const_cast<libs*> (ctx.targets.find<libs> (dir, out, n)) + : nullptr); + + lib* l (new lib (ctx, move (dir), move (out), move (n))); + + if (a != nullptr) a->group = l; + if (s != nullptr) s->group = l; + + return l; + } + + const target_type lib::static_type + { + "lib", + &libx::static_type, + &lib_factory, + nullptr, + nullptr, + nullptr, + nullptr, + &target_search, + false // Note: not see-through ("alternatives" group). + }; + + // libi + // + const target_type libi::static_type + { + "libi", + &file::static_type, + &target_factory<libi>, + nullptr, /* fixed_extension */ + &target_extension_var<nullptr>, + &target_pattern_var<nullptr>, + nullptr, + &file_search, + false + }; + + // def + // + extern const char def_ext[] = "def"; // VC14 rejects constexpr. + + const target_type def::static_type + { + "def", + &file::static_type, + &target_factory<def>, + &target_extension_fix<def_ext>, + nullptr, /* default_extension */ + &target_pattern_fix<def_ext>, + nullptr, + &file_search, + false + }; + } +} |