Skip to content

Commit 4cd6f18

Browse files
committed
Auto-generate oldnames.c from special MinGW .def directives
1 parent 8d3df83 commit 4cd6f18

File tree

2 files changed

+68
-172
lines changed

2 files changed

+68
-172
lines changed

windows/mingw/buildsdk.d

+68-32
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// source files extracted from MinGW-w64:
1111
// https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/mingw-w64-v6.0.0.tar.bz2
1212
//
13-
// assumes VC tools cl,link,lib and ml installed and found through path
13+
// assumes VC tools cl, lib and ml installed and found through path
1414
// and configured to the appropriate architecture
1515
//
1616

@@ -24,6 +24,10 @@ import std.string;
2424

2525
version = verbose;
2626

27+
bool x64;
28+
string[string] weakSymbols; // weak name => real name
29+
30+
2731
void runShell(string cmd)
2832
{
2933
version (verbose)
@@ -38,7 +42,7 @@ void runShell(string cmd)
3842
}
3943

4044
// Preprocesses a 'foo.def.in' file to 'foo.def'.
41-
void generateDef(bool x64, string inFile, string outFile)
45+
void generateDef(string inFile, string outFile)
4246
{
4347
const includeDir = buildPath(dirName(dirName(inFile)), "def-include");
4448
const archDefine = x64 ? "DEF_X64" : "DEF_I386";
@@ -54,12 +58,22 @@ void sanitizeDef(string defFile)
5458
{
5559
string l = line;
5660

57-
// The MinGW-w64 .def files specify renamings as 'exportedName == realName'.
58-
// The MS format is 'exportedName=realName'.
59-
l = l.replace(" == ", "=");
61+
// The MinGW-w64 .def files specify weak external symbols as 'alias == realName'.
62+
if (l.length > 1 && l[0] != ';')
63+
{
64+
const i = l.indexOf(" == ");
65+
if (i > 0)
66+
{
67+
const weakName = l[0 .. i];
68+
const realName = l[i+4 .. $];
69+
weakSymbols[weakName] = realName;
70+
71+
l = ";" ~ l;
72+
}
73+
}
6074

6175
// Don't export function 'atexit'; we have our own in msvc_atexit.c.
62-
if (l == "atexit" /* 120 */ || l == "atexit DATA" /* < 120 */)
76+
if (l == "atexit" /* msvcr120 */ || l == "atexit DATA" /* < 120 */)
6377
l = "";
6478

6579
// Do export function '__chkstk' (ntdll.dll).
@@ -77,7 +91,7 @@ void sanitizeDef(string defFile)
7791
std.file.write(defFile, newLines.join("\n"));
7892
}
7993

80-
void copyDefs(bool x64, string inDir, string outDir)
94+
void copyDefs(string inDir, string outDir)
8195
{
8296
mkdirRecurse(outDir);
8397

@@ -90,7 +104,7 @@ void copyDefs(bool x64, string inDir, string outDir)
90104
if (lowerPath.endsWith(".def.in"))
91105
{
92106
outFile = buildPath(outDir, baseName(f.name)[0 .. $-7] ~ ".def");
93-
generateDef(x64, path, outFile);
107+
generateDef(path, outFile);
94108
}
95109
else if (lowerPath.endsWith(".def"))
96110
{
@@ -103,78 +117,100 @@ void copyDefs(bool x64, string inDir, string outDir)
103117
}
104118
}
105119

106-
void def2implib(bool x64, string defFile)
120+
void def2implib(string defFile)
107121
{
108122
const libFile = setExtension(defFile, ".lib");
109123
const arch = x64 ? "X64" : "X86";
110124
runShell(`lib /MACHINE:` ~ arch ~ ` "/DEF:` ~ defFile ~ `" "/OUT:` ~ libFile ~ `"`);
111125
std.file.remove(setExtension(defFile, ".exp"));
112126
}
113127

114-
void defs2implibs(bool x64, string dir)
128+
void defs2implibs(string dir)
115129
{
116130
foreach (f; std.file.dirEntries(dir, SpanMode.shallow))
117131
{
118132
const path = f.name;
119133
if (toLower(path).endsWith(".def"))
120-
def2implib(x64, path);
134+
def2implib(path);
121135
}
122136
}
123137

124-
void buildMsvcrt(bool x64, string outDir)
138+
void buildMsvcrt(string outDir)
125139
{
126140
outDir ~= "/";
127141
const cl = "cl /c /Zl ";
128142
const lib = "lib /MACHINE:" ~ (x64 ? "X64" : "X86") ~ " ";
129143

130144
// compile some additional objects to be merged into the msvcr*.lib files
131-
runShell(cl ~ "/Fo" ~ outDir ~ "msvcrt_stub0.obj /D_APPTYPE=0 msvcrt_stub.c");
132-
runShell(cl ~ "/Fo" ~ outDir ~ "msvcrt_stub1.obj /D_APPTYPE=1 msvcrt_stub.c");
133-
runShell(cl ~ "/Fo" ~ outDir ~ "msvcrt_stub2.obj /D_APPTYPE=2 msvcrt_stub.c");
134-
runShell(cl ~ "/Fo" ~ outDir ~ "msvcrt_data.obj msvcrt_data.c");
135-
runShell(cl ~ "/Fo" ~ outDir ~ "msvcrt_atexit.obj msvcrt_atexit.c");
145+
runShell(cl ~ `"/Fo` ~ outDir ~ `msvcrt_stub0.obj" /D_APPTYPE=0 msvcrt_stub.c`);
146+
runShell(cl ~ `"/Fo` ~ outDir ~ `msvcrt_stub1.obj" /D_APPTYPE=1 msvcrt_stub.c`);
147+
runShell(cl ~ `"/Fo` ~ outDir ~ `msvcrt_stub2.obj" /D_APPTYPE=2 msvcrt_stub.c`);
148+
runShell(cl ~ `"/Fo` ~ outDir ~ `msvcrt_data.obj" msvcrt_data.c`);
149+
runShell(cl ~ `"/Fo` ~ outDir ~ `msvcrt_atexit.obj" msvcrt_atexit.c`);
136150
auto objs = [ "msvcrt_stub0.obj", "msvcrt_stub1.obj", "msvcrt_stub2.obj", "msvcrt_data.obj", "msvcrt_atexit.obj" ];
137151
if (!x64)
138152
{
139-
runShell("ml /c /Fo" ~ outDir ~ "msvcrt_abs.obj msvcrt_abs.asm");
153+
runShell(`ml /c "/Fo` ~ outDir ~ `msvcrt_abs.obj" msvcrt_abs.asm`);
140154
objs ~= "msvcrt_abs.obj";
141155
}
142156

143157
// merge into libs
144-
const additionalMsvcrtObjs = objs.map!(a => outDir ~ a).join(" ");
158+
const additionalMsvcrtObjs = objs.map!(a => `"` ~ outDir ~ a ~ `"`).join(" ");
145159
foreach (f; std.file.dirEntries(outDir[0 .. $-1], "msvcr*.lib", SpanMode.shallow))
146-
runShell(lib ~ f.name ~ " " ~ additionalMsvcrtObjs);
147-
148-
// create oldnames.lib (expected by dmd)
149-
runShell(cl ~ "/Fo" ~ outDir ~ "oldnames.obj oldnames.c");
150-
runShell(lib ~ "/OUT:" ~ outDir ~ "oldnames.lib " ~ outDir ~ "oldnames.obj");
151-
objs ~= "oldnames.obj";
160+
runShell(lib ~ `"` ~ f.name ~ `" ` ~ additionalMsvcrtObjs);
152161

153162
// create empty uuid.lib (expected by dmd, but UUIDs already in druntime)
154163
std.file.write(outDir ~ "empty.c", "");
155-
runShell(cl ~ "/Fo" ~ outDir ~ "uuid.obj " ~ outDir ~ "empty.c");
156-
runShell(lib ~ "/OUT:" ~ outDir ~ "uuid.lib " ~ outDir ~ "uuid.obj");
164+
runShell(cl ~ `"/Fo` ~ outDir ~ `uuid.obj" "` ~ outDir ~ `empty.c"`);
165+
runShell(lib ~ `"/OUT:` ~ outDir ~ `uuid.lib" "` ~ outDir ~ `uuid.obj"`);
157166
objs ~= "uuid.obj";
158167
std.file.remove(outDir ~ "empty.c");
159168

160169
foreach (f; objs)
161170
std.file.remove(outDir ~ f);
162171
}
163172

173+
void buildOldnames(string outDir)
174+
{
175+
const cPrefix = x64 ? "" : "_";
176+
const oldnames_c =
177+
// access this __ref_oldnames symbol to drag in the generated linker directives (msvcrt_stub.c)
178+
"int __ref_oldnames;\n" ~
179+
weakSymbols.byKeyValue.map!(pair =>
180+
`__pragma(comment(linker, "/alternatename:` ~ cPrefix ~ pair.key ~ `=` ~ cPrefix ~ pair.value ~ `"));`
181+
).join("\n");
182+
183+
version (verbose)
184+
writeln("\nAuto-generated oldnames.c:\n----------\n", oldnames_c, "\n----------\n");
185+
186+
const src = buildPath(outDir, "oldnames.c");
187+
std.file.write(src, oldnames_c);
188+
189+
const obj = setExtension(src, ".obj");
190+
runShell(`cl /c /Zl "/Fo` ~ obj ~ `" "` ~ src ~ `"`);
191+
192+
const lib = setExtension(src, ".lib");
193+
runShell(`lib /MACHINE:` ~ (x64 ? "X64" : "X86") ~ ` "/OUT:` ~ lib ~ `" "` ~ obj ~ `"`);
194+
195+
std.file.remove(src);
196+
std.file.remove(obj);
197+
}
198+
164199
void main(string[] args)
165200
{
166-
const x64 = (args.length > 1 && args[1] == "x64");
201+
x64 = (args.length > 1 && args[1] == "x64");
167202
const mingwDir = (args.length > 2 ? args[2] : "mingw-w64");
168203
string outDir = x64 ? "lib64" : "lib32";
169204
if (args.length > 3)
170205
outDir = args[3];
171206

172-
copyDefs(x64, buildPath(mingwDir, "mingw-w64-crt", "lib-common"), outDir);
173-
copyDefs(x64, buildPath(mingwDir, "mingw-w64-crt", "lib" ~ (x64 ? "64" : "32")), outDir);
207+
copyDefs(buildPath(mingwDir, "mingw-w64-crt", "lib-common"), outDir);
208+
copyDefs(buildPath(mingwDir, "mingw-w64-crt", "lib" ~ (x64 ? "64" : "32")), outDir);
174209

175-
defs2implibs(x64, outDir);
210+
defs2implibs(outDir);
176211

177-
buildMsvcrt(x64, outDir);
212+
buildMsvcrt(outDir);
213+
buildOldnames(outDir);
178214

179215
//version (verbose) {} else
180216
foreach (f; std.file.dirEntries(outDir, "*.def", SpanMode.shallow))

windows/mingw/oldnames.c

-140
This file was deleted.

0 commit comments

Comments
 (0)