10
10
// source files extracted from MinGW-w64:
11
11
// https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/mingw-w64-v6.0.0.tar.bz2
12
12
//
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
14
14
// and configured to the appropriate architecture
15
15
//
16
16
@@ -24,6 +24,10 @@ import std.string;
24
24
25
25
version = verbose;
26
26
27
+ bool x64;
28
+ string [string ] weakSymbols; // weak name => real name
29
+
30
+
27
31
void runShell (string cmd)
28
32
{
29
33
version (verbose)
@@ -38,7 +42,7 @@ void runShell(string cmd)
38
42
}
39
43
40
44
// 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)
42
46
{
43
47
const includeDir = buildPath(dirName(dirName(inFile)), " def-include" );
44
48
const archDefine = x64 ? " DEF_X64" : " DEF_I386" ;
@@ -54,12 +58,22 @@ void sanitizeDef(string defFile)
54
58
{
55
59
string l = line;
56
60
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
+ }
60
74
61
75
// 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 */ )
63
77
l = " " ;
64
78
65
79
// Do export function '__chkstk' (ntdll.dll).
@@ -77,7 +91,7 @@ void sanitizeDef(string defFile)
77
91
std.file.write (defFile, newLines.join(" \n " ));
78
92
}
79
93
80
- void copyDefs (bool x64, string inDir, string outDir)
94
+ void copyDefs (string inDir, string outDir)
81
95
{
82
96
mkdirRecurse(outDir);
83
97
@@ -90,7 +104,7 @@ void copyDefs(bool x64, string inDir, string outDir)
90
104
if (lowerPath.endsWith(" .def.in" ))
91
105
{
92
106
outFile = buildPath(outDir, baseName(f.name)[0 .. $- 7 ] ~ " .def" );
93
- generateDef(x64, path, outFile);
107
+ generateDef(path, outFile);
94
108
}
95
109
else if (lowerPath.endsWith(" .def" ))
96
110
{
@@ -103,78 +117,100 @@ void copyDefs(bool x64, string inDir, string outDir)
103
117
}
104
118
}
105
119
106
- void def2implib (bool x64, string defFile)
120
+ void def2implib (string defFile)
107
121
{
108
122
const libFile = setExtension(defFile, " .lib" );
109
123
const arch = x64 ? " X64" : " X86" ;
110
124
runShell(` lib /MACHINE:` ~ arch ~ ` "/DEF:` ~ defFile ~ ` " "/OUT:` ~ libFile ~ ` "` );
111
125
std.file.remove (setExtension(defFile, " .exp" ));
112
126
}
113
127
114
- void defs2implibs (bool x64, string dir)
128
+ void defs2implibs (string dir)
115
129
{
116
130
foreach (f; std.file.dirEntries (dir, SpanMode.shallow))
117
131
{
118
132
const path = f.name;
119
133
if (toLower(path).endsWith(" .def" ))
120
- def2implib(x64, path);
134
+ def2implib(path);
121
135
}
122
136
}
123
137
124
- void buildMsvcrt (bool x64, string outDir)
138
+ void buildMsvcrt (string outDir)
125
139
{
126
140
outDir ~= " /" ;
127
141
const cl = " cl /c /Zl " ;
128
142
const lib = " lib /MACHINE:" ~ (x64 ? " X64" : " X86" ) ~ " " ;
129
143
130
144
// 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` );
136
150
auto objs = [ " msvcrt_stub0.obj" , " msvcrt_stub1.obj" , " msvcrt_stub2.obj" , " msvcrt_data.obj" , " msvcrt_atexit.obj" ];
137
151
if (! x64)
138
152
{
139
- runShell(" ml /c /Fo" ~ outDir ~ " msvcrt_abs.obj msvcrt_abs.asm" );
153
+ runShell(` ml /c " /Fo` ~ outDir ~ ` msvcrt_abs.obj" msvcrt_abs.asm` );
140
154
objs ~= " msvcrt_abs.obj" ;
141
155
}
142
156
143
157
// merge into libs
144
- const additionalMsvcrtObjs = objs.map! (a => outDir ~ a).join(" " );
158
+ const additionalMsvcrtObjs = objs.map! (a => ` " ` ~ outDir ~ a ~ ` " ` ).join(" " );
145
159
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);
152
161
153
162
// create empty uuid.lib (expected by dmd, but UUIDs already in druntime)
154
163
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"` );
157
166
objs ~= " uuid.obj" ;
158
167
std.file.remove (outDir ~ " empty.c" );
159
168
160
169
foreach (f; objs)
161
170
std.file.remove (outDir ~ f);
162
171
}
163
172
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(" \n Auto-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
+
164
199
void main (string [] args)
165
200
{
166
- const x64 = (args.length > 1 && args[1 ] == " x64" );
201
+ x64 = (args.length > 1 && args[1 ] == " x64" );
167
202
const mingwDir = (args.length > 2 ? args[2 ] : " mingw-w64" );
168
203
string outDir = x64 ? " lib64" : " lib32" ;
169
204
if (args.length > 3 )
170
205
outDir = args[3 ];
171
206
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);
174
209
175
- defs2implibs(x64, outDir);
210
+ defs2implibs(outDir);
176
211
177
- buildMsvcrt(x64, outDir);
212
+ buildMsvcrt(outDir);
213
+ buildOldnames(outDir);
178
214
179
215
// version (verbose) {} else
180
216
foreach (f; std.file.dirEntries (outDir, " *.def" , SpanMode.shallow))
0 commit comments