aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-12-16 17:22:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-12-16 17:22:28 +0200
commit75152526696fc024628796f0633ed695d5ebc49c (patch)
treefaeef54a6b4d7e9a816b8d541500c48484e4ed39
parentcc12ed4245a2b61f4c4eb2a970398c920fbc1d37 (diff)
Move exe{} to build2 core, add fallback extensions (existing files)
-rw-r--r--build2/bin/init.cxx3
-rw-r--r--build2/bin/target10
-rw-r--r--build2/bin/target.cxx22
-rw-r--r--build2/cc/compile.cxx4
-rw-r--r--build2/cc/utility.ixx2
-rw-r--r--build2/context.cxx1
-rw-r--r--build2/install/init.cxx1
-rw-r--r--build2/rule.cxx5
-rw-r--r--build2/search.cxx4
-rw-r--r--build2/target27
-rw-r--r--build2/target-type9
-rw-r--r--build2/target.cxx39
-rw-r--r--build2/target.txx4
-rw-r--r--build2/test/target.cxx2
14 files changed, 74 insertions, 59 deletions
diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx
index 498118f..ff30c4f 100644
--- a/build2/bin/init.cxx
+++ b/build2/bin/init.cxx
@@ -342,9 +342,6 @@ namespace build2
t.insert<obja> ();
t.insert<objs> ();
- t.insert<exe> ();
- install_path<exe> (b, dir_path ("bin")); // Install into install.bin.
-
t.insert<lib> ();
t.insert<liba> ();
t.insert<libs> ();
diff --git a/build2/bin/target b/build2/bin/target
index caf96f4..f3fe4fe 100644
--- a/build2/bin/target
+++ b/build2/bin/target
@@ -60,16 +60,6 @@ namespace build2
virtual const target_type& dynamic_type () const {return static_type;}
};
- class exe: public file
- {
- public:
- using file::file;
-
- public:
- static const target_type static_type;
- virtual const target_type& dynamic_type () const {return static_type;}
- };
-
// The lib{} target group.
//
class liba: public file
diff --git a/build2/bin/target.cxx b/build2/bin/target.cxx
index 770afbb..3277eb1 100644
--- a/build2/bin/target.cxx
+++ b/build2/bin/target.cxx
@@ -129,28 +129,6 @@ namespace build2
false
};
- // @@ What extension should we be using when searching for an existing
- // exe{}? Say we have a dependency on some pre-existing tool, maybe
- // some source code generator. Should we use 'build' extension? But
- // what if we find such an executable for something that we need to
- // build for 'host'?
- //
- // What if we use extension variables and scoping. We could set the
- // root scope exe{*} extension to 'build' and then, say, cxx module
- // (or any module that knows how to build exe{}) changes it to the
- // 'host'. Maybe that's not a bad idea?
- //
- const target_type exe::static_type
- {
- "exe",
- &file::static_type,
- &target_factory<exe>,
- &target_extension_var<ext_var, nullptr>,
- nullptr,
- &search_file,
- false
- };
-
static target*
liba_factory (const target_type& t,
dir_path d,
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index 37cd7d7..74a9422 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -418,7 +418,9 @@ namespace build2
const string* dummy (nullptr);
target_key tk {&tt, nullptr, nullptr, &n, dummy};
- if (const string* de = tt.extension (tk, s))
+ // This is like prerequisite search.
+ //
+ if (const string* de = tt.extension (tk, s, true))
if (*de == e)
return true;
diff --git a/build2/cc/utility.ixx b/build2/cc/utility.ixx
index dda74eb..ee54b6d 100644
--- a/build2/cc/utility.ixx
+++ b/build2/cc/utility.ixx
@@ -19,7 +19,7 @@ namespace build2
link_type (target& t)
{
return
- t.is_a<bin::exe> () ? otype::e :
+ t.is_a<exe> () ? otype::e :
t.is_a<bin::liba> () ? otype::a :
otype::s;
}
diff --git a/build2/context.cxx b/build2/context.cxx
index 0966c3a..2b1f24d 100644
--- a/build2/context.cxx
+++ b/build2/context.cxx
@@ -314,6 +314,7 @@ namespace build2
t.insert<alias> ();
t.insert<dir> ();
t.insert<fsdir> ();
+ t.insert<exe> ();
t.insert<doc> ();
t.insert<man> ();
t.insert<man1> ();
diff --git a/build2/install/init.cxx b/build2/install/init.cxx
index 73e4c1e..842eb0c 100644
--- a/build2/install/init.cxx
+++ b/build2/install/init.cxx
@@ -245,6 +245,7 @@ namespace build2
// Configure "installability" for built-in target types.
//
+ install_path<exe> (b, dir_path ("bin")); // Install into install.bin.
install_path<doc> (b, dir_path ("doc")); // Install into install.doc.
install_path<man> (b, dir_path ("man")); // Install into install.man.
install_path<man1> (b, dir_path ("man1")); // Install into install.man1.
diff --git a/build2/rule.cxx b/build2/rule.cxx
index f9805db..49172a7 100644
--- a/build2/rule.cxx
+++ b/build2/rule.cxx
@@ -57,6 +57,11 @@ namespace build2
//
if (pt.path ().empty ())
{
+ // Since we cannot come up with an extension, ask the target's
+ // derivation function to treat this as prerequisite (just like
+ // in search_existing_file()).
+ //
+ pt.derive_extension (nullptr, true);
pt.derive_path ();
ts = pt.mtime ();
}
diff --git a/build2/search.cxx b/build2/search.cxx
index 68191f5..6889a36 100644
--- a/build2/search.cxx
+++ b/build2/search.cxx
@@ -81,9 +81,7 @@ namespace build2
if (ext == nullptr)
{
if (auto f = ctk.type->extension)
- {
- ext = f (ctk, *cpk.scope); // Already from the pool.
- }
+ ext = f (ctk, *cpk.scope, true); // Already from the pool.
if (ext == nullptr)
{
diff --git a/build2/target b/build2/target
index f824689..5c897f1 100644
--- a/build2/target
+++ b/build2/target
@@ -425,7 +425,7 @@ namespace build2
// By default we go an extra step and short-circuit to the target state
// even if the raw state is not group provided the recipe is group_recipe.
// This is normally what you want or need, as in inject_prerequisites()
- // in the cxx module. But sometimes not, as in execute().
+ // in the cc module. But sometimes not, as in execute().
//
target_state
state (bool shortcircuit = true) const
@@ -1140,10 +1140,11 @@ namespace build2
derive_path (path_type base, const char* default_ext = nullptr);
// As above but only derives (and returns) the extension (empty means no
- // extension used).
+ // extension used). If search is true then look for the extension as if
+ // it was a prerequisite, not a target.
//
const string&
- derive_extension (const char* default_ext = nullptr);
+ derive_extension (const char* default_ext = nullptr, bool search = false);
public:
static const target_type static_type;
@@ -1215,6 +1216,18 @@ namespace build2
virtual const target_type& dynamic_type () const {return static_type;}
};
+ // Executable file.
+ //
+ class exe: public file
+ {
+ public:
+ using file::file;
+
+ public:
+ static const target_type static_type;
+ virtual const target_type& dynamic_type () const {return static_type;}
+ };
+
class buildfile: public file
{
public:
@@ -1311,24 +1324,24 @@ namespace build2
//
template <const char* ext>
const string*
- target_extension_fix (const target_key&, scope&);
+ target_extension_fix (const target_key&, scope&, bool);
// Get the extension from the variable or use the default if none set. If
// the default is NULL, then return NULL.
//
template <const char* var, const char* def>
const string*
- target_extension_var (const target_key&, scope&);
+ target_extension_var (const target_key&, scope&, bool);
// Always return NULL extension.
//
const string*
- target_extension_null (const target_key&, scope&);
+ target_extension_null (const target_key&, scope&, bool);
// Assert if called.
//
const string*
- target_extension_assert (const target_key&, scope&);
+ target_extension_assert (const target_key&, scope&, bool);
// Target print functions.
//
diff --git a/build2/target-type b/build2/target-type
index 378fd7c..5e7f59b 100644
--- a/build2/target-type
+++ b/build2/target-type
@@ -31,9 +31,10 @@ namespace build2
// respectively. If the extension function returns NULL, then that means the
// default extension for this target could not be derived.
//
- // The extension is primarily used in two places: search_existing_file()
- // (called for a prerequisite) and in target::derive_path() (called for a
- // target); see their implementations for details.
+ // The extension is used in two places: search_existing_file() (called for a
+ // prerequisite with the last argument true) and in target::derive_path()
+ // (called for a target with the last argument false); see their
+ // implementations for details.
//
struct target_type
{
@@ -41,7 +42,7 @@ namespace build2
const target_type* base;
target* (*factory) (
const target_type&, dir_path, dir_path, string, const string*);
- const string* (*extension) (const target_key&, scope&);
+ const string* (*extension) (const target_key&, scope&, bool search);
void (*print) (ostream&, const target_key&);
target* (*search) (const prerequisite_key&);
bool see_through; // A group with the default "see through" semantics.
diff --git a/build2/target.cxx b/build2/target.cxx
index 126159c..385cebd 100644
--- a/build2/target.cxx
+++ b/build2/target.cxx
@@ -332,7 +332,7 @@ namespace build2
// path_target
//
const string& path_target::
- derive_extension (const char* de)
+ derive_extension (const char* de, bool search)
{
// See also search_existing_file() if updating anything here.
//
@@ -346,7 +346,7 @@ namespace build2
// the user can use to override extensions.
//
if (auto f = type ().extension)
- ext = f (key (), base_scope ()); // Already from the pool.
+ ext = f (key (), base_scope (), search); // Already from the pool.
if (ext == nullptr)
{
@@ -453,13 +453,13 @@ namespace build2
}
const string*
- target_extension_null (const target_key&, scope&)
+ target_extension_null (const target_key&, scope&, bool)
{
return nullptr;
}
const string*
- target_extension_assert (const target_key&, scope&)
+ target_extension_assert (const target_key&, scope&, bool)
{
assert (false); // Attempt to obtain the default extension.
throw failed ();
@@ -585,6 +585,35 @@ namespace build2
false
};
+ static const string*
+ exe_extension (const target_key&, scope&, bool search)
+ {
+ // If we are searching for an executable that is not a target, then
+ // use the build machine executable extension. Otherwise, if this is
+ // a target, then we expect the rule to use target machine extension.
+ //
+ return search
+ ? &extension_pool.find (
+#ifdef _WIN32
+ "exe"
+#else
+ ""
+#endif
+ )
+ : nullptr;
+ }
+
+ const target_type exe::static_type
+ {
+ "exe",
+ &file::static_type,
+ &target_factory<exe>,
+ &exe_extension,
+ nullptr,
+ &search_file,
+ false
+ };
+
static target*
buildfile_factory (const target_type&,
dir_path d,
@@ -599,7 +628,7 @@ namespace build2
}
static const string*
- buildfile_target_extension (const target_key& tk, scope&)
+ buildfile_target_extension (const target_key& tk, scope&, bool)
{
// If the name is special 'buildfile', then there is no extension,
// otherwise it is .build.
diff --git a/build2/target.txx b/build2/target.txx
index bdd1224..f342728 100644
--- a/build2/target.txx
+++ b/build2/target.txx
@@ -35,14 +35,14 @@ namespace build2
//
template <const char* ext>
const string*
- target_extension_fix (const target_key&, scope&)
+ target_extension_fix (const target_key&, scope&, bool)
{
return &extension_pool.find (ext);
}
template <const char* var, const char* def>
const string*
- target_extension_var (const target_key& tk, scope& s)
+ target_extension_var (const target_key& tk, scope& s, bool)
{
// Include target type/pattern-specific variables.
//
diff --git a/build2/test/target.cxx b/build2/test/target.cxx
index 1a215ca..727ae48 100644
--- a/build2/test/target.cxx
+++ b/build2/test/target.cxx
@@ -25,7 +25,7 @@ namespace build2
}
static const string*
- testscript_target_extension (const target_key& tk, scope&)
+ testscript_target_extension (const target_key& tk, scope&, bool)
{
// If the name is special 'testscript', then there is no extension,
// otherwise it is .test.