Skip to content

Commit 58c2651

Browse files
committed
Support ldc2.conf being a directory
If ldc2.conf is a directory go through each file (directly) inside it, ordered by name and apply the settings in it. It would be similar to appending all the files and treating it like a normal config file. The specific ordering is the one from llvm::StringRef::compare_numeric. The previous behavior was to always error out if ldc2.conf was a directory, being it passed through `-conf` or being automatically picked up. To account for this change the following restrictions that affect config files have been lifted: - at least one section must match the current triple This is undesirable for cross-compile setups in which one config file is dedicated to one triple - both switches and post-switches must be defined This is undesirable for config files that simply append a CLI switch The above have been replaced by a check that all settings represent valid keys (so switches, post-switches etc.) and that they are of the correct type. Signed-off-by: Andrei Horodniceanu <a.horodniceanu@proton.me>
1 parent e52a26c commit 58c2651

File tree

18 files changed

+188
-53
lines changed

18 files changed

+188
-53
lines changed

driver/configfile.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
#include "llvm/Support/Path.h"
1717
#include "llvm/Support/Regex.h"
1818
#include <cassert>
19+
#include <cstdio>
1920
#include <cstring>
2021
#include <iostream>
2122
#include <string>
23+
#include <system_error>
24+
#include <string>
2225

2326
#if _WIN32
2427
#define WIN32_LEAN_AND_MEAN
@@ -193,9 +196,43 @@ bool ConfigFile::read(const char *explicitConfFile, const char *triple) {
193196
}
194197

195198
pathcstr = strdup(pathstr.c_str());
196-
auto binpath = exe_path::getBinDir();
199+
return iterateConfigFiles(pathstr, triple);
200+
}
201+
202+
bool ConfigFile::iterateConfigFiles(const std::string &path, const char *triple) {
203+
auto bindirString = exe_path::getBinDir();
204+
auto bindir = bindirString.c_str();
205+
206+
if (sys::fs::is_directory(path)) {
207+
llvm::SmallVector<std::string, 8> configFiles;
208+
209+
std::error_code ec;
210+
auto it = sys::fs::directory_iterator(path, ec);
211+
do {
212+
if (ec) {
213+
fprintf(stderr, "Could not iterate config directory at %s: %s\n",
214+
path.c_str(), ec.message().c_str());
215+
return false;
216+
}
217+
if (it->type() != sys::fs::file_type::regular_file)
218+
continue;
219+
220+
configFiles.emplace_back(it->path());
221+
} while (it.increment(ec) != sys::fs::directory_iterator{});
222+
223+
llvm::sort(configFiles, [](const std::string &a, const std::string &b) {
224+
auto sa = llvm::StringRef(a), sb = llvm::StringRef(b);
225+
return sa.compare_numeric(sb) < 0;
226+
});
227+
228+
for (const auto &configPath: configFiles)
229+
if (!readConfig(configPath.c_str(), triple, bindir))
230+
return false;
231+
232+
return true;
233+
}
197234

198-
return readConfig(pathcstr, triple, binpath.c_str());
235+
return readConfig(pathcstr, triple, bindir);
199236
}
200237

201238
void ConfigFile::extendCommandLine(llvm::SmallVectorImpl<const char *> &args) {

driver/configfile.d

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,19 @@ string normalizeSlashes(const(char)* binDir)
2929
return cast(string)res; // assumeUnique
3030
}
3131

32-
const(string)[] findArraySetting(GroupSetting[] sections, string name)
32+
void findArraySetting(GroupSetting[] sections, string name, void delegate(const ArraySetting as) callback)
3333
{
34-
const(string)[] result = null;
3534
foreach (section; sections)
3635
{
3736
foreach (c; section.children)
3837
{
3938
if (c.type == Setting.Type.array && c.name == name)
4039
{
4140
auto as = cast(ArraySetting) c;
42-
if (as.isAppending)
43-
result ~= as.vals;
44-
else
45-
result = as.vals;
41+
callback(as);
4642
}
4743
}
4844
}
49-
return result;
5045
}
5146

