mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
177 lines
4.6 KiB
D
Executable file
177 lines
4.6 KiB
D
Executable file
import dshell;
|
|
|
|
import std.algorithm;
|
|
import std.file;
|
|
import std.process;
|
|
import std.regex;
|
|
import std.conv;
|
|
|
|
int main()
|
|
{
|
|
version(DigitalMars) { }
|
|
else
|
|
{
|
|
writeln("Skipping dwarf.d for non-DMD compilers.");
|
|
return DISABLED;
|
|
}
|
|
|
|
version(Windows)
|
|
{
|
|
writeln("Skipping dwarf.d for Windows.");
|
|
return DISABLED;
|
|
}
|
|
version(OSX)
|
|
{
|
|
writeln("Skipping dwarf.d for MacOS X.");
|
|
return DISABLED;
|
|
}
|
|
|
|
version(Windows)
|
|
immutable slash = "\\";
|
|
else
|
|
immutable slash = "/";
|
|
|
|
// If the Unix system doesn't have objdump, disable the tests
|
|
auto sysObjdump = executeShell("objdump --version");
|
|
if (sysObjdump.status)
|
|
return DISABLED;
|
|
|
|
double objdumpVersion;
|
|
try
|
|
{
|
|
// output examples :
|
|
// GNU objdump 2.15
|
|
// GNU objdump 2.17.50 [FreeBSD] 2007-07-03
|
|
// GNU objdump (GNU Binutils) 2.36.1
|
|
string strVer = sysObjdump.output.split("\n")[0];
|
|
writeln("Objdump version of the machine : ", strVer);
|
|
|
|
auto cap = matchFirst(strVer, `[0-9]+\.[0-9]+`);
|
|
assert(cap);
|
|
objdumpVersion = cap.hit.to!double;
|
|
}
|
|
catch (ConvException ce)
|
|
{
|
|
// The conversion failed
|
|
return DISABLED;
|
|
}
|
|
writeln("Parsed objdump version of the machine : ", objdumpVersion);
|
|
|
|
// DWARF 3 (and 4) support has been implemented in version 2.20 (2.20.51.0.1)
|
|
if(objdumpVersion < 2.20)
|
|
return DISABLED;
|
|
|
|
immutable extra_dwarf_dir = EXTRA_FILES ~ slash ~ "dwarf" ~ slash;
|
|
bool failed;
|
|
|
|
// test them all
|
|
foreach (string path; dirEntries(extra_dwarf_dir, SpanMode.shallow))
|
|
{
|
|
if (!isFile(path) || extension(path) != ".d")
|
|
continue;
|
|
|
|
// retrieve the filename without the extension
|
|
auto filename = baseName(stripExtension(path));
|
|
string[string] requirements = getRequirements(path);
|
|
|
|
try
|
|
{
|
|
if (objdumpVersion < requirements["MIN_OBJDUMP_VERSION"].to!double)
|
|
{
|
|
writeln("Warning: test " ~ path ~ " skipped.");
|
|
continue ;
|
|
}
|
|
}
|
|
catch(Exception e) { }
|
|
|
|
|
|
string exe = OUTPUT_BASE ~ slash ~ filename;
|
|
run("$DMD -m$MODEL -of" ~ exe ~ "$EXE -conf= -fPIE -g " ~ requirements["EXTRA_ARGS"]
|
|
~ " -I" ~ extra_dwarf_dir ~ " " ~ path);
|
|
|
|
// Write objdump result to a file
|
|
auto objdump = exe ~ ".objdump";
|
|
|
|
auto objdump_file = File(objdump, "w");
|
|
run("objdump -W " ~ exe, objdump_file);
|
|
objdump_file.close();
|
|
|
|
auto llvmDwarfdump = executeShell("llvm-dwarfdump --version");
|
|
try {
|
|
if (!llvmDwarfdump.status && requirements["DWARF_VERIFY"].to!bool)
|
|
run("llvm-dwarfdump --verify " ~ exe);
|
|
} catch (ConvException e) { }
|
|
|
|
// Objdump excepted results
|
|
string excepted_results_file = extra_dwarf_dir ~ "excepted_results"
|
|
~ slash ~ filename ~ ".txt";
|
|
|
|
if (!exists(excepted_results_file))
|
|
assert(0, "DWARF tests must have a .txt file in the `excepted_results`"
|
|
~ " folder which contains the DWARF dump info");
|
|
|
|
// Read file result as a string
|
|
auto result = cast(string)readText(objdump);
|
|
|
|
string failmsg;
|
|
|
|
foreach (line; File(excepted_results_file).byLine)
|
|
{
|
|
if (!canFind(result, line))
|
|
{
|
|
failmsg ~= filename ~ ": Couln't find `" ~ line
|
|
~ "` in the DWARF dump info.\n";
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
if (failmsg)
|
|
{
|
|
// Writes the result into stdout for the CI machines.
|
|
writeln(result);
|
|
write(failmsg);
|
|
}
|
|
}
|
|
|
|
return failed;
|
|
}
|
|
|
|
string[string] getRequirements(string dfile)
|
|
{
|
|
string[string] result;
|
|
// Initialize to an empty string to prevent RangeViolation exceptions.
|
|
foreach (req; ["EXTRA_ARGS", "MIN_OBJDUMP_VERSION"])
|
|
result[req] = "";
|
|
result["DWARF_VERIFY"] = "true";
|
|
|
|
bool begin;
|
|
|
|
auto f = File(dfile, "r");
|
|
|
|
foreach (line; f.byLine)
|
|
{
|
|
if (line.length < 2)
|
|
continue;
|
|
|
|
if (line.startsWith("/*"))
|
|
{
|
|
begin = true;
|
|
}
|
|
|
|
if (begin)
|
|
{
|
|
string[] args = line.split(":").to!(string[]);
|
|
if (args.length == 2)
|
|
{
|
|
result[args[0]] = args[1].strip();
|
|
}
|
|
|
|
if (line.indexOf("*/") != -1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
f.close();
|
|
return result;
|
|
}
|