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

Implemented recipe files for dub #2684 #2685

Merged
merged 11 commits into from
Aug 13, 2023
15 changes: 15 additions & 0 deletions changelog/recipefile.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Added `--recipe=` switch to DUB

You can now override which file is used as recipe, instead of the default
`dub.sdl` and `dub.json`. This means you can define multiple dub.json files for
local development, for example for special local-machine-only operations, and
select which one to use over the CLI.

```
dub build --recipe=custom-dub.json
```

This can also be used to pick dub.sdl over dub.json, if both of them exist in
the same directory. Although this is discouraged for interoperability with other
DUB-supporting tools and general confusion for users. Both existing at the same
time may also become an error when this switch is not specified in the future.
35 changes: 27 additions & 8 deletions source/dub/commandline.d
Original file line number Diff line number Diff line change
Expand Up @@ -501,11 +501,13 @@ int runDubCommandLine(string[] args)
return 1;
}

// initialize the root package
Dub dub = cmd.prepareDub(handler.options);
try {
// initialize the root package
Dub dub = cmd.prepareDub(handler.options);

// execute the command
try return cmd.execute(dub, remaining_args, command_args.appArgs);
// execute the command
return cmd.execute(dub, remaining_args, command_args.appArgs);
}
catch (UsageException e) {
// usage exceptions get thrown before any logging, so we are
// making the errors more narrow to better fit on small screens.
Expand Down Expand Up @@ -534,7 +536,7 @@ struct CommonOptions {
bool verbose, vverbose, quiet, vquiet, verror, version_;
bool help, annotate, bare;
string[] registry_urls;
string root_path;
string root_path, recipeFile;
enum Color { automatic, on, off }
Color colorMode = Color.automatic;
SkipPackageSuppliers skipRegistry = SkipPackageSuppliers.none;
Expand Down Expand Up @@ -568,6 +570,7 @@ struct CommonOptions {
{
args.getopt("h|help", &help, ["Display general or command specific help"]);
args.getopt("root", &root_path, ["Path to operate in instead of the current working dir"]);
args.getopt("recipe", &recipeFile, ["Loads a custom recipe path instead of dub.json/dub.sdl"]);
args.getopt("registry", &registry_urls, [
"Search the given registry URL first when resolving dependencies. Can be specified multiple times. Available registry types:",
" DUB: URL to DUB registry (default)",
Expand Down Expand Up @@ -836,11 +839,25 @@ class Command {
dub = new Dub(options.root_path, package_suppliers, options.skipRegistry);
dub.dryRun = options.annotate;
dub.defaultPlacementLocation = options.placementLocation;

dub.mainRecipePath = options.recipeFile;
// make the CWD package available so that for example sub packages can reference their
// parent package.
try dub.packageManager.getOrLoadPackage(NativePath(options.root_path), NativePath.init, false, StrictMode.Warn);
catch (Exception e) { logDiagnostic("No valid package found in current working directory: %s", e.msg); }
try dub.packageManager.getOrLoadPackage(NativePath(options.root_path), NativePath(options.recipeFile), false, StrictMode.Warn);
catch (Exception e) {
// by default we ignore CWD package load fails in prepareDUB, since
// they will fail again later when they are actually requested. This
// is done to provide custom options to the loading logic and should
// ideally be moved elsewhere. (This catch has been around since 10
// years when it was first introduced in _app.d_)
logDiagnostic("No valid package found in current working directory: %s", e.msg);

// for now, we work around not knowing if the package is needed or
// not, simply by trusting the user to only use `--recipe` when the
// recipe file actually exists, otherwise we throw the error.
bool loadMustSucceed = options.recipeFile.length > 0;
if (loadMustSucceed)
throw e;
}

return dub;
}
Expand Down Expand Up @@ -1168,6 +1185,7 @@ abstract class PackageBuildCommand : Command {
return true;
}


bool from_cwd = package_name.length == 0 || package_name.startsWith(":");
// load package in root_path to enable searching for sub packages
if (loadCwdPackage(dub, from_cwd)) {
Expand Down Expand Up @@ -1272,6 +1290,7 @@ class GenerateCommand : PackageBuildCommand {
if (!gensettings.config.length)
gensettings.config = m_defaultConfig;
gensettings.runArgs = app_args;
gensettings.recipeName = dub.mainRecipePath;
// legacy compatibility, default working directory is always CWD
gensettings.overrideToolWorkingDirectory = getWorkingDirectory();

Expand Down
9 changes: 9 additions & 0 deletions source/dub/dub.d
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class Dub {
PackageManager m_packageManager;
PackageSupplier[] m_packageSuppliers;
NativePath m_rootPath;
string m_mainRecipePath;
SpecialDirs m_dirs;
Settings m_config;
Project m_project;
Expand Down Expand Up @@ -391,6 +392,14 @@ class Dub {
/// application.
@property string projectName() const { return m_project.name; }

@property string mainRecipePath() const { return m_mainRecipePath; }
/// Whenever the switch --recipe= is supplied, this member will be populated.
@property string mainRecipePath(string recipePath)
{
return m_mainRecipePath = recipePath;
}


@property NativePath projectPath() const { return this.m_project.rootPackage.path; }

@property string[] configurations() const { return m_project.configurations; }
Expand Down
11 changes: 9 additions & 2 deletions source/dub/generators/build.d
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,16 @@ string computeBuildName(string config, in GeneratorSettings settings, const stri
addHash(settings.platform.architecture);
addHash(settings.platform.compiler);
addHash(settings.platform.compilerVersion);
if(settings.recipeName != "")
addHash(settings.recipeName);
const hashstr = Base64URL.encode(hash.finish()[0 .. $ / 2]).stripRight("=");

if(settings.recipeName != "")
{
import std.path:stripExtension, baseName;
string recipeName = settings.recipeName.baseName.stripExtension;
MrcSnm marked this conversation as resolved.
Show resolved Hide resolved
return format("%s-%s-%s-%s", config, settings.buildType, recipeName, hashstr);
}
return format("%s-%s-%s", config, settings.buildType, hashstr);
}

Expand Down Expand Up @@ -747,10 +755,9 @@ private string computeBuildID(in BuildSettings buildsettings, string config, Gen
(cast(uint)(buildsettings.options & ~BuildOption.color)).to!string, // exclude color option from id
settings.platform.compilerBinary,
settings.platform.compiler,
settings.platform.compilerVersion,
settings.platform.compilerVersion
],
];

return computeBuildName(config, settings, hashing);
}

Expand Down
1 change: 1 addition & 0 deletions source/dub/generators/generator.d
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ struct GeneratorSettings {
BuildPlatform platform;
Compiler compiler;
string config;
string recipeName;
MrcSnm marked this conversation as resolved.
Show resolved Hide resolved
string buildType;
BuildSettings buildSettings;
BuildMode buildMode = BuildMode.separate;
Expand Down
5 changes: 5 additions & 0 deletions test/issue2684-recipe-file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

cd ${CURR_DIR}/issue2684-recipe-file
${DUB} | grep -c "This was built using dub.json" > /dev/null
${DUB} --recipe=dubWithAnotherSource.json | grep -c "This was built using dubWithAnotherSource.json" > /dev/null
16 changes: 16 additions & 0 deletions test/issue2684-recipe-file/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.dub
docs.json
__dummy.html
docs/
/issue2684-recipe-file
issue2684-recipe-file.so
issue2684-recipe-file.dylib
issue2684-recipe-file.dll
issue2684-recipe-file.a
issue2684-recipe-file.lib
issue2684-recipe-file-test-*
*.exe
*.pdb
*.o
*.obj
*.lst
7 changes: 7 additions & 0 deletions test/issue2684-recipe-file/anotherSource/app.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module app;
import std.stdio;

void main()
{
writeln("This was built using dubWithAnotherSource.json");
}
9 changes: 9 additions & 0 deletions test/issue2684-recipe-file/dub.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"authors": [
"Hipreme"
],
"copyright": "Copyright © 2023, Hipreme",
"description": "A minimal D application.",
"license": "public domain",
"name": "issue2684-recipe-file"
}
10 changes: 10 additions & 0 deletions test/issue2684-recipe-file/dubWithAnotherSource.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"authors": [
"Hipreme"
],
"copyright": "Copyright © 2023, Hipreme",
"description": "A minimal D application.",
"sourcePaths": ["anotherSource"],
"license": "public domain",
"name": "issue2684-recipe-file"
}
10 changes: 10 additions & 0 deletions test/issue2684-recipe-file/source/app.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module app;
import std.stdio;

void main()
{
writeln("This was built using dub.json.
Try using the other configuration by calling dub with:
dub --recipe=dubWithAnotherSource.json
");
}