5247
string findScalarSetting(GroupSetting[] sections, string name)
@@ -128,6 +123,50 @@ string replacePlaceholders(string str, CfgPaths cfgPaths)
128123
.replace("%%ldcversion%%", cast(string) global.ldc_version);
129124
}
130125

126+
/++ Check that a section only contains known config keys
127+
128+
ldc recognizes:
129+
- switches
130+
- post-switches
131+
- lib-dirs
132+
- rpath
133+
+/
134+
void validateSettingNames(const GroupSetting group, const char* filePath) {
135+
static fail(const Setting setting, const char* filePath) {
136+
string fmt(Setting.Type type) {
137+
import std.traits : EnumMembers;
138+
final switch(type) {
139+
static foreach (mem; EnumMembers!(typeof(type)))
140+
case mem:
141+
return __traits(identifier, mem);
142+
}
143+
}
144+
145+
import dmd.root.string : toDString;
146+
string msg;
147+
if (setting.type == Setting.Type.group)
148+
msg = "Nested group " ~ setting.name ~ " is unsupported";
149+
else
150+
msg = "Unknown " ~ fmt(setting.type) ~ " setting named " ~ setting.name;
151+
152+
throw new Exception(msg);
153+
}
154+
155+
alias ST = Setting.Type;
156+
const static knownSettings = [
157+
new Setting("switches", ST.array),
158+
new Setting("post-switches", ST.array),
159+
new Setting("lib-dirs", ST.array),
160+
new Setting("rpath", ST.scalar),
161+
];
162+
outer: foreach (setting; group.children) {
163+
foreach (known; knownSettings)
164+
if (setting.name == known.name && setting.type == known.type)
165+
continue outer;
166+
fail(setting, filePath);
167+
}
168+
}
169+
131170
extern(C++) struct ConfigFile
132171
{
133172
__gshared ConfigFile instance;
@@ -160,37 +199,32 @@ private:
160199
}
161200
}
162201

163-
if (sections.length == 0)
164-
{
165-
throw new Exception("No matching section for triple '" ~ cast(string) triple.toDString
166-
~ "'");
167-
}
168-
169-
const switches = findArraySetting(sections, "switches");
170-
const postSwitches = findArraySetting(sections, "post-switches");
171-
if (switches.length + postSwitches.length == 0)
172-
throw new Exception("Could not look up switches");
202+
foreach (group; sections)
203+
validateSettingNames(group, cfPath);
173204

174-
void applyArray(ref Array!(const(char)*) output, const(string)[] input)
205+
void readArraySetting(GroupSetting[] sections, string name, ref Array!(const(char)*) output)
175206
{
176-
output.setDim(0);
177-
178-
output.reserve(input.length);
179-
foreach (sw; input)
207+
void applyArray(const ArraySetting input)
180208
{
181-
const finalSwitch = sw.replacePlaceholders(cfgPaths).toCString;
182-
output.push(finalSwitch.ptr);
209+
if (!input.isAppending)
210+
output.setDim(0);
211+
212+
output.reserve(input.vals.length);
213+
foreach (sw; input.vals)
214+
{
215+
const finalSwitch = sw.replacePlaceholders(cfgPaths).toCString;
216+
output.push(finalSwitch.ptr);
217+
}
183218
}
219+
findArraySetting(sections, name, &applyArray);
184220
}
185221

186-
applyArray(this.switches, switches);
187-
applyArray(this.postSwitches, postSwitches);
188-
189-
const libDirs = findArraySetting(sections, "lib-dirs");
190-
applyArray(_libDirs, libDirs);
191-
222+
readArraySetting(sections, "switches", switches);
223+
readArraySetting(sections, "post-switches", postSwitches);
224+
readArraySetting(sections, "lib-dirs", _libDirs);
192225
const rpath = findScalarSetting(sections, "rpath");
193-
this.rpathcstr = rpath.length == 0 ? null : rpath.replacePlaceholders(cfgPaths).toCString.ptr;
226+
if (rpath.length)
227+
this.rpathcstr = rpath.replacePlaceholders(cfgPaths).toCString.ptr;
194228

