11//
2- // Convert MingGW-w64 definition files to COFF import librries
2+ // Convert MingGW-w64 definition files to COFF import libraries
33//
44// Distributed under the Boost Software License, Version 1.0.
55// (See accompanying file LICENSE_1_0.txt or copy at
@@ -85,9 +85,47 @@ void generateDef(string inFile, string outFile)
8585
8686void sanitizeDef (string defFile)
8787{
88+ // The MinGW runtime overrides some functions and hides the original
89+ // functions by appending a ' DATA' suffix in the .def files.
90+ static __gshared const overriddenMinGWFunctions =
91+ [
92+ // ucrtbase.def:
93+ " _assert" , " _cabs" , " _fpreset" , " _tzset" ,
94+ " ceil" , " ceilf" , " coshf" , " fabs" ,
95+ " floor" , " floorf" , " modf" , " modff" ,
96+ " sinhf" , " sqrt" , " sqrtf" , " wcsnlen" ,
97+ // additional ones in msvcr100.def:
98+ " __report_gsfailure" ,
99+ " _byteswap_uint64" , " _byteswap_ulong" , " _byteswap_ushort" ,
100+ " _difftime32" , " _difftime64" ,
101+ " _fseeki64" , " _ftelli64" ,
102+ " _get_errno" ,
103+ " _rotl64" , " _rotr64" ,
104+ " _set_errno" ,
105+ " _wassert" ,
106+ " acosf" , " asinf" , " atan2" , " atan2f" , " atanf" ,
107+ " btowc" ,
108+ " cos" , " cosf" , " exp" , " expf" , " fmod" , " fmodf" , " ldexp" ,
109+ " longjmp" ,
110+ " llabs" , " lldiv" ,
111+ " log" , " log10f" , " logf" ,
112+ " mbrlen" , " mbrtowc" , " mbsrtowcs" ,
113+ " pow" , " powf" ,
114+ " sin" , " sinf" ,
115+ " strnlen" ,
116+ " tanf" , " tanhf" ,
117+ " wcrtomb" , " wcsrtombs" , " wctob" ,
118+ ];
119+
88120 patchLines(defFile, defFile, (line)
89121 {
90- if (line.length == 0 || line[0 ] == ' ;' )
122+ if (line.length == 0 )
123+ return line;
124+
125+ if (line == " ; strnlen replaced by emu" )
126+ return " strnlen" ;
127+
128+ if (line[0 ] == ' ;' )
91129 return line;
92130
93131 if (line == " LIBRARY vcruntime140_app" )
@@ -107,14 +145,12 @@ void sanitizeDef(string defFile)
107145 }
108146 }
109147
110- // The MinGW runtime apparently replaces ceil(f)/floor(f) and hides the original functions via DATA.
111- if (line == " ceil DATA" || line == " ceilf DATA" ||
112- line == " floor DATA" || line == " floorf DATA" )
113- return line[0 .. $- 5 ];
114-
115- // MinGW apparently also replaces ucrtbase.dll's '_tzset'.
116- if (line == " _tzset DATA" )
117- return " _tzset" ;
148+ // Un-hide functions overridden by the MinGW runtime.
149+ foreach (name; overriddenMinGWFunctions)
150+ {
151+ if (line.length == name.length + 5 && line.startsWith(name) && line.endsWith(" DATA" ))
152+ return name;
153+ }
118154
119155 // Don't export function 'atexit'; we have our own in msvc_atexit.c.
120156 if (line == " atexit" )
@@ -167,8 +203,7 @@ void def2implib(string defFile)
167203 }
168204
169205 const libFile = setExtension(defFile, " .lib" );
170- const arch = x64 ? " X64" : " X86" ;
171- runShell(` lib /MACHINE:` ~ arch ~ ` "/DEF:` ~ defFile ~ ` " "/OUT:` ~ libFile ~ ` "` );
206+ runShell(` lib "/DEF:` ~ defFile ~ ` " "/OUT:` ~ libFile ~ ` "` );
172207 std.file.remove (setExtension(defFile, " .exp" ));
173208}
174209
@@ -309,13 +344,12 @@ void c2lib(string outDir, string cFile)
309344 const obj = buildPath(outDir, baseName(cFile).setExtension(" .obj" ));
310345 const lib = setExtension(obj, " .lib" );
311346 cl(obj, quote (cFile));
312- runShell(` lib /MACHINE: ` ~ (x64 ? " X64 " : " X86 " ) ~ ` " /OUT:` ~ lib ~ ` " " ` ~ obj ~ ` " ` );
347+ runShell(` lib " /OUT:` ~ lib ~ ` " ` ~ quote( obj) );
313348 std.file.remove (obj);
314349}
315350
316351void buildMsvcrt (string outDir)
317352{
318- const arch = x64 ? " X64" : " X86" ;
319353 foreach (lib; std.file.dirEntries (outDir, " *.lib" , SpanMode.shallow))
320354 {
321355 const lowerBase = toLower(baseName(lib.name));
@@ -325,7 +359,9 @@ void buildMsvcrt(string outDir)
325359 // parse version from filename (e.g., 140 for VC++ 2015)
326360 const versionStart = lowerBase[0 ] == ' m' ? 5 : 9 ;
327361 const versionLength = lowerBase[versionStart .. $].countUntil! (c => ! isDigit(c));
328- const msvcrtVersion = versionLength == 0 ? " 0" : lowerBase[versionStart .. versionStart+ versionLength];
362+ const msvcrtVersion = versionLength == 0
363+ ? " 70" // msvcrt.lib
364+ : lowerBase[versionStart .. versionStart+ versionLength];
329365
330366 string [] objs;
331367 void addObj (string objFilename, string args)
@@ -348,7 +384,7 @@ void buildMsvcrt(string outDir)
348384 }
349385
350386 // merge them into the library
351- runShell(` lib /MACHINE: ` ~ arch ~ ` " ` ~ lib.name ~ ` " ` ~ objs.map! quote.join(" " ));
387+ runShell(" lib " ~ quote( lib.name) ~ " " ~ objs.map! quote.join(" " ));
352388
353389 foreach (obj; objs)
354390 std.file.remove (obj);
@@ -388,6 +424,14 @@ void buildUuid(string outDir)
388424 std.file.remove (src);
389425}
390426
427+ // vfw32.lib is a merge of 3 other libs
428+ void buildVfw32 (string outDir)
429+ {
430+ auto srcLibs = [ " msvfw32" , " avicap32" , " avifil32" ].map! (name => buildPath(outDir, name ~ " .lib" ));
431+ const outLib = buildPath(outDir, " vfw32.lib" );
432+ runShell(` lib "/OUT:` ~ outLib ~ ` " ` ~ srcLibs.map! quote.join(" " ));
433+ }
434+
391435void main (string [] args)
392436{
393437 x64 = (args.length > 1 && args[1 ] == " x64" );
@@ -405,6 +449,19 @@ void main(string[] args)
405449 buildOldnames(outDir);
406450 buildLegacyStdioDefinitions(outDir);
407451 buildUuid(outDir);
452+ buildVfw32(outDir);
453+
454+ // rename msvcr<N>.lib to msvcrt<N>.lib as expected by DMD
455+ foreach (lib; std.file.dirEntries (outDir, " msvcr*.lib" , SpanMode.shallow))
456+ {
457+ const base = baseName(lib.name);
458+ if (! isDigit(base[5 ])) // msvcrt.lib
459+ continue ;
460+ const newName = buildPath(outDir, " msvcrt" ~ base[5 .. $]);
461+ version (verbose)
462+ writefln(" Renaming '%s' to '%s'" , lib.name, newName);
463+ std.file.rename (lib.name, newName);
464+ }
408465
409466 // version (verbose) {} else
410467 foreach (f; std.file.dirEntries (outDir, " *.def*" , SpanMode.shallow))
0 commit comments