aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2019-03-14 22:03:59 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2019-03-15 20:06:52 +0300
commit361fcde22d3c9729882505968c3370effb0ac772 (patch)
tree56c8be79d06a279e82c00dfc1e0b709339770b8e
parent5b91a1ba5f651bbbe5409077134201dd65777cb0 (diff)
Add support for c++ source file extensions granular customization
-rw-r--r--bdep/bdep.cxx2
-rw-r--r--bdep/buildfile7
-rw-r--r--bdep/new-parsers.cxx64
-rw-r--r--bdep/new-types.hxx11
-rw-r--r--bdep/new-types.ixx64
-rw-r--r--bdep/new.cli137
-rw-r--r--bdep/new.cxx172
-rw-r--r--tests/new.testscript170
8 files changed, 535 insertions, 92 deletions
diff --git a/bdep/bdep.cxx b/bdep/bdep.cxx
index 00d70f7..e4146e5 100644
--- a/bdep/bdep.cxx
+++ b/bdep/bdep.cxx
@@ -203,7 +203,7 @@ try
// First parse common options and --version/--help.
//
- options o;
+ bdep::options o;
o.parse (scan, unknown_mode::stop);
if (o.version ())
diff --git a/bdep/buildfile b/bdep/buildfile
index 74e8a0e..a328629 100644
--- a/bdep/buildfile
+++ b/bdep/buildfile
@@ -127,9 +127,10 @@ if $cli.configured
cli.options += -I $src_root --include-with-brackets --include-prefix bdep \
--guard-prefix BDEP --cxx-prologue "#include <bdep/types-parsers.hxx>" \
--cli-namespace bdep::cli --generate-vector-scanner --generate-file-scanner \
---generate-group-scanner --keep-separator --generate-specifier --generate-modifier \
---generate-parse --page-usage 'bdep::print_$name$_' --ansi-color \
---include-base-last --suppress-undocumented --option-length 23
+--generate-group-scanner --keep-separator --generate-specifier \
+--generate-modifier --generate-description --generate-parse \
+--page-usage 'bdep::print_$name$_' --ansi-color --include-base-last \
+--suppress-undocumented --option-length 23
cli.cxx{common-options}: cli.options += --short-usage --long-usage # Both.
cli.cxx{bdep-options}: cli.options += --short-usage
diff --git a/bdep/new-parsers.cxx b/bdep/new-parsers.cxx
index ca45447..f8a8c75 100644
--- a/bdep/new-parsers.cxx
+++ b/bdep/new-parsers.cxx
@@ -21,34 +21,62 @@ namespace bdep
static O
parse_options (const char* o, const string v, size_t pos)
{
- // Use vector_scanner to parse the comma-separated list as options.
+ // Use vector_scanner to parse the comma-separated list of
+ // parameter-specific options. Make sure that option values are only
+ // specified if required (no value for flags, etc).
//
vector<string> os;
+ const options& ods (O::description ());
+
for (size_t i (pos), j; i != string::npos; )
{
j = i + 1;
i = v.find (',', j);
- os.push_back (string (v, j, i != string::npos ? i - j : i));
+
+ string po (v, j, i != string::npos ? i - j : i);
+
+ // Split the parameter-specific option into the name and value.
+ //
+ optional<string> pv;
+ {
+ size_t i (po.find ('='));
+
+ if (i != string::npos)
+ {
+ pv = string (po, i + 1);
+ po.resize (i);
+ }
+ }
+
+ // Verify that the option is known and its value is only specified if
+ // required.
+ //
+ {
+ auto i (ods.find (po));
+
+ if (i == ods.end ())
+ throw invalid_value (o, po);
+
+ bool flag (!pv);
+
+ if (flag != i->flag ())
+ throw invalid_value (o,
+ po,
+ string (flag ? "missing" : "unexpected") +
+ " value for '" + po + "'");
+ }
+
+ os.push_back (move (po));
+
+ if (pv)
+ os.push_back (move (*pv));
}
vector_scanner s (os);
- try
- {
- O r;
- r.parse (s,
- unknown_mode::fail /* unknown_option */,
- unknown_mode::fail /* unknown_argument */);
- return r;
- }
- catch (const unknown_option& e)
- {
- throw invalid_value (o, e.option ());
- }
- catch (const unknown_argument& e)
- {
- throw invalid_value (o, e.argument ());
- }
+ O r;
+ r.parse (s);
+ return r;
}
void parser<type>::
diff --git a/bdep/new-types.hxx b/bdep/new-types.hxx
index f80b973..0f36e42 100644
--- a/bdep/new-types.hxx
+++ b/bdep/new-types.hxx
@@ -82,7 +82,14 @@ namespace bdep
// Default is C++ with no options.
//
- cmd_new_lang_template (): lang (cxx) {cxx_opt = CXX ();}
+ cmd_new_lang_template (): lang (cxx), cxx_opt (CXX ()) {}
+
+ cmd_new_lang_template (cmd_new_lang_template&&);
+ cmd_new_lang_template (const cmd_new_lang_template&);
+ cmd_new_lang_template& operator= (cmd_new_lang_template&&);
+ cmd_new_lang_template& operator= (const cmd_new_lang_template&);
+
+ ~cmd_new_lang_template ();
};
using cmd_new_lang = cmd_new_lang_template<>;
@@ -114,4 +121,6 @@ namespace bdep
using cmd_new_vcs = cmd_new_vcs_template<>;
}
+#include <bdep/new-types.ixx>
+
#endif // BDEP_NEW_TYPES_HXX
diff --git a/bdep/new-types.ixx b/bdep/new-types.ixx
new file mode 100644
index 0000000..a8eafc5
--- /dev/null
+++ b/bdep/new-types.ixx
@@ -0,0 +1,64 @@
+// file : bdep/new-types.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <bdep/utility.hxx> // move()
+
+namespace bdep
+{
+ template <typename C, typename CXX>
+ inline cmd_new_lang_template<C, CXX>::
+ ~cmd_new_lang_template ()
+ {
+ if (lang == c)
+ c_opt.~C ();
+ else
+ cxx_opt.~CXX ();
+ }
+
+ template <typename C, typename CXX>
+ inline cmd_new_lang_template<C, CXX>::
+ cmd_new_lang_template (cmd_new_lang_template&& l): lang (l.lang)
+ {
+ if (lang == c)
+ new (&c_opt) C (move (l.c_opt));
+ else
+ new (&cxx_opt) CXX (move (l.cxx_opt));
+ }
+
+ template <typename C, typename CXX>
+ inline cmd_new_lang_template<C, CXX>::
+ cmd_new_lang_template (const cmd_new_lang_template& l): lang (l.lang)
+ {
+ if (lang == c)
+ new (&c_opt) C (l.c_opt);
+ else
+ new (&cxx_opt) CXX (l.cxx_opt);
+ }
+
+ template <typename C, typename CXX>
+ inline cmd_new_lang_template<C, CXX>& cmd_new_lang_template<C, CXX>::
+ operator= (cmd_new_lang_template&& l)
+ {
+ if (this != &l)
+ {
+ this->~cmd_new_lang_template<C, CXX> ();
+
+ // Assume noexcept move-construction.
+ //
+ new (this) cmd_new_lang_template<C, CXX> (move (l));
+ }
+
+ return *this;
+ }
+
+ template <typename C, typename CXX>
+ inline cmd_new_lang_template<C, CXX>& cmd_new_lang_template<C, CXX>::
+ operator= (const cmd_new_lang_template& l)
+ {
+ if (this != &l)
+ *this = cmd_new_lang_template<C, CXX> (l); // Reduce to move-assignment.
+
+ return *this;
+ }
+}
diff --git a/bdep/new.cli b/bdep/new.cli
index 38572c8..8f64e8f 100644
--- a/bdep/new.cli
+++ b/bdep/new.cli
@@ -119,45 +119,66 @@ namespace bdep
\li|\cb{exe}
- A project that builds a sample executable. Recognized executable
- project options:
+ A project that builds a sample executable. Recognized
+ executable project options:|
- \cb{no-tests} \- Don't add support for functional/integration testing.
+ \li|\n\ \ \ \cb{no-tests}
- \cb{unit-tests} \- Add support for unit testing.
+ Don't add support for functional/integration testing.|
- \cb{alt-naming} \- Use the alternative build file/directory naming scheme.
- |
+ \li|\n\ \ \ \cb{unit-tests}
+
+ Add support for unit testing.|
+
+ \li|\n\ \ \ \cb{alt-naming}
+
+ Use the alternative build file/directory naming scheme.||
+
+ \dl|
\li|\cb{lib}
- A project that builds a sample library. Recognized library project
- options:
+ A project that builds a sample library. Recognized library
+ project options:|
+
+ \li|\n\ \ \ \cb{no-tests}
+
+ Don't add support for functional/integration testing.|
+
+ \li|\n\ \ \ \cb{unit-tests}
+
+ Add support for unit testing.|
+
+ \li|\n\ \ \ \cb{no-version}
- \cb{no-tests} \- Don't add support for functional/integration testing.
+ Don't add support for generating the version header.|
- \cb{unit-tests} \- Add support for unit testing.
+ \li|\n\ \ \ \cb{alt-naming}
- \cb{no-version} \- Don't add support for generating the version header.
+ Use the alternative build file/directory naming scheme.||
- \cb{alt-naming} \- Use the alternative build file/directory naming scheme.
- |
+ \dl|
\li|\cb{bare}
- A project without any source code that can be filled later (see
- \cb{--subdirectory}). Recognized bare project options:
+ A project without any source code that can be filled later
+ (see \cb{--subdirectory}). Recognized bare project options:|
+
+ \li|\n\ \ \ \cb{no-tests}
+
+ Don't add support for testing.|
- \cb{no-tests} \- Don't add support for testing.
+ \li|\n\ \ \ \cb{alt-naming}
- \cb{alt-naming} \- Use the alternative build file/directory naming scheme.
- |
+ Use the alternative build file/directory naming scheme.||
+
+ \dl|
\li|\cb{empty}
An empty project that can be filled with packages (see
- \cb{--package}). Note that the project language is ignored for
- this project type.||
+ \cb{--package}). Note that the project language is ignored for this
+ project type.||
The project language can be specified with the \c{\b{--lang}|\b{-l}}
option. Valid values for this option and their semantics are described
@@ -167,19 +188,65 @@ namespace bdep
\li|\cb{c}
- A C project.|
+ A C project.||
+
+ \dl|
\li|\cb{c++}
- A C++ project. Recognized language options:
+ A C++ project. Recognized language options:|
+
+ \li|\n\ \ \ \cb{binless}
+
+ Create a header-only library.|
+
+ \li|\n\ \ \ \cb{cpp}
- \cb{cxx} \- Use the \cb{.cxx}, \cb{.hxx}, \cb{.ixx}, \cb{.txx}, and
- \cb{.mxx} source file extensions (default).
+ Use the \cb{.cpp}, \cb{.hpp}, \cb{.ipp}, \cb{.tpp}, and \cb{.mpp}
+ source file extensions (alias for \cb{extension=?pp}).|
- \cb{cpp} \- Use the \cb{.cpp}, \cb{.hpp}, \cb{.ipp}, \cb{.tpp}, and
- \cb{.mpp} source file extensions.
+ \li|\n\ \ \ \c{\b{extension=}\i{pattern}}
- \cb{binless} \- Create a header-only library.||
+ Derive source file extensions from \ci{pattern} by replacing
+ every \cb{?} with one of the \cb{c} (source), \cb{h} (header),
+ \cb{i} (inline), \cb{t} (template), or \cb{m} (module interface)
+ letters. If unspecified and no individual extensions are specified
+ with the below options, then \cb{?xx} is used by default.|
+
+ \li|\n\ \ \ \c{\b{hxx=}\i{extension}}
+
+ Use the specified \ci{extension} for header files instead of
+ the default \cb{.hxx}.|
+
+ \li|\n\ \ \ \c{\b{cxx=}\i{extension}}
+
+ Use the specified \ci{extension} for source files instead of
+ the default \cb{.cxx}.|
+
+ \li|\n\ \ \ \c{\b{ixx=}\i{extension}}
+
+ Use the specified \ci{extension} for inline files. If
+ unspecified, then assume no inline files are used by the
+ project.|
+
+ \li|\n\ \ \ \c{\b{txx=}\i{extension}}
+
+ Use the specified \ci{extension} for template files. If
+ unspecified, then assume no template files are used by the
+ project.|
+
+ \li|\n\ \ \ \c{\b{mxx=}\i{extension}}
+
+ Use the specified \ci{extension} for module interface files. If
+ unspecified, then assume no modules are used by the project.||
+
+ As an example, the following command creates a header-only C++ library
+ that uses the \cb{.h} extension for header files and \cb{.cpp} \- for
+ source files:
+
+ \
+ $ bdep new -t lib -l c++,binless,hxx=h,cxx=cpp libhello
+ \
The project version control system can be specified with the
\c{\b{--vcs}|\b{-s}} option. Valid values for this option and their
@@ -191,7 +258,9 @@ namespace bdep
\li|\cb{git}
Initialize a \cb{git(1)} repository inside the project and generate
- \cb{.gitignore} files.|
+ \cb{.gitignore} files.||
+
+ \dl|
\li|\cb{none}
@@ -232,11 +301,19 @@ namespace bdep
{
};
+ // The cpp flag is the "extension=?pp" alias and is mutually exclusive with
+ // extension=.
+ //
class cmd_new_cxx_options
{
- bool cpp;
- bool cxx;
bool binless;
+ bool cpp;
+ string extension;
+ string hxx;
+ string cxx;
+ string ixx;
+ string txx;
+ string mxx;
};
// --vcs options
diff --git a/bdep/new.cxx b/bdep/new.cxx
index 91b1bc5..80bb4d8 100644
--- a/bdep/new.cxx
+++ b/bdep/new.cxx
@@ -4,6 +4,8 @@
#include <bdep/new.hxx>
+#include <algorithm> // replace()
+
#include <libbutl/project-name.mxx>
#include <bdep/project.hxx>
@@ -127,8 +129,24 @@ namespace bdep
{
auto& o (l.cxx_opt);
- if (o.cpp () && o.cxx ())
- fail << "'cxx' and 'cpp' are mutually exclusive c++ options";
+ if (o.cpp () && o.extension_specified ())
+ fail << "'extension' and 'cpp' are mutually exclusive c++ options";
+
+ // Verify that none of the extensions are specified as empty, except
+ // for hxx.
+ //
+ auto empty_ext = [] (const string& v, const char* o)
+ {
+ if (v.empty () || (v.size () == 1 && v[0] == '.'))
+ fail << "empty extension specified with '" << o << "' c++ option";
+ };
+
+ if (o.extension_specified ()) empty_ext (o.extension (), "extension");
+
+ if (o.cxx_specified ()) empty_ext (o.cxx (), "cxx");
+ if (o.ixx_specified ()) empty_ext (o.ixx (), "ixx");
+ if (o.txx_specified ()) empty_ext (o.txx (), "txx");
+ if (o.mxx_specified ()) empty_ext (o.mxx (), "mxx");
if (o.binless () && t != type::lib)
fail << "'binless' is only valid for libraries";
@@ -523,8 +541,13 @@ namespace bdep
string m; // Language module.
string x; // Source target type.
string h; // Header target type.
- string hs; // All header target types.
- string es; // Source file extension suffix (pp, xx).
+ string hs; // All header-like target types.
+ string xe; // Source file extension (including leading dot).
+ string he; // Header file extension (including leading dot unless empty).
+
+ optional<string> ie; // Inline file extension.
+ optional<string> te; // Template file extension.
+ optional<string> me; // Module interface extension.
switch (l)
{
@@ -534,19 +557,84 @@ namespace bdep
x = "c";
h = "h";
hs = "h";
+ xe = ".c";
+ he = ".h";
break;
}
case lang::cxx:
{
+ const auto& opt (l.cxx_opt);
+
m = "cxx";
x = "cxx";
h = "hxx";
- hs = "hxx ixx txx";
- es = l.cxx_opt.cpp () ? "pp" : "xx";
+ hs = "hxx";
+
+ // Return the extension (v), if specified (s), derive the extension
+ // from the pattern and type (t), or return the default (d), if
+ // specified.
+ //
+ auto ext = [&opt] (bool s,
+ const string& v,
+ char t,
+ const char* d = nullptr) -> optional<string>
+ {
+ optional<string> r;
+
+ if (s)
+ r = v;
+ else if (opt.extension_specified () || opt.cpp ())
+ {
+ string p (opt.extension_specified () ? opt.extension () :
+ opt.cpp () ? "?pp" : "");
+
+ replace (p.begin (), p.end (), '?', t);
+ r = move (p);
+ }
+ else if (d != nullptr)
+ r = d;
+
+ // Add leading dot if absent.
+ //
+ if (r && !r->empty () && r->front () != '.')
+ r = '.' + *r;
+
+ return r;
+ };
+
+ xe = *ext (opt.cxx_specified (), opt.cxx (), 'c', "cxx");
+ he = *ext (opt.hxx_specified (), opt.hxx (), 'h', "hxx");
+
+ // We only want default .ixx/.txx/.mxx if the user didn't specify
+ // any of the extension-related options explicitly.
+ //
+ bool d (!opt.cxx_specified () &&
+ !opt.hxx_specified () &&
+ !opt.ixx_specified () &&
+ !opt.txx_specified () &&
+ !opt.mxx_specified ());
+
+ ie = ext (opt.ixx_specified (), opt.ixx (), 'i', d ? "ixx" : nullptr);
+ te = ext (opt.txx_specified (), opt.txx (), 't', d ? "txx" : nullptr);
+ me = ext (opt.mxx_specified (), opt.mxx (), 'm', d ? "mxx" : nullptr);
+
+ if (ie) hs += " ixx";
+ if (te) hs += " txx";
+ if (me) hs += " mxx";
+
break;
}
}
+ // Return the pointer to the extension suffix after the leading dot or
+ // to the extension beginning if it is empty.
+ //
+ auto pure_ext = [] (const string& e)
+ {
+ assert (e.empty () || e[0] == '.');
+ return e.c_str () + (e.empty () ? 0 : 1);
+ };
+
// build/
//
dir_path bd;
@@ -595,11 +683,14 @@ namespace bdep
os << "cxx.std = latest" << endl
<< endl
<< "using cxx" << endl
- << endl
- << "hxx{*}: extension = h" << es << endl
- << "ixx{*}: extension = i" << es << endl
- << "txx{*}: extension = t" << es << endl
- << "cxx{*}: extension = c" << es << endl;
+ << endl;
+
+ if (me) os << "mxx{*}: extension = " << pure_ext (*me) << endl;
+ os << "hxx{*}: extension = " << pure_ext (he) << endl;
+ if (ie) os << "ixx{*}: extension = " << pure_ext (*ie) << endl;
+ if (te) os << "txx{*}: extension = " << pure_ext (*te) << endl;
+ os << "cxx{*}: extension = " << pure_ext (xe) << endl;
+
break;
}
}
@@ -676,9 +767,9 @@ namespace bdep
}
case lang::cxx:
{
- // <base>/<stem>.c(xx|pp)
+ // <base>/<stem>.<cxx-ext>
//
- os.open (f = sd / s + ".c" + es);
+ os.open (f = sd / s + xe);
os << "#include <iostream>" << endl
<< endl
<< "int main (int argc, char* argv[])" << endl
@@ -804,9 +895,9 @@ namespace bdep
}
case lang::cxx:
{
- // <base>/<stem>.test.c(xx|pp)
+ // <base>/<stem>.test.<cxx-ext>
//
- os.open (f = sd / s + ".test.c" + es);
+ os.open (f = sd / s + ".test" + xe);
os << "#include <cassert>" << endl
<< "#include <iostream>" << endl
<< endl
@@ -890,10 +981,10 @@ namespace bdep
case lang::cxx:
if (l.cxx_opt.binless ())
{
- apih = s + ".h" + es;
- verh = ver ? "version.h" + es : string ();
+ apih = s + he;
+ verh = ver ? "version" + he : string ();
- // <stem>.h(xx|pp)
+ // <stem>[.<hxx-ext>]
//
os.open (f = sd / apih);
os << "#pragma once" << endl
@@ -924,11 +1015,11 @@ namespace bdep
}
else
{
- apih = s + ".h" + es;
- exph = "export.h" + es;
- verh = ver ? "version.h" + es : string ();
+ apih = s + he;
+ exph = "export" + he;
+ verh = ver ? "version" + he : string ();
- // <stem>.h(xx|pp)
+ // <stem>[.<hxx-ext>]
//
os.open (f = sd / apih);
os << "#pragma once" << endl
@@ -948,9 +1039,9 @@ namespace bdep
<< "}" << endl;
os.close ();
- // <stem>.c(xx|pp)
+ // <stem>.<cxx-ext>
//
- os.open (f = sd / s + ".c" + es);
+ os.open (f = sd / s + xe);
os << "#include <" << ip << apih << ">" << endl
<< endl
<< "#include <ostream>" << endl
@@ -1246,9 +1337,9 @@ namespace bdep
}
case lang::cxx:
{
- // <base>/<stem>.test.c(xx|pp)
+ // <base>/<stem>.test.<cxx-ext>
//
- os.open (f = sd / s + ".test.c" + es);
+ os.open (f = sd / s + ".test" + xe);
os << "#include <cassert>" << endl
<< "#include <iostream>" << endl
<< endl
@@ -1324,22 +1415,25 @@ namespace bdep
os << "cxx.std = latest" << endl
<< endl
<< "using cxx" << endl
- << endl
- << "hxx{*}: extension = h" << es << endl
- << "ixx{*}: extension = i" << es << endl
- << "txx{*}: extension = t" << es << endl
- << "cxx{*}: extension = c" << es << endl;
+ << endl;
+
+ if (me) os << "mxx{*}: extension = " << pure_ext (*me) << endl;
+ os << "hxx{*}: extension = " << pure_ext (he) << endl;
+ if (ie) os << "ixx{*}: extension = " << pure_ext (*ie) << endl;
+ if (te) os << "txx{*}: extension = " << pure_ext (*te) << endl;
+ os << "cxx{*}: extension = " << pure_ext (xe) << endl;
+
break;
}
}
- os << endl
+ os << endl
<< "# Every exe{} in this subproject is by default a test."<< endl
- << "#" << endl
- << "exe{*}: test = true" << endl
- << endl
+ << "#" << endl
+ << "exe{*}: test = true" << endl
+ << endl
<< "# The test target for cross-testing (running tests under Wine, etc)." << endl
- << "#" << endl
- << "test.target = $" << m << ".target" << endl;
+ << "#" << endl
+ << "test.target = $" << m << ".target" << endl;
os.close ();
// tests/build/.gitignore
@@ -1425,9 +1519,9 @@ namespace bdep
}
case lang::cxx:
{
- // tests/basics/driver.c(xx|pp)
+ // tests/basics/driver.<cxx-ext>
//
- os.open (f = td / "driver.c" + es);
+ os.open (f = td / "driver" + xe);
os << "#include <cassert>" << endl
<< "#include <sstream>" << endl
<< "#include <stdexcept>" << endl
diff --git a/tests/new.testscript b/tests/new.testscript
index 8e8fd75..6662eee 100644
--- a/tests/new.testscript
+++ b/tests/new.testscript
@@ -294,6 +294,176 @@ status += -d prj
EOE
}
}
+
+ : extensions
+ :
+ {
+ : default
+ :
+ {
+ $* -t lib -l c++ libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.cxx;
+ test -f libprj/libprj/prj.hxx;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : cpp
+ :
+ {
+ $* -t lib -l c++,cpp libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.cpp;
+ test -f libprj/libprj/prj.hpp;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : extension-c++
+ :
+ {
+ $* -t lib -l c++,extension=?++ libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.c++;
+ test -f libprj/libprj/prj.h++;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : extension-cc
+ :
+ {
+ $* -t lib -l c++,extension=?? libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.cc;
+ test -f libprj/libprj/prj.hh;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : cxx-hxx
+ :
+ {
+ $* -t lib -l c++,cxx=c,hxx=h libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.c;
+ test -f libprj/libprj/prj.h;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : empty-hxx
+ :
+ {
+ $* -t lib -l c++,hxx= libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.cxx;
+ test -f libprj/libprj/prj;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : ixx
+ :
+ {
+ $* -t lib -l c++,ixx=ixx libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ sed -n -e 's/(.*\bixx\b.*)/\1/p' libprj/build/root.build >>EOO;
+ ixx{*}: extension = ixx
+ EOO
+
+ sed -n -e 's/(.*\bixx\b.*)/\1/p' libprj/libprj/buildfile >>~%EOO%;
+ %.*\{hxx ixx cxx\}.*%
+ {hxx ixx}{*}:
+ EOO
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : leading-dot
+ :
+ {
+ $* -t lib -l c++,cxx=.cpp libprj 2>>/"EOE" &libprj/***;
+ created new library project libprj in $~/libprj/
+ EOE
+
+ test -f libprj/libprj/prj.cpp;
+ test -f libprj/libprj/prj.hxx;
+
+ $build libprj/ $cxx 2>>~%EOE%
+ %(version\.in|c\+\+|ar|ld) .+%{7}
+ EOE
+ }
+
+ : errors
+ :
+ {
+ : missing-value
+ :
+ $* -t lib -l c++,cxx libprj 2>>EOE != 0
+ error: invalid value 'cxx' for option '-l': missing value for 'cxx'
+ EOE
+
+ : unexpected-value
+ :
+ $* -t lib -l c++,cpp=cxx libprj 2>>EOE != 0
+ error: invalid value 'cpp' for option '-l': unexpected value for 'cpp'
+ EOE
+
+ : empty-value
+ :
+ $* -t lib -l c++,extension= libprj 2>>EOE != 0
+ error: empty extension specified with 'extension' c++ option
+ EOE
+
+ : dot-only
+ :
+ $* -t lib -l c++,extension=. libprj 2>>EOE != 0
+ error: empty extension specified with 'extension' c++ option
+ EOE
+
+ : unknown-value
+ :
+ $* -t lib -l c++,zxx= libprj 2>>EOE != 0
+ error: invalid value 'zxx' for option '-l'
+ EOE
+
+ : mutually-exclusive
+ :
+ $* -t lib -l c++,cpp,extension=?pp libprj 2>>EOE != 0
+ error: 'extension' and 'cpp' are mutually exclusive c++ options
+ EOE
+ }
+ }
}
: cfg