Skip to content

Commit

Permalink
add "cacheArtifactPath" in TargetDescription
Browse files Browse the repository at this point in the history
Allow 3rd party programs (e.g. Meson) to locate artifacts in the cache
  • Loading branch information
rtbo committed Aug 12, 2023
1 parent 52fd928 commit 5c3268f
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 34 deletions.
1 change: 1 addition & 0 deletions source/dub/description.d
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ struct TargetDescription {
string[] packages; /// All packages contained in this target (e.g. for target type "sourceLibrary")
string rootConfiguration; /// Build configuration of the target's root package used for building
BuildSettings buildSettings; /// Final build settings to use when building the target
string cacheArtifactPath; /// The full path of the built target in the cache
string[] dependencies; /// List of all dependencies of this target (package names)
string[] linkDependencies; /// List of all link-dependencies of this target (target names)
}
Expand Down
35 changes: 1 addition & 34 deletions source/dub/generators/build.d
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class BuildGenerator : ProjectGenerator {
m_tempTargetExecutablePath = target_path = getTempDir() ~ format(".dub/build/%s-%s/%s/", packageName, pack.version_, build_id);
}
else
target_path = packageCache(settings.cache, pack) ~ "build/" ~ build_id;
target_path = targetCacheDir(settings.cache, pack, build_id);

if (!settings.force && isUpToDate(target_path, buildsettings, settings, pack, packages, additional_dep_files)) {
logInfo("Up-to-date", Color.green, "%s %s: target for configuration [%s] is up to date.",
Expand Down Expand Up @@ -721,39 +721,6 @@ class BuildGenerator : ProjectGenerator {
}
}

/**
* Provides a unique (per build) identifier
*
* When building a package, it is important to have a unique but stable
* identifier to differentiate builds and allow their caching.
* This function provides such an identifier.
* Example:
* ```
* application-debug-linux.posix-x86_64-dmd_v2.100.2-D80285212AEC1FF9855F18AD52C68B9EEB5C7690609C224575F920096FB1965B
* ```
*/
private string computeBuildID(in BuildSettings buildsettings, string config, GeneratorSettings settings)
{
const(string[])[] hashing = [
buildsettings.versions,
buildsettings.debugVersions,
buildsettings.dflags,
buildsettings.lflags,
buildsettings.stringImportPaths,
buildsettings.importPaths,
buildsettings.cImportPaths,
settings.platform.architecture,
[
(cast(uint)(buildsettings.options & ~BuildOption.color)).to!string, // exclude color option from id
settings.platform.compilerBinary,
settings.platform.compiler,
settings.platform.compilerVersion,
],
];

return computeBuildName(config, settings, hashing);
}

private NativePath getMainSourceFile(in Package prj)
{
foreach (f; ["source/app.d", "src/app.d", "source/"~prj.name~".d", "src/"~prj.name~".d"])
Expand Down
48 changes: 48 additions & 0 deletions source/dub/generators/generator.d
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,54 @@ package(dub) NativePath packageCache(NativePath cachePath, in Package pkg)
return cachePath ~ pkg.name ~ pkg.version_.toString();
}

/**
* Compute and return the directory where a target should be cached.
*
* Params:
* cachePath = Base path at which the build cache is located,
* e.g. `$HOME/.dub/cache/`
* pkg = The package. Cannot be `null`.
* buildId = The build identifier of the target.
*/
package(dub) NativePath targetCacheDir(NativePath cachePath, in Package pkg, string buildId)
{
return packageCache(cachePath, pkg) ~ "build" ~ buildId;
}

/**
* Provides a unique (per build) identifier
*
* When building a package, it is important to have a unique but stable
* identifier to differentiate builds and allow their caching.
* This function provides such an identifier.
* Example:
* ```
* library-debug-Z7qINYX4IxM8muBSlyNGrw
* ```
*/
package(dub) string computeBuildID(in BuildSettings buildsettings, string config, GeneratorSettings settings)
{
import std.conv : to;

const(string[])[] hashing = [
buildsettings.versions,
buildsettings.debugVersions,
buildsettings.dflags,
buildsettings.lflags,
buildsettings.stringImportPaths,
buildsettings.importPaths,
buildsettings.cImportPaths,
settings.platform.architecture,
[
(cast(uint)(buildsettings.options & ~BuildOption.color)).to!string, // exclude color option from id
settings.platform.compilerBinary,
settings.platform.compiler,
settings.platform.compilerVersion,
],
];

return computeBuildName(config, settings, hashing);
}

struct GeneratorSettings {
NativePath cache;
Expand Down
3 changes: 3 additions & 0 deletions source/dub/generators/targetdescription.d
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class TargetDescriptionGenerator : ProjectGenerator {
d.packages = ti.packages.map!(p => p.name).array;
d.rootConfiguration = ti.config;
d.buildSettings = ti.buildSettings.dup;
const buildId = computeBuildID(d.buildSettings, ti.config, settings);
const filename = settings.compiler.getTargetFileName(d.buildSettings, settings.platform);
d.cacheArtifactPath = (targetCacheDir(settings.cache, ti.pack, buildId) ~ filename).toNativeString();
d.dependencies = ti.dependencies.dup;
d.linkDependencies = ti.linkDependencies.dup;

Expand Down
2 changes: 2 additions & 0 deletions test/pr2644-describe-artifact-path/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dubhome/
pr2644-describe-artifact-path
Empty file.
2 changes: 2 additions & 0 deletions test/pr2644-describe-artifact-path/dub.sdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name "pr2644-describe-artifact-path";
targetType "executable";
61 changes: 61 additions & 0 deletions test/pr2644-describe-artifact-path/source/describe_artifact_path.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module describe_artifact_path;

import std.path;
import std.file;
import std.process;
import std.stdio;
import std.json;

void main()
{
const dubhome = __FILE_FULL_PATH__.dirName().dirName().buildNormalizedPath("dubhome");
if (exists(dubhome))
{
rmdirRecurse(dubhome);
}
scope (success)
{
// leave dubhome in the tree for analysis in case of failure
rmdirRecurse(dubhome);
}

const string[string] env = [
"DUB_HOME": dubhome,
];
const fetchProgram = [
environment["DUB"],
"fetch",
"[email protected]",
];
auto dubFetch = spawnProcess(fetchProgram, stdin, stdout, stderr, env);
wait(dubFetch);


const describeProgram = [
environment["DUB"],
"describe",
"--compiler=" ~ environment["DC"],
"--build=debug",
"--config=lib",
"[email protected]",
];
auto result = execute(describeProgram, env);
assert(result.status == 0, "expected dub describe to return zero");
auto json = parseJSON(result.output);

auto cacheFile = json["targets"][0]["cacheArtifactPath"].str;
assert(!exists(cacheFile), "found cache file in virgin dubhome");

const buildProgram = [
environment["DUB"],
"build",
"--compiler=" ~ environment["DC"],
"--build=debug",
"--config=lib",
"[email protected]",
];
auto dubBuild = spawnProcess(buildProgram, stdin, stdout, stderr, env);
wait(dubBuild);

assert(exists(cacheFile), "did not find cache file after build");
}

0 comments on commit 5c3268f

Please sign in to comment.