Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ac0b94b
commit 7455e3b
Showing
4 changed files
with
373 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
module xfbuild.Linker; | ||
|
||
private | ||
{ | ||
import xfbuild.GlobalParams; | ||
import xfbuild.Module; | ||
import xfbuild.Process; | ||
import xfbuild.Misc; | ||
|
||
import std.ascii : isAlpha; | ||
import std.array; | ||
|
||
//~ import tango.sys.Process; | ||
//~ import tango.io.stream.Lines; | ||
//~ import tango.stdc.ctype : isAlpha; | ||
//~ import tango.text.Util : contains; | ||
//~ import Array = tango.core.Array; | ||
|
||
//~ // TODO: better logging | ||
//~ import tango.io.Stdout; | ||
} | ||
|
||
/+private { | ||
Regex linkerFileRegex; | ||
} | ||
static this() { | ||
//defend\terrain\Generator.obj(Generator) | ||
//linkerFileRegex = Regex(`([a-zA-Z0-9.:_\-\\/]+)\(.*\)`); | ||
}+/ | ||
|
||
import std.string; | ||
|
||
bool contains(string where, char what) | ||
{ | ||
return where.indexOf(what) != -1; | ||
} | ||
|
||
bool isValidObjFileName(string f) | ||
{ | ||
foreach (c; f) | ||
{ | ||
if (!isAlpha(c) && !(`.:_-\/`.contains(c))) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool contains(string[] haystack, string needle) | ||
{ | ||
foreach (val; haystack) | ||
{ | ||
if (val == needle) | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
bool link(ref Module[string] modules, string[] mainFiles = null) | ||
{ | ||
bool retryCompile; | ||
|
||
string[] args; | ||
args ~= globalParams.compilerName; | ||
args ~= globalParams.compilerOptions; | ||
|
||
foreach (k; mainFiles) | ||
{ | ||
foreach (m; modules) | ||
{ | ||
if (m.path == k) | ||
{ | ||
if (!m.isHeader) | ||
args ~= m.objFile; | ||
|
||
break; | ||
} | ||
} | ||
} | ||
|
||
foreach (k, m; modules) | ||
{ | ||
if (m.isHeader || contains(mainFiles, m.path)) | ||
continue; | ||
|
||
args ~= m.objFile; | ||
} | ||
|
||
args ~= "-of" ~ globalParams.outputFile; | ||
|
||
if (!globalParams.recompileOnUndefinedReference) | ||
{ | ||
executeCompilerViaResponseFile( | ||
args[0], | ||
args[1..$], | ||
globalParams.linkerAffinityMask | ||
); | ||
} | ||
else | ||
{ | ||
//~ this(bool copyEnv, char[][] args...) | ||
// copies environment variables | ||
scope process = new Process(true, args); | ||
|
||
// todo: use different execute, this one redirects to tango | ||
execute(process); | ||
|
||
string currentFile = null; | ||
Module currentModule = null; | ||
|
||
version (Windows) | ||
{ | ||
auto procOut = process.stdout; | ||
} | ||
else | ||
{ | ||
auto procOut = process.stderr; | ||
} | ||
|
||
// todo: this is basically redirect, we read from the process | ||
// to see what it prints out. But we can do the same via | ||
// system. | ||
foreach (line; new Lines!(char)(procOut)) | ||
{ | ||
line = TextUtil.trim(line); | ||
|
||
if (line.length > 0) | ||
{ | ||
Stdout.formatln("linker: '{}'", line); | ||
} | ||
|
||
try | ||
{ | ||
auto arr = line.decomposeString(cast(string)null, "(", null, ")"); | ||
|
||
//if(linkerFileRegex.test(line)) | ||
if (arr && isValidObjFileName(arr[1])) | ||
{ | ||
//currentFile = linkerFileRegex[1]; | ||
currentFile = arr[1]; | ||
|
||
foreach (m; modules) | ||
if (m.objFile == currentFile) | ||
currentModule = m; | ||
|
||
if (!currentModule && globalParams.verbose) | ||
{ | ||
Stdout.formatln("{} doesn't belong to any known module", currentFile); | ||
continue; | ||
} | ||
|
||
if (globalParams.verbose) | ||
Stdout.formatln("linker error in file {} (module {})", currentFile, currentModule); | ||
} | ||
else if (/*undefinedReferenceRegex.test(line)*/ line.startsWith("Error 42:") && globalParams.recompileOnUndefinedReference) | ||
{ | ||
if (globalParams.verbose) | ||
{ | ||
if (!currentFile || !currentModule) | ||
{ | ||
Stdout.formatln("no file.. wtf?"); | ||
|
||
//continue; // as i currently recompile every file anyway... | ||
} | ||
|
||
/*Stdout.formatln("undefined reference to {}, will try to recompile {}", undefinedReferenceRegex[1], currentModule); | ||
currentModule.needRecompile = true; | ||
retryCompile = true;*/ | ||
|
||
Stdout.formatln("undefined reference, will try teh full recompile :F"); | ||
|
||
foreach (m; modules) | ||
m.needRecompile = true; | ||
|
||
retryCompile = true; | ||
|
||
break; | ||
} | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
if (currentFile && currentModule) | ||
{ | ||
Stdout.formatln("{}", e); | ||
Stdout.formatln("utf8 exception caught, assuming linker error in file {}", currentModule); | ||
|
||
// orly! | ||
foreach (m; modules) | ||
m.needRecompile = true; | ||
|
||
retryCompile = true; | ||
|
||
break; | ||
} | ||
else | ||
{ | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
try | ||
{ | ||
// todo: replace with a system call? find one which returns 0, | ||
// it's probably synchronous | ||
checkProcessFail(process); | ||
} | ||
catch (Exception e) | ||
{ | ||
version (Windows) { | ||
// I don't know if Windows is affected too? | ||
} | ||
else | ||
{ | ||
// DMD somehow puts some linker errors onto stdout :S | ||
Stderr.copy(process.stdout).flush; | ||
} | ||
|
||
if (retryCompile && globalParams.verbose) | ||
Stdout.formatln("ignoring linker error, will try to recompile"); | ||
else if (!retryCompile) | ||
throw e; // rethrow exception since we're not going to retry what we did | ||
|
||
} | ||
} | ||
|
||
globalParams.recompileOnUndefinedReference = false; // avoid infinite loop | ||
|
||
return retryCompile; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
binary D:\DMD\dmd2\windows\bin\dmd.exe | ||
version v2.056 | ||
config D:\DMD\dmd2\windows\bin\sc.ini | ||
parse Linker | ||
importall Linker | ||
import object (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\object.di) | ||
import xfbuild.GlobalParams (..\xfbuild\GlobalParams.d) | ||
import std.path (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\path.d) | ||
import std.algorithm (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\algorithm.d) | ||
import std.c.string (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\string.d) | ||
import core.stdc.string (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\string.di) | ||
import core.stdc.stddef (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\stddef.di) | ||
import std.array (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\array.d) | ||
import core.memory (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\memory.di) | ||
import core.bitop (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\bitop.di) | ||
import std.ascii (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\ascii.d) | ||
import std.range (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\range.d) | ||
import std.conv (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d) | ||
import core.stdc.math (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\math.di) | ||
import core.stdc.config (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\config.di) | ||
import std.exception (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\exception.d) | ||
import std.string (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\string.d) | ||
import core.exception (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\exception.di) | ||
import core.stdc.stdio (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\stdio.di) | ||
import core.stdc.stdarg (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\stdarg.di) | ||
import core.vararg (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\vararg.di) | ||
import core.stdc.stdlib (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\stdlib.di) | ||
import std.format (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\format.d) | ||
import std.bitmanip (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\bitmanip.d) | ||
import std.traits (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\traits.d) | ||
import std.typetuple (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\typetuple.d) | ||
import std.typecons (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\typecons.d) | ||
import std.metastrings (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\metastrings.d) | ||
import std.stdio (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\stdio.d) | ||
import std.stdiobase (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\stdiobase.d) | ||
import core.stdc.errno (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\errno.di) | ||
import core.stdc.wchar_ (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\wchar_.di) | ||
import core.stdc.time (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\time.di) | ||
import core.stdc.stdint (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\stdint.di) | ||
import core.stdc.signal (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\stdc\signal.di) | ||
import std.file (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\file.d) | ||
import std.datetime (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\datetime.d) | ||
import core.time (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\time.di) | ||
import core.sys.windows.windows (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sys\windows\windows.di) | ||
import std.functional (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\functional.d) | ||
import std.math (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\math.d) | ||
import std.system (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\system.d) | ||
import std.c.windows.winsock (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\windows\winsock.d) | ||
import std.stdint (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\stdint.d) | ||
import std.c.windows.windows (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\windows\windows.d) | ||
import std.windows.registry (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\windows\registry.d) | ||
import std.windows.syserror (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\windows\syserror.d) | ||
import std.windows.charset (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\windows\charset.d) | ||
import std.utf (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\utf.d) | ||
import std.__fileinit (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\__fileinit.d) | ||
import std.internal.windows.advapi32 (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\internal\windows\advapi32.d) | ||
import std.process (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\process.d) | ||
import core.thread (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\thread.di) | ||
import core.sync.mutex (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sync\mutex.di) | ||
import core.sync.exception (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sync\exception.di) | ||
import core.sys.windows.threadaux (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sys\windows\threadaux.di) | ||
import core.atomic (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\atomic.di) | ||
import std.c.process (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\process.d) | ||
import std.c.stddef (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\stddef.d) | ||
import std.internal.processinit (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\internal\processinit.d) | ||
import std.random (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\random.d) | ||
import std.c.time (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\time.d) | ||
import std.numeric (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\numeric.d) | ||
import std.c.stdlib (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\stdlib.d) | ||
import std.complex (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\complex.d) | ||
import std.c.stdio (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\stdio.d) | ||
import std.regex (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\regex.d) | ||
import std.outbuffer (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\outbuffer.d) | ||
import std.c.stdarg (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\c\stdarg.d) | ||
import std.uni (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\uni.d) | ||
import std.container (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\container.d) | ||
import xfbuild.Module (..\xfbuild\Module.d) | ||
import xfbuild.Misc (..\xfbuild\Misc.d) | ||
import xfbuild.Process (..\xfbuild\Process.d) | ||
import win32.windef (..\WindowsAPI\win32\windef.d) | ||
import win32.winnt (..\WindowsAPI\win32\winnt.d) | ||
import win32.basetsd (..\WindowsAPI\win32\basetsd.d) | ||
import win32.winerror (..\WindowsAPI\win32\winerror.d) | ||
import win32.w32api (..\WindowsAPI\win32\w32api.d) | ||
import win32.basetyps (..\WindowsAPI\win32\basetyps.d) | ||
import win32.winuser (..\WindowsAPI\win32\winuser.d) | ||
import win32.winbase (..\WindowsAPI\win32\winbase.d) | ||
import win32.winver (..\WindowsAPI\win32\winver.d) | ||
import win32.wingdi (..\WindowsAPI\win32\wingdi.d) | ||
import win32.winnls (..\WindowsAPI\win32\winnls.d) | ||
import std.concurrency (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d) | ||
import core.sync.barrier (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sync\barrier.di) | ||
import core.sync.condition (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sync\condition.di) | ||
import core.sync.semaphore (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sync\semaphore.di) | ||
import core.sync.rwmutex (D:\DMD\dmd2\windows\bin\..\..\src\druntime\import\core\sync\rwmutex.di) | ||
import std.variant (D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\variant.d) | ||
semantic Linker | ||
library advapi32.lib | ||
library shell32.lib | ||
library user32.lib | ||
library kernel32.lib | ||
library gdi32.lib | ||
library kernel32.lib | ||
semantic2 Linker | ||
semantic3 Linker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.