195229
return true;
196230
}

driver/configfile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct ConfigFile {
4343
// implemented in D
4444
bool readConfig(const char *cfPath, const char *triple, const char *binDir);
4545

46+
bool iterateConfigFiles(const std::string &path, const char *triple);
47+
4648
const char *pathcstr = nullptr;
4749
Array<const char *> switches;
4850
Array<const char *> postSwitches;

tests/driver/config_diag.d

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
// RUN: %ldc -o- -conf=%S/inputs/noswitches.conf %s 2>&1 | FileCheck %s --check-prefix=NOSWITCHES
2-
// NOSWITCHES: Error while reading config file: {{.*}}noswitches.conf
3-
// NOSWITCHES-NEXT: Could not look up switches
4-
5-
// RUN: %ldc -o- -conf=%S/inputs/section_aaa.conf %s 2>&1 | FileCheck %s --check-prefix=NO_SEC
6-
// NO_SEC: Error while reading config file: {{.*}}section_aaa.conf
7-
// NO_SEC-NEXT: No matching section for triple '{{.*}}'
1+
// INV: %ldc -o- -conf=%S/inputs/invalid_setting.conf %s 2>&1 | FileCheck %s --check-prefix=INV_SET
2+
// INV_SET: Error while reading config file: {{.*}}invalid_setting.conf
3+
// INV_SET-NEXT: Unknown scalar setting named blah-blah
84

95
// RUN: %ldc -o- -conf=%S/inputs/invalid_append.conf %s 2>&1 | FileCheck %s --check-prefix=APP
106
// APP: Error while reading config file: {{.*}}invalid_append.conf

tests/driver/config_dir.d

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module object;
2+
3+
alias string = immutable(char)[];
4+
5+
template Version(string ident) {
6+
mixin(`version(` ~ ident ~ `)
7+
enum Version = true;
8+
else
9+
enum Version = false;
10+
`);
11+
}
12+
13+
// RUN: %ldc -d-version=TEST_ORDER -o- -conf=%S/inputs/order.conf %s 2>&1
14+
version (TEST_ORDER) {
15+
static assert(!Version!"File1");
16+
static assert(Version!"File2");
17+
static assert(!Version!"File3");
18+
}
19+
20+
// RUN: %ldc -d-version=TEST_APPENDING -o- -conf=%S/inputs/appending.conf %s 2>&1
21+
version (TEST_APPENDING) {
22+
static assert(!Version!"File1_Sec1");
23+
static assert(!Version!"File1_Sec2");
24+
25+
static assert(!Version!"File2_Sec1");
26+
static assert(Version!"File2_Sec2");
27+
28+
static assert(Version!"File3_Sec1");
29+
static assert(Version!"File3_Sec2");
30+
}
31+
32+
// RUN: not %ldc -d-version=TEST_RPATH -conf=%S/inputs/multiple_rpaths.conf -v %s 2>&1 | FileCheck %s --check-prefix=RPATHS
33+
// RPATHS: /second_rpath
34+
// RPATHS-NOT: /first_rpath
35+
version (TEST_RPATH) {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default: {
2+
switches ~= [ "-d-version=File1_Sec1" ]
3+
}
4+
5+
".?": {
6+
switches = [ "-d-version=File1_Sec2" ]
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default: {
2+
switches ~= [ "-d-version=File2_Sec1" ]
3+
}
4+
5+
".?": {
6+
switches = [ "-d-version=File2_Sec2" ]
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default: {
2+
switches ~= [ "-d-version=File3_Sec1" ]
3+
}
4+
5+
".?": {
6+
switches ~= [ "-d-version=File3_Sec2" ]
7+
}

tests/driver/inputs/invalid_append.conf

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,3 @@ default:
22
{
33
rpath ~= "/path";
44
}
5-
6-
default:
7-
{
8-
switches = [];
9-
post-switches = [];
10-
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
default:
2+
{
3+
blah-blah = "12";
4+
};

0 commit comments

Comments
 (0)