@@ -23,6 +23,7 @@ import dub.package_;
2323import dub.project;
2424
2525import dub.compilers.compiler;
26+ import dub.generators.build;
2627import dub.generators.generator;
2728
2829import dub.compilers.buildsettings;
@@ -55,14 +56,8 @@ class DubComponent : ComponentWrapper
5556 try
5657 {
5758 start();
58- // upgrade();
5959
60- _compilerBinaryName = _dub.defaultCompiler;
61- Compiler compiler = getCompiler(_compilerBinaryName);
62- BuildSettings settings;
63- auto platform = compiler.determinePlatform(settings, _compilerBinaryName);
64-
65- _configuration = _dub.project.getDefaultConfiguration(platform);
60+ _configuration = _dub.project.getDefaultConfiguration(_platform);
6661 if (! _dub.project.configurations.canFind(_configuration))
6762 {
6863 stderr.writeln(" Dub Error: No configuration available" );
@@ -78,28 +73,97 @@ class DubComponent : ComponentWrapper
7873 throw e;
7974 stderr.writeln(" Dub Error (ignored): " , e);
8075 }
81- catch (AssertError e)
76+ /* catch (AssertError e)
8277 {
8378 if (!_dub || !_dub.project)
8479 throw e;
8580 stderr.writeln("Dub Error (ignored): ", e);
86- }
81+ }*/
8782 }
8883
8984 private void start ()
9085 {
86+ _dubRunning = false ;
9187 _dub = new Dub(instance.cwd, null , SkipPackageSuppliers.none);
9288 _dub.packageManager.getOrLoadPackage(NativePath(instance.cwd));
9389 _dub.loadPackage();
9490 _dub.project.validate();
91+
92+ // mark all packages as optional so we don't crash
93+ int missingPackages;
94+ auto optionalified = optionalifyPackages;
95+ foreach (ref pkg; _dub.project.getTopologicalPackageList())
96+ {
97+ optionalifyRecipe(pkg);
98+ foreach (dep; pkg.getAllDependencies().filter! (a => optionalified.canFind(a.name)))
99+ {
100+ auto d = _dub.project.getDependency(dep.name, true );
101+ if (! d)
102+ missingPackages++ ;
103+ else
104+ optionalifyRecipe(d);
105+ }
106+ }
107+
108+ if (! _compilerBinaryName.length)
109+ _compilerBinaryName = _dub.defaultCompiler;
110+ setCompiler(_compilerBinaryName);
111+ if (missingPackages > 0 )
112+ {
113+ upgrade(false );
114+ optionalifyPackages();
115+ }
116+
117+ _dubRunning = true ;
118+ }
119+
120+ private string [] optionalifyPackages ()
121+ {
122+ bool [Package] visited;
123+ string [] optionalified;
124+ foreach (pkg; _dub.project.dependencies)
125+ optionalified ~= optionalifyRecipe(cast () pkg);
126+ return optionalified;
127+ }
128+
129+ private string [] optionalifyRecipe (Package pkg)
130+ {
131+ string [] optionalified;
132+ foreach (key, ref value; pkg.recipe.buildSettings.dependencies)
133+ {
134+ if (! value.optional)
135+ {
136+ value.optional = true ;
137+ value.default_ = true ;
138+ optionalified ~= key;
139+ }
140+ }
141+ foreach (ref config; pkg.recipe.configurations)
142+ foreach (key, ref value; config.buildSettings.dependencies)
143+ {
144+ if (! value.optional)
145+ {
146+ value.optional = true ;
147+ value.default_ = true ;
148+ optionalified ~= key;
149+ }
150+ }
151+ return optionalified;
95152 }
96153
97154 private void restart ()
98155 {
99156 _dub.destroy ();
157+ _dubRunning = false ;
100158 start();
101159 }
102160
161+ bool isRunning ()
162+ {
163+ return _dub ! is null && _dub.project ! is null && _dub.project.rootPackage ! is null
164+ && _dubRunning;
165+ }
166+
103167 // / Reloads the dub.json or dub.sdl file from the cwd
104168 // / Returns: `false` if there are no import paths available
105169 Future! bool update ()
@@ -127,17 +191,13 @@ class DubComponent : ComponentWrapper
127191 if (restartDub)
128192 restart();
129193
130- auto compiler = getCompiler(_compilerBinaryName);
131- BuildSettings buildSettings;
132- auto buildPlatform = compiler.determinePlatform(buildSettings, _compilerBinaryName, _archType);
133-
134194 GeneratorSettings settings;
135- settings.platform = buildPlatform ;
195+ settings.platform = _platform ;
136196 settings.config = _configuration;
137197 settings.buildType = _buildType;
138- settings.compiler = compiler ;
139- settings.buildSettings = buildSettings ;
140- settings.buildSettings.options |= BuildOption.syntaxOnly;
198+ settings.compiler = _compiler ;
199+ settings.buildSettings = _settings ;
200+ settings.buildSettings.addOptions( BuildOption.syntaxOnly) ;
141201 settings.combined = true ;
142202 settings.run = false ;
143203
@@ -162,9 +222,12 @@ class DubComponent : ComponentWrapper
162222 }
163223
164224 // / Calls `dub upgrade`
165- void upgrade ()
225+ void upgrade (bool save = true )
166226 {
167- _dub.upgrade(UpgradeOptions.select | UpgradeOptions.upgrade);
227+ if (save)
228+ _dub.upgrade(UpgradeOptions.select | UpgradeOptions.upgrade);
229+ else
230+ _dub.upgrade(UpgradeOptions.noSaveSelections);
168231 }
169232
170233 // / Throws if configuration is invalid, otherwise does nothing.
@@ -174,6 +237,17 @@ class DubComponent : ComponentWrapper
174237 throw new Exception (" Cannot use dub with invalid configuration" );
175238 }
176239
240+ // / Throws if configuration is invalid or targetType is none or source library, otherwise does nothing.
241+ void validateBuildConfiguration ()
242+ {
243+ if (! _dub.project.configurations.canFind(_configuration))
244+ throw new Exception (" Cannot use dub with invalid configuration" );
245+ if (_settings.targetType == TargetType.none)
246+ throw new Exception (" Cannot build with dub with targetType == none" );
247+ if (_settings.targetType == TargetType.sourceLibrary)
248+ throw new Exception (" Cannot build with dub with targetType == sourceLibrary" );
249+ }
250+
177251 // / Lists all dependencies. This will go through all dependencies and contain the dependencies of dependencies. You need to create a tree structure from this yourself.
178252 // / Returns: `[{dependencies: [string], ver: string, name: string}]`
179253 auto dependencies () @property
@@ -249,7 +323,7 @@ class DubComponent : ComponentWrapper
249323 {
250324 string [] types = [" x86_64" , " x86" ];
251325
252- string compilerName = getCompiler(_compilerBinaryName) .name;
326+ string compilerName = _compiler .name;
253327
254328 version (Windows )
255329 {
@@ -326,13 +400,14 @@ class DubComponent : ComponentWrapper
326400 try
327401 {
328402 _compilerBinaryName = compiler;
329- Compiler comp = getCompiler(compiler); // make sure it gets a valid compiler
330- return true ;
403+ _compiler = getCompiler(compiler); // make sure it gets a valid compiler
331404 }
332405 catch (Exception e)
333406 {
334407 return false ;
335408 }
409+ _platform = _compiler.determinePlatform(_settings, _compilerBinaryName, _archType);
410+ return true ;
336411 }
337412
338413 // / Returns the project name
@@ -350,38 +425,35 @@ class DubComponent : ComponentWrapper
350425 // / Returns whether there is a target set to build. If this is false then build will throw an exception.
351426 bool canBuild () @property
352427 {
353- if (! _dub.project.configurations.canFind(_configuration))
428+ if (_settings.targetType == TargetType.none || _settings.targetType == TargetType.sourceLibrary
429+ || ! _dub.project.configurations.canFind(_configuration))
354430 return false ;
355- auto compiler = getCompiler(_compilerBinaryName);
356- BuildSettings buildSettings;
357- compiler.determinePlatform(buildSettings, _compilerBinaryName, _archType);
358431 return true ;
359432 }
360433
361434 // / Asynchroniously builds the project WITHOUT OUTPUT. This is intended for linting code and showing build errors quickly inside the IDE.
362435 Future! (BuildIssue[]) build ()
363436 {
364- validateConfiguration();
437+ validateBuildConfiguration();
438+
439+ // copy to this thread
440+ auto compiler = _compiler;
441+ auto buildPlatform = _platform;
442+
443+ GeneratorSettings settings;
444+ settings.platform = buildPlatform;
445+ settings.config = _configuration;
446+ settings.buildType = _buildType;
447+ settings.compiler = compiler;
448+ settings.tempBuild = true ;
449+ settings.buildSettings = _settings;
450+ settings.buildSettings.addOptions(BuildOption.syntaxOnly);
451+ settings.buildSettings.addDFlags(" -o-" );
365452
366453 auto ret = new Future! (BuildIssue[]);
367454 new Thread ({
368455 try
369456 {
370- auto compiler = getCompiler(_compilerBinaryName);
371- BuildSettings buildSettings;
372- auto buildPlatform = compiler.determinePlatform(buildSettings,
373- _compilerBinaryName, _archType);
374-
375- GeneratorSettings settings;
376- settings.platform = buildPlatform;
377- settings.config = _configuration;
378- settings.buildType = _buildType;
379- settings.compiler = compiler;
380- settings.tempBuild = true ;
381- settings.buildSettings = buildSettings;
382- settings.buildSettings.addOptions(BuildOption.syntaxOnly);
383- settings.buildSettings.addDFlags(" -o-" );
384-
385457 BuildIssue[] issues;
386458
387459 settings.compileCallback = (status, output) {
@@ -440,12 +512,13 @@ class DubComponent : ComponentWrapper
440512
441513private :
442514 Dub _dub;
515+ bool _dubRunning = false ;
443516 string _configuration;
444517 string _archType = " x86_64" ;
445518 string _buildType = " debug" ;
446519 string _compilerBinaryName;
447- BuildSettings _settings;
448520 Compiler _compiler;
521+ BuildSettings _settings;
449522 BuildPlatform _platform;
450523 string [] _importPaths, _stringImportPaths, _importFiles;
451524}
0 commit comments