diff --git a/changelog/dependency-build-settings.dd b/changelog/dependency-build-settings.dd new file mode 100644 index 0000000..8859018 --- /dev/null +++ b/changelog/dependency-build-settings.dd @@ -0,0 +1,15 @@ +Allow custom build settings to be defined for dependencies + +For example: +--- +{ + "name": "example", + "dependencies": { + "vibe-d": { "version" : "~>0.9.2", "dflags" : ["-preview=in"] } + } +} +--- + +In this example, `-preview=in` will be applied to `vibe-d` and all of its dependencies. +Any $(LINK2 build settings, https://dub.pm/package-format-json.html#build-settings) field will be parsed, +however only `dflags` is taken into account when compiling for now. diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 9d38fd6..9ab99e7 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -314,20 +314,45 @@ visited.clear(); // 1. downwards inherits versions, debugVersions, and inheritable build settings - static void configureDependencies(const scope ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0) + static void configureDependencies(const scope ref TargetInfo ti, TargetInfo[string] targets, + BuildSettings[string] dependBS, size_t level = 0) { + + static void applyForcedSettings(const scope ref BuildSettings forced, ref BuildSettings child) { + child.addDFlags(forced.dflags); + } + // do not use `visited` here as dependencies must inherit // configurations from *all* of their parents logDebug("%sConfigure dependencies of %s, deps:%(%s, %)", ' '.repeat(2 * level), ti.pack.name, ti.dependencies); foreach (depname; ti.dependencies) { + BuildSettings forcedSettings; auto pti = &targets[depname]; mergeFromDependent(ti.buildSettings, pti.buildSettings); - configureDependencies(*pti, targets, level + 1); + + if (auto matchedSettings = depname in dependBS) + forcedSettings = *matchedSettings; + else if (auto matchedSettings = "*" in dependBS) + forcedSettings = *matchedSettings; + + applyForcedSettings(forcedSettings, pti.buildSettings); + configureDependencies(*pti, targets, ["*" : forcedSettings], level + 1); } } - configureDependencies(*roottarget, targets); + BuildSettings[string] dependencyBuildSettings; + foreach (key, value; rootPackage.recipe.buildSettings.dependencyBuildSettings) + { + BuildSettings buildSettings; + if (auto target = key in targets) + { + value.getPlatformSettings(buildSettings, genSettings.platform, target.pack.path); + buildSettings.processVars(m_project, target.pack, buildSettings, genSettings, true); + dependencyBuildSettings[key] = buildSettings; + } + } + configureDependencies(*roottarget, targets, dependencyBuildSettings); // 2. add Have_dependency_xyz for all direct dependencies of a target // (includes incorporated non-target dependencies and their dependencies) diff --git a/source/dub/recipe/json.d b/source/dub/recipe/json.d index 54486c7..60e7626 100644 --- a/source/dub/recipe/json.d +++ b/source/dub/recipe/json.d @@ -177,7 +177,13 @@ pkg = package_name ~ pkg; } enforce(pkg !in bs.dependencies, "The dependency '"~pkg~"' is specified more than once." ); - bs.dependencies[pkg] = deserializeJson!Dependency(verspec); + bs.dependencies[pkg] = Dependency.fromJson(verspec); + if (verspec.type == Json.Type.object) + { + BuildSettingsTemplate dbs; + dbs.parseJson(verspec, package_name); + bs.dependencyBuildSettings[pkg] = dbs; + } } break; case "systemDependencies": @@ -251,7 +257,7 @@ if( bs.dependencies !is null ){ auto deps = Json.emptyObject; foreach( pack, d; bs.dependencies ) - deps[pack] = serializeToJson(d); + deps[pack] = d.toJson(); ret["dependencies"] = deps; } if (bs.systemDependencies !is null) ret["systemDependencies"] = bs.systemDependencies; diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index e03fa92..f03a943 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -176,6 +176,7 @@ /// a certain BuildPlatform. struct BuildSettingsTemplate { Dependency[string] dependencies; + BuildSettingsTemplate[string] dependencyBuildSettings; string systemDependencies; TargetType targetType = TargetType.autodetect; string targetPath; diff --git a/test/depen-build-settings/.gitignore b/test/depen-build-settings/.gitignore new file mode 100644 index 0000000..3dfd42f --- /dev/null +++ b/test/depen-build-settings/.gitignore @@ -0,0 +1,4 @@ +depend.json +depend2.json +depen-build-settings.json +depen-build-settings diff --git a/test/depen-build-settings/.no_test b/test/depen-build-settings/.no_test new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/depen-build-settings/.no_test diff --git a/test/depen-build-settings/depend/depend2/dub.json b/test/depen-build-settings/depend/depend2/dub.json new file mode 100644 index 0000000..b3ac9ae --- /dev/null +++ b/test/depen-build-settings/depend/depend2/dub.json @@ -0,0 +1,5 @@ +{ + "targetType": "library", + "description": "A minimal D application.", + "name": "depend2" +} diff --git a/test/depen-build-settings/depend/depend2/source/depend2.d b/test/depen-build-settings/depend/depend2/source/depend2.d new file mode 100644 index 0000000..31b6367 --- /dev/null +++ b/test/depen-build-settings/depend/depend2/source/depend2.d @@ -0,0 +1,6 @@ +import std.stdio; + +extern (C) void depend2_func() +{ + writeln("depend2_func"); +} diff --git a/test/depen-build-settings/depend/dub.json b/test/depen-build-settings/depend/dub.json new file mode 100644 index 0000000..4d7ad5a --- /dev/null +++ b/test/depen-build-settings/depend/dub.json @@ -0,0 +1,9 @@ +{ + "targetType": "library", + "description": "A minimal D application.", + "name": "depend1", + + "dependencies": { + "depend2": { "version" : "*" } + } +} diff --git a/test/depen-build-settings/depend/source/depend.d b/test/depen-build-settings/depend/source/depend.d new file mode 100644 index 0000000..d9bb981 --- /dev/null +++ b/test/depen-build-settings/depend/source/depend.d @@ -0,0 +1,9 @@ +import std.stdio; + +extern (C) void depend2_func(); + +extern (C) void depend1_func() +{ + writeln("depend1_func"); + depend2_func(); +} diff --git a/test/depen-build-settings/dub.json b/test/depen-build-settings/dub.json new file mode 100644 index 0000000..1769ac1 --- /dev/null +++ b/test/depen-build-settings/dub.json @@ -0,0 +1,8 @@ +{ + "description": "A minimal D application.", + "name": "depen-build-settings", + + "dependencies": { + "depend1": { "version" : "*", "dflags" : ["-X"] } + } +} diff --git a/test/depen-build-settings/dub.selections.json b/test/depen-build-settings/dub.selections.json new file mode 100644 index 0000000..584b513 --- /dev/null +++ b/test/depen-build-settings/dub.selections.json @@ -0,0 +1,7 @@ +{ + "fileVersion": 1, + "versions": { + "depend1": {"path":"depend/"}, + "depend2": {"path":"depend/depend2/"} + } +} diff --git a/test/depen-build-settings/source/app.d b/test/depen-build-settings/source/app.d new file mode 100644 index 0000000..8893119 --- /dev/null +++ b/test/depen-build-settings/source/app.d @@ -0,0 +1,12 @@ +import std.stdio; +import std.file; + +extern (C) void depend1_func(); + +void main() +{ + writeln("Edit source/app.d to start your project."); + depend1_func(); + assert(exists("depend2.json")); + assert(exists("depend.json")); +}