Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add betterC probing for performance and for applications without drun… #2753

Merged
merged 3 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ __dummy.html
/bin/dub-test-library
/bin/libdub.a
/bin/dub-*
/bin/dub.*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a minor annoyance when using vscode source control on windows, I was thinking it didn't require mention, nor its own pull request.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What artifacts does vscode generate ? We can keep it in this PR, I just could not tell where it's coming from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the dub.exe and dub.pdb files that are generated when building under windows.


# Ignore files or directories created by the test suite.
*.exe
Expand Down
20 changes: 11 additions & 9 deletions source/dub/compilers/compiler.d
Original file line number Diff line number Diff line change
Expand Up @@ -177,27 +177,29 @@ interface Compiler {
args = arguments for the probe compilation
arch_override = special handler for x86_mscoff
*/
protected final BuildPlatform probePlatform(string compiler_binary, string[] args,
string arch_override)
protected final BuildPlatform probePlatform(string compiler_binary, string[] args, string arch_override)
{
import dub.compilers.utils : generatePlatformProbeFile, readPlatformJsonProbe;
import dub.compilers.utils : generatePlatformProbeFile, readPlatformSDLProbe;
Geod24 marked this conversation as resolved.
Show resolved Hide resolved
import std.string : format, strip;

auto fil = generatePlatformProbeFile();
NativePath fil = generatePlatformProbeFile();
string betterC_flag = "-betterC";
if (compiler_binary == "gdc")
betterC_flag = "-fno-druntime";

auto result = execute(compiler_binary ~ args ~ fil.toNativeString());
auto result = execute(compiler_binary ~ args ~ betterC_flag ~ fil.toNativeString());
enforce!CompilerInvocationException(result.status == 0,
format("Failed to invoke the compiler %s to determine the build platform: %s",
compiler_binary, result.output));
BuildPlatform build_platform;

auto build_platform = readPlatformJsonProbe(result.output);
build_platform = readPlatformSDLProbe(result.output);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge those two lines ?

string ver = determineVersion(compiler_binary, result.output).strip;
build_platform.compilerBinary = compiler_binary;

auto ver = determineVersion(compiler_binary, result.output)
.strip;
if (ver.empty) {
logWarn(`Could not probe the compiler version for "%s". ` ~
`Toolchain requirements might be ineffective`, build_platform.compiler);
`Toolchain requirements might be ineffective`, build_platform.compiler);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert

}
else {
build_platform.compilerVersion = ver;
Expand Down
117 changes: 71 additions & 46 deletions source/dub/compilers/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
module dub.compilers.utils;

import dub.compilers.buildsettings;
import dub.platform : BuildPlatform, archCheck, compilerCheck, platformCheck;
import dub.platform : BuildPlatform, archCheckPragmas, compilerCheckPragmas, platformCheckPragmas;
import dub.internal.vibecompat.inet.path;
import dub.internal.logging;

Expand Down Expand Up @@ -269,77 +269,102 @@ private enum probeEndMark = "__dub_probe_end__";
NativePath generatePlatformProbeFile()
{
import dub.internal.vibecompat.core.file;
import dub.internal.vibecompat.data.json;
import dub.internal.utils;
import std.string : format;

enum moduleInfo = q{
module object;
alias string = const(char)[];
};

// try to not use phobos in the probe to avoid long import times
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also modify the comment so the next person knows the platform probe should not rely on the runtime to make your use case possible.

enum probe = q{
module dub_platform_probe;

template toString(int v) { enum toString = v.stringof; }
string stringArray(string[] ary) {
string res;
foreach (i, e; ary) {
if (i)
res ~= ", ";
res ~= '"' ~ e ~ '"';
}
return res;
}

pragma(msg, `%1$s`
~ '\n' ~ `{`
~ '\n' ~ ` "compiler": "`~ determineCompiler() ~ `",`
~ '\n' ~ ` "frontendVersion": ` ~ toString!__VERSION__ ~ `,`
~ '\n' ~ ` "compilerVendor": "` ~ __VENDOR__ ~ `",`
~ '\n' ~ ` "platform": [`
~ '\n' ~ ` ` ~ determinePlatform().stringArray
~ '\n' ~ ` ],`
~ '\n' ~ ` "architecture": [`
~ '\n' ~ ` ` ~ determineArchitecture().stringArray
~ '\n' ~ ` ],`
~ '\n' ~ `}`
~ '\n' ~ `%2$s`);

string[] determinePlatform() { %3$s }
string[] determineArchitecture() { %4$s }
string determineCompiler() { %5$s }

}.format(probeBeginMark, probeEndMark, platformCheck, archCheck, compilerCheck);
%1$s
pragma(msg, `%2$s`);
pragma(msg, `\n`);
pragma(msg, `compiler`);
%6$s
pragma(msg, `\n`);
pragma(msg, `frontendVersion "`);
pragma(msg, __VERSION__.stringof);
pragma(msg, `"\n`);
pragma(msg, `compilerVendor "`);
pragma(msg, __VENDOR__);
pragma(msg, `"\n`);
pragma(msg, `platform`);
%4$s
pragma(msg, `\n`);
pragma(msg, `architecture `);
%5$s
pragma(msg, `\n`);
pragma(msg, `%3$s`);
}.format(moduleInfo, probeBeginMark, probeEndMark, platformCheckPragmas, archCheckPragmas, compilerCheckPragmas);

auto path = getTempFile("dub_platform_probe", ".d");
writeFile(path, probe);

return path;
}


/**
Processes the JSON output generated by compiling the platform probe file.
Processes the SDL output generated by compiling the platform probe file.

See_Also: `generatePlatformProbeFile`.
*/
BuildPlatform readPlatformJsonProbe(string output)
BuildPlatform readPlatformSDLProbe(string output)
{
import std.algorithm : map;
import std.algorithm : map, max, splitter, joiner, count, filter;
import std.array : array;
import std.exception : enforce;
import std.range : front;
import std.ascii : newline;
import std.string;
import dub.internal.sdlang.parser;
import dub.internal.sdlang.ast;
import std.conv;

// work around possible additional output of the compiler
auto idx1 = output.indexOf(probeBeginMark);
auto idx2 = output.lastIndexOf(probeEndMark);
auto idx1 = output.indexOf(probeBeginMark ~ newline ~ "\\n");
auto idx2 = output[max(0, idx1) .. $].indexOf(probeEndMark) + idx1;
enforce(idx1 >= 0 && idx1 < idx2,
"Unexpected platform information output - does not contain a JSON object.");
output = output[idx1+probeBeginMark.length .. idx2];
output = output[idx1 + probeBeginMark.length .. idx2].replace(newline, "").replace("\\n", "\n");

import dub.internal.vibecompat.data.json;
auto json = parseJsonString(output);
output = output.splitter("\n").filter!((e) => e.length > 0)
.map!((e) {
if (e.count("\"") == 0)
{
return e ~ ` ""`;
}
return e;
})
.joiner("\n").array().to!string;

BuildPlatform build_platform;
build_platform.platform = json["platform"].get!(Json[]).map!(e => e.get!string()).array();
build_platform.architecture = json["architecture"].get!(Json[]).map!(e => e.get!string()).array();
build_platform.compiler = json["compiler"].get!string;
build_platform.frontendVersion = json["frontendVersion"].get!int;
Tag sdl = parseSource(output);

foreach (n; sdl.all.tags)
{
switch (n.name)
{
default:
break;
case "platform":
build_platform.platform = n.values.map!(e => e.toString()).array();
break;
case "architecture":
build_platform.architecture = n.values.map!(e => e.toString()).array();
break;
case "compiler":
build_platform.compiler = n.values.front.toString();
break;
case "frontendVersion":
build_platform.frontendVersion = n.values.front.toString()
.filter!((e) => e >= '0' && e <= '9').array().to!string
.to!int;
break;
}
}
return build_platform;
}
85 changes: 85 additions & 0 deletions source/dub/platform.d
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,91 @@ enum string compilerCheck = q{
else return null;
};


enum string platformCheckPragmas = q{
version(Windows) pragma(msg, ` "windows"`);
version(linux) pragma(msg, ` "linux"`);
version(Posix) pragma(msg, ` "posix"`);
version(OSX) pragma(msg, ` "osx" "darwin"`);
version(iOS) pragma(msg, ` "ios" "darwin"`);
version(TVOS) pragma(msg, ` "tvos" "darwin"`);
version(WatchOS) pragma(msg, ` "watchos" "darwin"`);
version(FreeBSD) pragma(msg, ` "freebsd"`);
version(OpenBSD) pragma(msg, ` "openbsd"`);
version(NetBSD) pragma(msg, ` "netbsd"`);
version(DragonFlyBSD) pragma(msg, ` "dragonflybsd"`);
version(BSD) pragma(msg, ` "bsd"`);
version(Solaris) pragma(msg, ` "solaris"`);
version(AIX) pragma(msg, ` "aix"`);
version(Haiku) pragma(msg, ` "haiku"`);
version(SkyOS) pragma(msg, ` "skyos"`);
version(SysV3) pragma(msg, ` "sysv3"`);
version(SysV4) pragma(msg, ` "sysv4"`);
version(Hurd) pragma(msg, ` "hurd"`);
version(Android) pragma(msg, ` "android"`);
version(Cygwin) pragma(msg, ` "cygwin"`);
version(MinGW) pragma(msg, ` "mingw"`);
version(PlayStation4) pragma(msg, ` "playstation4"`);
version(WebAssembly) pragma(msg, ` "wasm"`);
};

enum string archCheckPragmas = q{

version(X86) pragma(msg, ` "x86"`);
// Hack: see #1535
// Makes "x86_omf" available as a platform specifier in the package recipe
version(X86) version(CRuntime_DigitalMars) pragma(msg, ` "x86_omf"`);
// Hack: see #1059
// When compiling with --arch=x86_mscoff build_platform.architecture is equal to ["x86"] and canFind below is false.
// This hack prevents unnecessary warning 'Failed to apply the selected architecture x86_mscoff. Got ["x86"]'.
// And also makes "x86_mscoff" available as a platform specifier in the package recipe
version(X86) version(CRuntime_Microsoft) pragma(msg, ` "x86_mscoff"`);
version(X86_64) pragma(msg, ` "x86_64"`);
version(ARM) pragma(msg, ` "arm"`);
version(AArch64) pragma(msg, ` "aarch64"`);
version(ARM_Thumb) pragma(msg, ` "arm_thumb"`);
version(ARM_SoftFloat) pragma(msg, ` "arm_softfloat"`);
version(ARM_HardFloat) pragma(msg, ` "arm_hardfloat"`);
version(PPC) pragma(msg, ` "ppc"`);
version(PPC_SoftFP) pragma(msg, ` "ppc_softfp"`);
version(PPC_HardFP) pragma(msg, ` "ppc_hardfp"`);
version(PPC64) pragma(msg, ` "ppc64"`);
version(IA64) pragma(msg, ` "ia64"`);
version(MIPS) pragma(msg, ` "mips"`);
version(MIPS32) pragma(msg, ` "mips32"`);
version(MIPS64) pragma(msg, ` "mips64"`);
version(MIPS_O32) pragma(msg, ` "mips_o32"`);
version(MIPS_N32) pragma(msg, ` "mips_n32"`);
version(MIPS_O64) pragma(msg, ` "mips_o64"`);
version(MIPS_N64) pragma(msg, ` "mips_n64"`);
version(MIPS_EABI) pragma(msg, ` "mips_eabi"`);
version(MIPS_NoFloat) pragma(msg, ` "mips_nofloat"`);
version(MIPS_SoftFloat) pragma(msg, ` "mips_softfloat"`);
version(MIPS_HardFloat) pragma(msg, ` "mips_hardfloat"`);
version(SPARC) pragma(msg, ` "sparc"`);
version(SPARC_V8Plus) pragma(msg, ` "sparc_v8plus"`);
version(SPARC_SoftFP) pragma(msg, ` "sparc_softfp"`);
version(SPARC_HardFP) pragma(msg, ` "sparc_hardfp"`);
version(SPARC64) pragma(msg, ` "sparc64"`);
version(S390) pragma(msg, ` "s390"`);
version(S390X) pragma(msg, ` "s390x"`);
version(HPPA) pragma(msg, ` "hppa"`);
version(HPPA64) pragma(msg, ` "hppa64"`);
version(SH) pragma(msg, ` "sh"`);
version(SH64) pragma(msg, ` "sh64"`);
version(Alpha) pragma(msg, ` "alpha"`);
version(Alpha_SoftFP) pragma(msg, ` "alpha_softfp"`);
version(Alpha_HardFP) pragma(msg, ` "alpha_hardfp"`);
};

/// private
enum string compilerCheckPragmas = q{
version(DigitalMars) pragma(msg, ` "dmd"`);
else version(GNU) pragma(msg, ` "gdc"`);
else version(LDC) pragma(msg, ` "ldc"`);
else version(SDC) pragma(msg, ` "sdc"`);
};

/** Determines the full build platform used for the current build.
Note that the `BuildPlatform.compilerBinary` field will be left empty.
Expand Down
Loading