1
0
mirror of https://github.com/skeeto/w64devkit.git synced 2025-07-31 15:04:21 +03:00

Upgrade to u-config 0.30.2

System import libraries are handled a little better, namely the linker
order, when using multiple packages at a time.
This commit is contained in:
Christopher Wellons
2023-01-30 10:30:55 -05:00
parent 63418a5589
commit 18542a50fc

View File

@ -6,7 +6,7 @@
// Fundamental definitions // Fundamental definitions
#define VERSION "0.30.1" #define VERSION "0.30.2"
typedef int Size; typedef int Size;
#define Size_MASK ((unsigned)-1) #define Size_MASK ((unsigned)-1)
@ -858,14 +858,33 @@ static void usage(Out *out)
outstr(out, S(usage)); outstr(out, S(usage));
} }
typedef struct SearchNode { typedef struct StrListNode {
struct SearchNode *next; struct StrListNode *next;
Str dir; Str entry;
} SearchNode; } StrListNode;
typedef struct { typedef struct {
SearchNode *head; StrListNode *head;
SearchNode *tail; StrListNode *tail;
} StrList;
static void append(Arena *a, StrList *list, Str str)
{
StrListNode *node = (StrListNode *)alloc(a, SIZEOF(*node));
node->next = 0;
node->entry = str;
if (list->tail) {
ASSERT(list->head);
list->tail->next = node;
} else {
ASSERT(!list->tail);
list->head = node;
}
list->tail = node;
}
typedef struct {
StrList list;
Byte delim; Byte delim;
} Search; } Search;
@ -876,28 +895,13 @@ static Search newsearch(Byte delim)
return r; return r;
} }
static void appenddir(Arena *a, Search *dirs, Str dir)
{
SearchNode *node = (SearchNode *)alloc(a, SIZEOF(*node));
node->dir = dir;
node->next = 0;
if (dirs->tail) {
ASSERT(dirs->head);
dirs->tail->next = node;
} else {
ASSERT(!dirs->tail);
dirs->head = node;
}
dirs->tail = node;
}
static void appendpath(Arena *a, Search *dirs, Str path) static void appendpath(Arena *a, Search *dirs, Str path)
{ {
while (path.len) { while (path.len) {
Cut c = cut(path, dirs->delim); Cut c = cut(path, dirs->delim);
Str dir = c.head; Str dir = c.head;
if (dir.len) { if (dir.len) {
appenddir(a, dirs, dir); append(a, &dirs->list, dir);
} }
path = c.tail; path = c.tail;
} }
@ -905,15 +909,15 @@ static void appendpath(Arena *a, Search *dirs, Str path)
static void prependpath(Arena *a, Search *dirs, Str path) static void prependpath(Arena *a, Search *dirs, Str path)
{ {
if (!dirs->head) { if (!dirs->list.head) {
// Empty, so appending is the same a prepending // Empty, so appending is the same a prepending
appendpath(a, dirs, path); appendpath(a, dirs, path);
} else { } else {
// Append to an empty Search, then transplant it // Append to an empty Search, then transplant in front
Search temp = newsearch(dirs->delim); Search temp = newsearch(dirs->delim);
appendpath(a, &temp, path); appendpath(a, &temp, path);
temp.tail->next = dirs->head; temp.list.tail->next = dirs->list.head;
dirs->head = temp.head; dirs->list.head = temp.list.head;
} }
} }
@ -1064,8 +1068,8 @@ static Pkg findpackage(Arena *a, Search *dirs, Out *err, Str realname)
} }
} }
for (SearchNode *n = dirs->head; n && !contents.s; n = n->next) { for (StrListNode *n = dirs->list.head; n && !contents.s; n = n->next) {
path = buildpath(a, n->dir, realname); path = buildpath(a, n->entry, realname);
contents = readpackage(a, err, path, realname); contents = readpackage(a, err, path, realname);
path = cuttail(path, 1); // remove null terminator path = cuttail(path, 1); // remove null terminator
} }
@ -1583,50 +1587,83 @@ static void msvcize(Out *out, Str arg)
typedef struct { typedef struct {
Treap node; Treap node;
Bool present; Size position;
} StrSetEntry; } ArgsNode;
typedef struct { typedef struct {
Treap *set; StrList list;
} StrSet; Treap *map;
Size count;
} Args;
// Try to insert the string into the set, returning true on success. static Bool dedupable(Str arg)
static Bool insertstr(Arena *a, StrSet *set, Str s)
{ {
StrSetEntry *e = (StrSetEntry *)treapinsert(a, &set->set, s, SIZEOF(*e)); // Do not count "-I" or "-L" with detached argument
if (!e->present) { if (arg.len<3 || arg.s[0]!='-') {
e->present = 1; return 0;
} else if (equals(arg, S("-pthread"))) {
return 1; return 1;
} }
Str flags = S("DILflm");
for (Size i = 0; i < flags.len; i++) {
if (arg.s[1] == flags.s[i]) {
return 1;
}
}
return 0; return 0;
} }
static void appendarg(Arena *a, Args *args, Str arg)
{
Size position = args->count++;
append(a, &args->list, arg);
if (dedupable(arg)) {
ArgsNode *n = (ArgsNode *)treapinsert(a, &args->map, arg, SIZEOF(*n));
if (!n->position || startswith(arg, S("-l"))) {
// Zero position reserved for null, so bias it by 1
n->position = 1 + position;
}
}
}
static void excludearg(Arena *a, Args *args, Str arg)
{
ArgsNode *n = (ArgsNode *)treapinsert(a, &args->map, arg, SIZEOF(*n));
n->position = -1; // i.e. position before first argument
}
// Is this the correct position for the given argument?
static Bool inposition(Args *args, Str arg, Size position)
{
ArgsNode *n = (ArgsNode *)treapinsert(0, &args->map, arg, SIZEOF(*n));
return !n || n->position==position+1;
}
typedef struct { typedef struct {
Arena *arena; Arena *arena;
Out *out; Size *argcount;
Out *err; Args args;
Size count;
StrSet seen;
Filter filter; Filter filter;
Bool msvc; Bool msvc;
Byte delim; Byte delim;
} OutConfig; } FieldWriter;
static OutConfig newoutconf(Arena *a, Out *out, Out *err) static FieldWriter newfieldwriter(Arena *a, Filter filter, Size *argcount)
{ {
OutConfig r = {a, out, err, 0, {0}, Filter_ANY, 0, ' '}; FieldWriter w = {0};
return r; w.arena = a;
w.filter = filter;
w.argcount = argcount;
return w;
} }
static void insertsyspath(OutConfig *conf, Str path, Byte delim, Byte flag) static void insertsyspath(FieldWriter *w, Str path, Byte delim, Byte flag)
{ {
Arena *a = w->arena;
Byte flagbuf[] = {'-', flag}; Byte flagbuf[] = {'-', flag};
Str prefix = {flagbuf, SIZEOF(flagbuf)}; Str prefix = {flagbuf, SIZEOF(flagbuf)};
while (path.len) { while (path.len) {
// Allocations are tentative and may be discarded
Arena save = *conf->arena;
Cut c = cut(path, delim); Cut c = cut(path, delim);
Str dir = c.head; Str dir = c.head;
path = c.tail; path = c.tail;
@ -1635,12 +1672,12 @@ static void insertsyspath(OutConfig *conf, Str path, Byte delim, Byte flag)
} }
// Prepend option flag // Prepend option flag
Str syspath = newstr(&save, prefix.len+dir.len); Str syspath = newstr(a, prefix.len+dir.len);
copy(copy(syspath, prefix), dir); copy(copy(syspath, prefix), dir);
// Process as an argument, as though being printed // Process as an argument, as though being printed
syspath = maybequote(&save, syspath); syspath = maybequote(a, syspath);
DequoteResult dr = dequote(&save, syspath); DequoteResult dr = dequote(a, syspath);
syspath = dr.arg; syspath = dr.arg;
// NOTE(NRK): Technically, the path doesn't need to follow the flag // NOTE(NRK): Technically, the path doesn't need to follow the flag
@ -1651,43 +1688,52 @@ static void insertsyspath(OutConfig *conf, Str path, Byte delim, Byte flag)
// handling this edge-case. As a proof that this should be fine in // handling this edge-case. As a proof that this should be fine in
// practice, `pkgconf` which is used by many distros, also doesn't // practice, `pkgconf` which is used by many distros, also doesn't
// handle it. // handle it.
if (dr.ok && !dr.tail.len && insertstr(&save, &conf->seen, syspath)) { if (dr.ok && !dr.tail.len) {
*conf->arena = save; excludearg(a, &w->args, syspath);
} }
} }
} }
// Process the field while writing it to the output. static void appendfield(Out *err, FieldWriter *w, Pkg *p, Str field)
static void fieldout(OutConfig *conf, Pkg *p, Str field)
{ {
Arena *a = conf->arena; Arena *a = w->arena;
Filter f = conf->filter; Filter f = w->filter;
while (field.len) { while (field.len) {
Arena tentative = *a; DequoteResult r = dequote(a, field);
DequoteResult r = dequote(&tentative, field);
if (!r.ok) { if (!r.ok) {
outstr(conf->err, S("pkg-config: ")); outstr(err, S("pkg-config: "));
outstr(conf->err, S("unmatched quote in '")); outstr(err, S("unmatched quote in '"));
outstr(conf->err, p->realname); outstr(err, p->realname);
outstr(conf->err, S("'\n")); outstr(err, S("'\n"));
flush(conf->err); flush(err);
os_fail(); os_fail();
} }
if (filterok(f, r.arg) && insertstr(&tentative, &conf->seen, r.arg)) { if (filterok(f, r.arg)) {
*a = tentative; // keep the allocations appendarg(a, &w->args, r.arg);
if (conf->count++) {
outbyte(conf->out, conf->delim);
}
if (conf->msvc) {
msvcize(conf->out, r.arg);
} else {
outstr(conf->out, r.arg);
}
} }
field = r.tail; field = r.tail;
} }
} }
static void writeargs(Out *out, FieldWriter *w)
{
Size position = 0;
Byte delim = w->delim ? w->delim : ' ';
for (StrListNode *n = w->args.list.head; n; n = n->next) {
Str arg = n->entry;
if (inposition(&w->args, arg, position++)) {
if ((*w->argcount)++) {
outbyte(out, delim);
}
if (w->msvc) {
msvcize(out, arg);
} else {
outstr(out, arg);
}
}
}
}
static int parseuint(Str s, int hi) static int parseuint(Str s, int hi)
{ {
int v = 0; int v = 0;
@ -1715,12 +1761,14 @@ static void appmain(Config conf)
Out out = newoutput(a, 1, 1<<12); Out out = newoutput(a, 1, 1<<12);
Out err = newoutput(a, 2, 1<<7); Out err = newoutput(a, 2, 1<<7);
Processor proc = newprocessor(&conf, &err, &global, &pkgs); Processor proc = newprocessor(&conf, &err, &global, &pkgs);
OutConfig outconf = newoutconf(a, &out, &err); Size argcount = 0;
Bool msvc = 0;
Bool libs = 0; Bool libs = 0;
Bool cflags = 0; Bool cflags = 0;
Bool silent = 0; Bool silent = 0;
Bool static_ = 0; Bool static_ = 0;
Byte argdelim = ' ';
Bool modversion = 0; Bool modversion = 0;
Bool print_sysinc = 0; Bool print_sysinc = 0;
Bool print_syslib = 0; Bool print_syslib = 0;
@ -1819,7 +1867,7 @@ static void appmain(Config conf)
proc.maxdepth = parseuint(r.value, 1000); proc.maxdepth = parseuint(r.value, 1000);
} else if (equals(r.arg, S("-msvc-syntax"))) { } else if (equals(r.arg, S("-msvc-syntax"))) {
outconf.msvc = 1; msvc = 1;
} else if (equals(r.arg, S("-define-variable"))) { } else if (equals(r.arg, S("-define-variable"))) {
if (!r.value.s) { if (!r.value.s) {
@ -1837,7 +1885,7 @@ static void appmain(Config conf)
*insert(a, &global, c.head) = c.tail; *insert(a, &global, c.head) = c.tail;
} else if (equals(r.arg, S("-newlines"))) { } else if (equals(r.arg, S("-newlines"))) {
outconf.delim = '\n'; argdelim = '\n';
} else if (equals(r.arg, S("-exists"))) { } else if (equals(r.arg, S("-exists"))) {
// The check already happens, just disable the messages // The check already happens, just disable the messages
@ -1879,14 +1927,6 @@ static void appmain(Config conf)
err = newnullout(); err = newnullout();
} }
if (!print_sysinc) {
insertsyspath(&outconf, conf.sys_incpath, conf.delim, 'I');
}
if (!print_syslib) {
insertsyspath(&outconf, conf.sys_libpath, conf.delim, 'L');
}
for (Size i = 0; i < nargs; i++) { for (Size i = 0; i < nargs; i++) {
process(a, &proc, args[i]); process(a, &proc, args[i]);
} }
@ -1921,22 +1961,36 @@ static void appmain(Config conf)
} }
if (cflags) { if (cflags) {
outconf.filter = filterc; Arena temp = *a; // auto-free when done
for (Pkg *p = pkgs.head; p; p = p->list) { FieldWriter fw = newfieldwriter(&temp, filterc, &argcount);
fieldout(&outconf, p, p->cflags); fw.delim = argdelim;
fw.msvc = msvc;
if (!print_sysinc) {
insertsyspath(&fw, conf.sys_incpath, conf.delim, 'I');
} }
for (Pkg *p = pkgs.head; p; p = p->list) {
appendfield(&err, &fw, p, p->cflags);
}
writeargs(&out, &fw);
} }
if (libs) { if (libs) {
outconf.filter = filterl; Arena temp = *a; // auto-free when done
FieldWriter fw = newfieldwriter(&temp, filterl, &argcount);
fw.delim = argdelim;
fw.msvc = msvc;
if (!print_syslib) {
insertsyspath(&fw, conf.sys_libpath, conf.delim, 'L');
}
for (Pkg *p = pkgs.head; p; p = p->list) { for (Pkg *p = pkgs.head; p; p = p->list) {
if (static_) { if (static_) {
fieldout(&outconf, p, p->libs); appendfield(&err, &fw, p, p->libs);
fieldout(&outconf, p, p->libsprivate); appendfield(&err, &fw, p, p->libsprivate);
} else if (p->flags & Pkg_PUBLIC) { } else if (p->flags & Pkg_PUBLIC) {
fieldout(&outconf, p, p->libs); appendfield(&err, &fw, p, p->libs);
} }
} }
writeargs(&out, &fw);
} }
if (cflags || libs) { if (cflags || libs) {