mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 20:50:41 +03:00

The build of the lexer dub subpackage requires running and building a little config.d tool as custom pregenerate command. Forwarding the target architecture via `--arch=$DUB_ARCH` to the nested dub build of config.d was added in #9275, to fix cross- compilation, but in reality broke it. Not specifying the architecture explicitly for the little helper build lets the compiler pick the default one, the host's native platform in practice, which is guaranteed to be runnable on that compiling **host**, independent from the **target** platform for the main dub build. Suppose one cross-compiles the dmd:lexer subpackage from x86_64 to AArch64 - an AArch64 config.d executable will hardly run on the x86_64 host, and won't be able to generate the `VERSION` and `SYSCONFDIR.imp` string-import files as pre- requisite of the build. Side note: using little separately-built .d tools/scripts as build helpers for autogenerating little VERSION files etc. is IMO bad practice - when cross-compiling, you require a D compiler that can a) cross-compile, and b) build successfully for the native platform too. Not sure this approach will e.g. ever work with GDC, where you have different toolchains for each host->target combination.
83 lines
2.2 KiB
D
Executable file
83 lines
2.2 KiB
D
Executable file
#!/usr/bin/env dub
|
|
/+
|
|
dub.sdl:
|
|
name "config"
|
|
targetPath "generated/dub-gen"
|
|
+/
|
|
/**
|
|
Generates the compiler version, the version printed with `dmd --version`.
|
|
|
|
Outputs a file with the generated version which is imported as a string literal
|
|
in the compiler source code.
|
|
*/
|
|
module config;
|
|
|
|
void main(const string[] args)
|
|
{
|
|
import std.file : mkdirRecurse, readText;
|
|
import std.path : buildPath;
|
|
|
|
const outputDirectory = args[1];
|
|
const versionFile = args[2];
|
|
|
|
mkdirRecurse(outputDirectory);
|
|
const version_ = generateVersion(versionFile);
|
|
|
|
updateIfChanged(buildPath(outputDirectory, "VERSION"), version_);
|
|
|
|
if (args.length > 3)
|
|
{
|
|
const sysConfigDirectory = args[3];
|
|
const path = buildPath(outputDirectory, "SYSCONFDIR.imp");
|
|
updateIfChanged(path, sysConfigDirectory);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Generates the version for the compiler.
|
|
|
|
If anything goes wrong in the process the contents of the file
|
|
`versionFile` will be returned.
|
|
|
|
Params:
|
|
versionFile = a file containing a version, used for backup if generating the
|
|
version fails
|
|
|
|
Returns: the generated version, or the content of `versionFile`
|
|
*/
|
|
string generateVersion(const string versionFile)
|
|
{
|
|
import std.process : execute;
|
|
import std.file : readText;
|
|
import std.path : dirName;
|
|
import std.string : strip;
|
|
|
|
enum workDir = __FILE_FULL_PATH__.dirName;
|
|
const result = execute(["git", "-C", workDir, "describe", "--dirty"]);
|
|
|
|
return result.status == 0 ? result.output.strip : versionFile.readText;
|
|
}
|
|
|
|
/**
|
|
Writes given the content to the given file.
|
|
|
|
The content will only be written to the file specified in `path` if that file
|
|
doesn't exist, or the content of the existing file is different from the given
|
|
content.
|
|
|
|
This makes sure the timestamp of the file is only updated when the
|
|
content has changed. This will avoid rebuilding when the content hasn't changed.
|
|
|
|
Params:
|
|
path = the path to the file to write the content to
|
|
content = the content to write to the file
|
|
*/
|
|
void updateIfChanged(const string path, const string content)
|
|
{
|
|
import std.file : exists, readText, write;
|
|
|
|
const existingContent = path.exists ? path.readText : "";
|
|
|
|
if (content != existingContent)
|
|
write(path, content);
|
|
}
|