Add ability to specify substitutions as key-value pairs

This commit is contained in:
Boris Kolpackov 2022-09-02 10:45:23 +02:00
parent 48fb7e2cc9
commit ed653f0cc2
7 changed files with 103 additions and 21 deletions

View File

@ -55,8 +55,8 @@ h{config}: in{config}
```
Besides the built-in configuration options, custom substitutions can be
specified as `buildfile` variables in the same way as with the
[`in`][module-in] module. For example:
specified as `buildfile` variables or key-value pairs in the same way as with
the [`in`][module-in] module. For example, as `buildfile` variables:
```
/* config.h.in */
@ -76,7 +76,35 @@ h{config}: in{config}
}
```
This mechanism can also be used to override the built-in checks, for example:
As key-value pairs in the `autoconf.substitutions` map (which is an alias for
the `in.substitutions` variable; see the [`in`][module-in] module for
details):
```
/* config.h.in */
#undef _GNU_SOURCE
#undef _POSIX_SOURCE
```
```
gnu_source = ($c.stdlib == 'glibc')
posix_source = ($c.target.class != 'windows' && !$gnu_source)
h{config}: in{config}
{
autoconf.substitutions = _GNU_SOURCE@$gnu_source
autoconf.substitutions += _POSIX_SOURCE@$posix_source
}
```
In particular, the `autoconf.substitutions` mechanism is the only way to have
substitutions that cannot be specified as `buildfile` variables because they
start with an underscore (and thus are reserved, as in the above example) or
refer to one of the predefined variables.
The custom substitutions can also be used to override the built-in checks, for
example:
```
h{config}: in{config}

View File

@ -7,5 +7,5 @@ license: MIT ; MIT License.
description-file: README.md
url: https://github.com/build2/libbuild2-autoconf
email: users@build2.org
depends: * build2 >= 0.15.0-
depends: * bpkg >= 0.15.0-
depends: * build2 >= 0.16.0-
depends: * bpkg >= 0.16.0-

View File

@ -401,3 +401,26 @@ cat config.h >>EOO
# define PREFIX_zzz_TEST_DUMMY5_H PREFIX_zzz_TEST_DUMMY4_H
#endif /*zzz_TEST_DUMMY3_H*/
EOO
: substitution-map
:
mkdir build;
ln -s ../../bootstrap.build ../../root.build build/;
cat <<EOI >=config.h.in;
#undef _GNU_SOURCE
#undef _POSIX_SOURCE
#undef FOO
EOI
$* <<EOI &config.h &config.h.d;
gnu = false
./: h{config}: in{config}
{
autoconf.substitutions = _GNU_SOURCE@$gnu _POSIX_SOURCE@true
FOO = true
}
EOI
cat config.h >>EOO
#undef _GNU_SOURCE
#define _POSIX_SOURCE 1
#define FOO 1
EOO

View File

@ -43,6 +43,11 @@ namespace build2
// Built-in checks prefix.
//
vp.insert<string> ("autoconf.prefix");
// Substitution map (an alias for in.substitutions).
//
vp.insert_alias (*vp.find ("in.substitutions"),
"autoconf.substitutions");
}
// Register the rule.

View File

@ -144,6 +144,7 @@ namespace build2
const char* nl,
char sym,
bool strict,
const substitution_map* smap,
const optional<string>& null) const
{
auto ws = [] (char c)
@ -182,7 +183,7 @@ namespace build2
&l,
a, &t,
&dd, &dd_skip,
nl, strict, &null,
nl, strict, smap, &null,
&s] (const string& name,
bool value = true) -> optional<bool>
{
@ -195,7 +196,7 @@ namespace build2
a, t,
dd, dd_skip,
name, 1 /* flags */,
strict, null));
strict, smap, null));
assert (ov); // C identifier is a valid variable name.
string& v (*ov);
@ -470,7 +471,8 @@ namespace build2
}
}
in::rule::process (l, a, t, dd, dd_skip, s, b, nl, sym, strict, null);
in::rule::process (
l, a, t, dd, dd_skip, s, b, nl, sym, strict, smap, null);
}
string rule::
@ -478,6 +480,7 @@ namespace build2
action a, const target& t,
const string& n,
optional<uint64_t> flags,
const substitution_map* smap,
const optional<string>& null) const
{
if (flags)
@ -508,7 +511,7 @@ namespace build2
// variable is unlikely, something like const or volatile is
// possible. Since there is no way to undefine a buildfile variable
// (becasue we could always see a value from the outer scope), we
// will treat null as an indication to use the built-in check.
// will treat null as an instruction to use the built-in check.
// While this clashes with the in.null semantics, it's just as
// easy to set the variable to the real default value as to null.
//
@ -554,11 +557,31 @@ namespace build2
(!up || strchr (i->modifier, '!') != nullptr)) ? i : nullptr;
};
// Note: original name in variable lookup.
// Return true if there is a custom substitution for the name.
//
// Note: see above on the special NULL semantics.
//
auto custom = [&t, smap] (const string& n) -> bool
{
if (smap != nullptr)
{
auto i (smap->find (n));
// Note that we treat NULL as the "use built-in check" instruction
// (see above). So it's a return, not fall through.
//
if (i != smap->end ())
return i->second.has_value ();
}
return static_cast<bool> (t[n]);
};
// Note: original name in the custom substitution lookup.
//
const check* c (find (en, pn == nullptr));
if (c != nullptr && !t[n])
if (c != nullptr && !custom (n))
{
// The plan is as follows: keep adding base checks (suppressing
// duplicates) followed by the main check while prefixing all the
@ -616,11 +639,12 @@ namespace build2
// Buildscript).
//
auto base = [this,
&l, &t, a, &null,
&l, &t, a, smap, &null,
&md, &p, &ns,
&find, &append, &prefix] (const string& n,
const char* bs,
const auto& base) -> void
&find, &custom,
&append, &prefix] (const string& n,
const char* bs,
const auto& base) -> void
{
auto df = make_diag_frame (
[&n] (const diag_record& dr)
@ -666,9 +690,9 @@ namespace build2
md.checks.emplace (pn, n);
if (t[n])
append (
this->in::rule::lookup (l, a, t, n, nullopt, null).c_str ());
if (custom (n))
append (this->in::rule::lookup (
l, a, t, n, nullopt, smap, null).c_str ());
else
{
if (*c->base != '\0')
@ -706,7 +730,7 @@ namespace build2
}
}
return in::rule::lookup (l, a, t, n, nullopt, null);
return in::rule::lookup (l, a, t, n, nullopt, smap, null);
}
}
}

View File

@ -39,6 +39,7 @@ namespace build2
const char*,
char,
bool,
const substitution_map*,
const optional<string>&) const override;
virtual string
@ -46,6 +47,7 @@ namespace build2
action, const target&,
const string&,
optional<uint64_t>,
const substitution_map*,
const optional<string>&) const override;
};
}

View File

@ -9,6 +9,6 @@ url: https://github.com/build2/libbuild2-autoconf
email: users@build2.org
build-warning-email: builds@build2.org
builds: all
depends: * build2 >= 0.15.0-
depends: * bpkg >= 0.15.0-
depends: * build2 >= 0.16.0-
depends: * bpkg >= 0.16.0-
tests: * libbuild2-autoconf-tests == $