Config file: Treat section names as target triple regexps (#2718)

This commit is contained in:
Martin Kinkelin 2018-06-01 20:42:01 +02:00 committed by GitHub
parent 7816e7730a
commit ddbd77c009
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 109 additions and 72 deletions

View file

@ -232,7 +232,7 @@ after_test:
ren lib lib32 ren lib lib32
(cat etc\ldc2.conf).replace('%%ldcbinarypath%%/../lib', '%%ldcbinarypath%%/../lib64') | Set-Content etc\ldc2.conf (cat etc\ldc2.conf).replace('%%ldcbinarypath%%/../lib', '%%ldcbinarypath%%/../lib64') | Set-Content etc\ldc2.conf
$conf32 = cat ..\ldc2-x86\etc\ldc2.conf -Raw $conf32 = cat ..\ldc2-x86\etc\ldc2.conf -Raw
$conf32 = "`r`ni686-pc-windows-msvc:" + $conf32.Substring($conf32.IndexOf("`r`ndefault:") + 10) $conf32 = "`r`n""i[3-6]86-.*-windows-msvc"":" + $conf32.Substring($conf32.IndexOf("`r`ndefault:") + 10)
$conf32 = $conf32.Replace('%%ldcbinarypath%%/../lib', '%%ldcbinarypath%%/../lib32') $conf32 = $conf32.Replace('%%ldcbinarypath%%/../lib', '%%ldcbinarypath%%/../lib32')
Add-Content etc\ldc2.conf $conf32 Add-Content etc\ldc2.conf $conf32
cd .. cd ..

View file

@ -136,7 +136,7 @@ EBNF grammar.
It is a subset of the libconfig grammar (http://www.hyperrealm.com/libconfig). It is a subset of the libconfig grammar (http://www.hyperrealm.com/libconfig).
config = { ows , setting } , ows ; config = { ows , setting } , ows ;
setting = name , (":" | "=") , value , [";" | ","] ; setting = (name | string) , (":" | "=") , value , [";" | ","] ;
name = alpha , { alpha | digit | "_" | "-" } ; name = alpha , { alpha | digit | "_" | "-" } ;
value = string | array | group ; value = string | array | group ;
array = "[" , ows , array = "[" , ows ,
@ -445,14 +445,20 @@ struct Parser
Setting parseSetting() Setting parseSetting()
{ {
immutable name = accept(Token.name); string name;
auto t = getTok(name);
if (t != Token.name && t != Token.str)
{
unexpectedTokenError(t, Token.name, name);
assert(false);
}
accept(Token.assign); accept(Token.assign);
Setting res = parseValue(name); Setting res = parseValue(name);
string s; string s;
immutable t = getTok(s); t = getTok(s);
if (t != Token.semicolon && t != Token.comma) if (t != Token.semicolon && t != Token.comma)
{ {
ungetTok(t, s); ungetTok(t, s);
@ -567,25 +573,25 @@ unittest
`// comment `// comment
// comment // comment
group-1: {}; group-1_2: {};
// comment // comment
Group-2: "86(_64)?-.*linux\\.?":
{ {
// comment // comment
scalar = "abc"; scalar = "abc";
// comment // comment
Array_1 = [ "a" ]; Array_1-2 = [ "a" ];
}; };
`; `;
auto settings = Parser(input).parseConfig(); auto settings = Parser(input).parseConfig();
assert(settings.length == 2); assert(settings.length == 2);
assert(settings[0].name == "group-1"); assert(settings[0].name == "group-1_2");
assert(settings[0].type == Setting.Type.group); assert(settings[0].type == Setting.Type.group);
assert((cast(GroupSetting) settings[0]).children == []); assert((cast(GroupSetting) settings[0]).children == []);
assert(settings[1].name == "Group-2"); assert(settings[1].name == "86(_64)?-.*linux\\.?");
assert(settings[1].type == Setting.Type.group); assert(settings[1].type == Setting.Type.group);
auto group2 = cast(GroupSetting) settings[1]; auto group2 = cast(GroupSetting) settings[1];
assert(group2.children.length == 2); assert(group2.children.length == 2);
@ -594,7 +600,7 @@ Group-2:
assert(group2.children[0].type == Setting.Type.scalar); assert(group2.children[0].type == Setting.Type.scalar);
assert((cast(ScalarSetting) group2.children[0]).val == "abc"); assert((cast(ScalarSetting) group2.children[0]).val == "abc");
assert(group2.children[1].name == "Array_1"); assert(group2.children[1].name == "Array_1-2");
assert(group2.children[1].type == Setting.Type.array); assert(group2.children[1].type == Setting.Type.array);
assert((cast(ArraySetting) group2.children[1]).vals == [ "a" ]); assert((cast(ArraySetting) group2.children[1]).vals == [ "a" ]);
} }

View file

@ -13,6 +13,7 @@
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@ -172,7 +173,7 @@ bool ConfigFile::locate(std::string &pathstr) {
return false; return false;
} }
bool ConfigFile::read(const char *explicitConfFile, const char *section) { bool ConfigFile::read(const char *explicitConfFile, const char *triple) {
std::string pathstr; std::string pathstr;
// explicitly provided by user in command line? // explicitly provided by user in command line?
if (explicitConfFile) { if (explicitConfFile) {
@ -201,7 +202,7 @@ bool ConfigFile::read(const char *explicitConfFile, const char *section) {
pathcstr = strdup(pathstr.c_str()); pathcstr = strdup(pathstr.c_str());
auto binpath = exe_path::getBinDir(); auto binpath = exe_path::getBinDir();
return readConfig(pathcstr, section, binpath.c_str()); return readConfig(pathcstr, triple, binpath.c_str());
} }
void ConfigFile::extendCommandLine(llvm::SmallVectorImpl<const char *> &args) { void ConfigFile::extendCommandLine(llvm::SmallVectorImpl<const char *> &args) {
@ -219,3 +220,7 @@ void ConfigFile::extendCommandLine(llvm::SmallVectorImpl<const char *> &args) {
args.insert(runIndex == 0 ? args.end() : args.begin() + runIndex, args.insert(runIndex == 0 ? args.end() : args.begin() + runIndex,
postSwitches.begin(), postSwitches.end()); postSwitches.begin(), postSwitches.end());
} }
bool ConfigFile::sectionMatches(const char *section, const char *triple) {
return llvm::Regex(section).match(triple);
}

View file

@ -29,27 +29,28 @@ string prepareBinDir(const(char)* binDir)
return cast(string)res; // assumeUnique return cast(string)res; // assumeUnique
} }
T findSetting(T)(GroupSetting[] sections, Setting.Type type, string name)
ArraySetting findArraySetting(GroupSetting section, string name)
{ {
if (!section) return null; // lexically later sections dominate earlier ones
foreach_reverse (section; sections)
{
foreach (c; section.children) foreach (c; section.children)
{ {
if (c.type == Setting.Type.array && c.name == name) if (c.type == type && c.name == name)
return cast(ArraySetting) c; return cast(T) c;
}
} }
return null; return null;
} }
ScalarSetting findScalarSetting(GroupSetting section, string name) ArraySetting findArraySetting(GroupSetting[] sections, string name)
{ {
if (!section) return null; return findSetting!ArraySetting(sections, Setting.Type.array, name);
foreach (c; section.children) }
{
if (c.type == Setting.Type.scalar && c.name == name) ScalarSetting findScalarSetting(GroupSetting[] sections, string name)
return cast(ScalarSetting) c; {
} return findSetting!ScalarSetting(sections, Setting.Type.scalar, name);
return null;
} }
string replace(string str, string pattern, string replacement) string replace(string str, string pattern, string replacement)
@ -107,47 +108,37 @@ private:
Array!(const(char)*) postSwitches; Array!(const(char)*) postSwitches;
const(char)* rpathcstr; const(char)* rpathcstr;
bool readConfig(const(char)* cfPath, const(char)* sectionName, const(char)* binDir) static bool sectionMatches(const(char)* section, const(char)* triple);
bool readConfig(const(char)* cfPath, const(char)* triple, const(char)* binDir)
{ {
switches.setDim(0); switches.setDim(0);
postSwitches.setDim(0); postSwitches.setDim(0);
immutable dBinDir = prepareBinDir(binDir); immutable dBinDir = prepareBinDir(binDir);
const dSec = sectionName[0 .. strlen(sectionName)];
try try
{ {
GroupSetting section, defaultSection; GroupSetting[] sections; // in lexical order
foreach (s; parseConfigFile(cfPath)) foreach (s; parseConfigFile(cfPath))
{ {
if (s.type != Setting.Type.group) if (s.type == Setting.Type.group &&
continue; (s.name == "default" || sectionMatches((s.name ~ '\0').ptr, triple)))
if (s.name == dSec) {
section = cast(GroupSetting) s; sections ~= cast(GroupSetting) s;
else if (s.name == "default") }
defaultSection = cast(GroupSetting) s;
} }
if (!section && !defaultSection) if (sections.length == 0)
{ {
const dTriple = triple[0 .. strlen(triple)];
const dCfPath = cfPath[0 .. strlen(cfPath)]; const dCfPath = cfPath[0 .. strlen(cfPath)];
if (sectionName) throw new Exception("No matching section for triple '" ~ cast(string) dTriple
throw new Exception("Could not look up section '" ~ cast(string) dSec ~ "' in " ~ cast(string) dCfPath);
~ "' nor the 'default' section in " ~ cast(string) dCfPath);
else
throw new Exception("Could not look up 'default' section in " ~ cast(string) dCfPath);
} }
ArraySetting findArray(string name) auto switches = findArraySetting(sections, "switches");
{ auto postSwitches = findArraySetting(sections, "post-switches");
auto r = findArraySetting(section, name);
if (!r)
r = findArraySetting(defaultSection, name);
return r;
}
auto switches = findArray("switches");
auto postSwitches = findArray("post-switches");
if (!switches && !postSwitches) if (!switches && !postSwitches)
{ {
const dCfPath = cfPath[0 .. strlen(cfPath)]; const dCfPath = cfPath[0 .. strlen(cfPath)];
@ -170,16 +161,7 @@ private:
applyArray(this.switches, switches); applyArray(this.switches, switches);
applyArray(this.postSwitches, postSwitches); applyArray(this.postSwitches, postSwitches);
ScalarSetting findScalar(string name) if (auto rpath = findScalarSetting(sections, "rpath"))
{
auto r = findScalarSetting(section, name);
if (!r)
r = findScalarSetting(defaultSection, name);
return r;
}
auto rpath = findScalar("rpath");
if (rpath)
this.rpathcstr = (rpath.val.replace("%%ldcbinarypath%%", dBinDir) ~ '\0').ptr; this.rpathcstr = (rpath.val.replace("%%ldcbinarypath%%", dBinDir) ~ '\0').ptr;
return true; return true;
@ -191,3 +173,10 @@ private:
} }
} }
} }
unittest
{
assert(ConfigFile.sectionMatches("i[3-6]86-.*-windows-msvc", "i686-pc-windows-msvc"));
assert(ConfigFile.sectionMatches("86(_64)?-.*-linux", "x86_64--linux-gnu"));
assert(!ConfigFile.sectionMatches("^linux", "x86_64--linux-gnu"));
}

View file

@ -24,7 +24,7 @@ class ConfigFile {
public: public:
static ConfigFile instance; static ConfigFile instance;
bool read(const char *explicitConfFile, const char *section); bool read(const char *explicitConfFile, const char *triple);
llvm::StringRef path() { llvm::StringRef path() {
return pathcstr ? llvm::StringRef(pathcstr) : llvm::StringRef(); return pathcstr ? llvm::StringRef(pathcstr) : llvm::StringRef();
@ -38,9 +38,10 @@ public:
private: private:
bool locate(std::string &pathstr); bool locate(std::string &pathstr);
static bool sectionMatches(const char *section, const char *triple);
// implemented in D // implemented in D
bool readConfig(const char *cfPath, const char *section, const char *binDir); bool readConfig(const char *cfPath, const char *triple, const char *binDir);
const char *pathcstr = nullptr; const char *pathcstr = nullptr;
Array<const char *> switches; Array<const char *> switches;

View file

@ -1,7 +1,19 @@
// See comments in driver/config.d in ldc source tree for grammar description of // See comments in driver/config.d in ldc source tree for grammar description of
// this config file. // this config file.
// The default group is required // For cross-compilation, you can add sections for specific target triples by
// naming the sections as (quoted) regex patterns. See LDC's `-v` output
// (`config` line) to figure out your normalized triple, depending on the used
// `-mtriple`, `-m32` etc. E.g.:
//
// "^arm.*-linux-gnueabihf$": { … };
// "86(_64)?-.*-linux": { … };
// "i[3-6]86-.*-windows-msvc": { … };
//
// Later sections take precedence and override settings from previous matching
// sections while inheriting unspecified settings from previous sections.
// A `default` section always matches (treated as ".*") and is therefore usually
// the first section.
default: default:
{ {
// default switches injected before all explicit command-line switches // default switches injected before all explicit command-line switches

View file

@ -1,7 +1,19 @@
// See comments in driver/config.d in ldc source tree for grammar description of // See comments in driver/config.d in ldc source tree for grammar description of
// this config file. // this config file.
// The default group is required // For cross-compilation, you can add sections for specific target triples by
// naming the sections as (quoted) regex patterns. See LDC's `-v` output
// (`config` line) to figure out your normalized triple, depending on the used
// `-mtriple`, `-m32` etc. E.g.:
//
// "^arm.*-linux-gnueabihf$": { … };
// "86(_64)?-.*-linux": { … };
// "i[3-6]86-.*-windows-msvc": { … };
//
// Later sections take precedence and override settings from previous matching
// sections while inheriting unspecified settings from previous sections.
// A `default` section always matches (treated as ".*") and is therefore usually
// the first section.
default: default:
{ {
// default switches injected before all explicit command-line switches // default switches injected before all explicit command-line switches

View file

@ -1,7 +1,19 @@
// See comments in driver/config.d in ldc source tree for grammar description of // See comments in driver/config.d in ldc source tree for grammar description of
// this config file. // this config file.
// The default group is required // For cross-compilation, you can add sections for specific target triples by
// naming the sections as (quoted) regex patterns. See LDC's `-v` output
// (`config` line) to figure out your normalized triple, depending on the used
// `-mtriple`, `-m32` etc. E.g.:
//
// "^arm.*-linux-gnueabihf$": { … };
// "86(_64)?-.*-linux": { … };
// "i[3-6]86-.*-windows-msvc": { … };
//
// Later sections take precedence and override settings from previous matching
// sections while inheriting unspecified settings from previous sections.
// A `default` section always matches (treated as ".*") and is therefore usually
// the first section.
default: default:
{ {
// default switches injected before all explicit command-line switches // default switches injected before all explicit command-line switches

View file

@ -2,7 +2,7 @@
// NOSWITCHES: Could not look up switches in {{.*}}noswitches.conf // NOSWITCHES: Could not look up switches in {{.*}}noswitches.conf
// RUN: not %ldc -conf=%S/inputs/section_aaa.conf %s 2>&1 | FileCheck %s --check-prefix=NO_SEC // RUN: not %ldc -conf=%S/inputs/section_aaa.conf %s 2>&1 | FileCheck %s --check-prefix=NO_SEC
// NO_SEC: Could not look up section '{{.*}}' nor the 'default' section in {{.*}}section_aaa.conf // NO_SEC: No matching section for triple '{{.*}}' in {{.*}}section_aaa.conf
void foo() void foo()

View file

@ -1,9 +1,9 @@
x86-apple-windows-msvc:
{
switches = [ "-version" ];
};
default: default:
{ {
switches = [ "" ]; switches = [ "" ];
}; };
x86-apple-windows-msvc:
{
switches = [ "-version" ];
};