@@ -18,9 +18,13 @@ package packagemanager
1818import  (
1919	"fmt" 
2020	"net/url" 
21+ 	"os" 
2122	"path" 
23+ 	"path/filepath" 
24+ 	"strconv" 
2225	"strings" 
2326	"sync" 
27+ 	"time" 
2428
2529	"github.com/arduino/arduino-cli/arduino/cores" 
2630	"github.com/arduino/arduino-cli/arduino/cores/packageindex" 
@@ -29,6 +33,7 @@ import (
2933	"github.com/arduino/arduino-cli/i18n" 
3034	paths "github.com/arduino/go-paths-helper" 
3135	properties "github.com/arduino/go-properties-orderedmap" 
36+ 	"github.com/arduino/go-timeutils" 
3237	"github.com/sirupsen/logrus" 
3338	semver "go.bug.st/relaxed-semver" 
3439)
@@ -275,50 +280,141 @@ func (pme *Explorer) ResolveFQBN(fqbn *cores.FQBN) (
275280		return  targetPackage , nil , nil , nil , nil ,
276281			fmt .Errorf (tr ("unknown platform %s:%s" ), targetPackage , fqbn .PlatformArch )
277282	}
278- 	platformRelease  :=  pme .GetInstalledPlatformRelease (platform )
279- 	if  platformRelease  ==  nil  {
283+ 	boardPlatformRelease  :=  pme .GetInstalledPlatformRelease (platform )
284+ 	if  boardPlatformRelease  ==  nil  {
280285		return  targetPackage , nil , nil , nil , nil ,
281286			fmt .Errorf (tr ("platform %s is not installed" ), platform )
282287	}
283288
284289	// Find board 
285- 	board  :=  platformRelease .Boards [fqbn .BoardID ]
290+ 	board  :=  boardPlatformRelease .Boards [fqbn .BoardID ]
286291	if  board  ==  nil  {
287- 		return  targetPackage , platformRelease , nil , nil , nil ,
292+ 		return  targetPackage , boardPlatformRelease , nil , nil , nil ,
288293			fmt .Errorf (tr ("board %s not found" ), fqbn .StringWithoutConfig ())
289294	}
290295
291- 	buildProperties , err  :=  board .GetBuildProperties (fqbn .Configs )
296+ 	boardBuildProperties , err  :=  board .GetBuildProperties (fqbn .Configs )
292297	if  err  !=  nil  {
293- 		return  targetPackage , platformRelease , board , nil , nil ,
298+ 		return  targetPackage , boardPlatformRelease , board , nil , nil ,
294299			fmt .Errorf (tr ("getting build properties for board %[1]s: %[2]s" ), board , err )
295300	}
296301
297- 	// Determine the platform used for the build (in case the board refers 
302+ 	// Determine the platform used for the build and the variant  (in case the board refers 
298303	// to a core contained in another platform) 
299- 	buildPlatformRelease  :=  platformRelease 
300- 	coreParts  :=  strings .Split (buildProperties .Get ("build.core" ), ":" )
301- 	if  len (coreParts ) >  1  {
302- 		referredPackage  :=  coreParts [0 ]
303- 		buildPackage  :=  pme .packages [referredPackage ]
304- 		if  buildPackage  ==  nil  {
305- 			return  targetPackage , platformRelease , board , buildProperties , nil ,
306- 				fmt .Errorf (tr ("missing package %[1]s referenced by board %[2]s" ), referredPackage , fqbn )
304+ 	core , corePlatformRelease , variant , variantPlatformRelease , err  :=  pme .determineReferencedPlatformRelease (boardBuildProperties , boardPlatformRelease , fqbn )
305+ 	if  err  !=  nil  {
306+ 		return  targetPackage , boardPlatformRelease , board , nil , nil , err 
307+ 	}
308+ 
309+ 	// Create the build properties map by overlaying the properties of the 
310+ 	// referenced platform propeties, the board platform properties and the 
311+ 	// board specific properties. 
312+ 	buildProperties  :=  properties .NewMap ()
313+ 	buildProperties .Merge (variantPlatformRelease .Properties )
314+ 	buildProperties .Merge (corePlatformRelease .Properties )
315+ 	buildProperties .Merge (boardPlatformRelease .Properties )
316+ 	buildProperties .Merge (boardBuildProperties )
317+ 
318+ 	// Add runtime build properties 
319+ 	buildProperties .Merge (boardPlatformRelease .RuntimeProperties ())
320+ 	buildProperties .SetPath ("build.core.path" , corePlatformRelease .InstallDir .Join ("cores" , core ))
321+ 	buildProperties .SetPath ("build.system.path" , corePlatformRelease .InstallDir .Join ("system" ))
322+ 	buildProperties .Set ("build.variant.path" , "" )
323+ 	if  variant  !=  ""  {
324+ 		buildProperties .SetPath ("build.variant.path" , variantPlatformRelease .InstallDir .Join ("variants" , variant ))
325+ 	}
326+ 
327+ 	for  _ , tool  :=  range  pme .GetAllInstalledToolsReleases () {
328+ 		buildProperties .Merge (tool .RuntimeProperties ())
329+ 	}
330+ 	requiredTools , err  :=  pme .FindToolsRequiredForBuild (boardPlatformRelease , corePlatformRelease )
331+ 	if  err  !=  nil  {
332+ 		return  targetPackage , boardPlatformRelease , board , buildProperties , corePlatformRelease , err 
333+ 	}
334+ 	for  _ , tool  :=  range  requiredTools  {
335+ 		buildProperties .Merge (tool .RuntimeProperties ())
336+ 	}
337+ 	now  :=  time .Now ()
338+ 	buildProperties .Set ("extra.time.utc" , strconv .FormatInt (now .Unix (), 10 ))
339+ 	buildProperties .Set ("extra.time.local" , strconv .FormatInt (timeutils .LocalUnix (now ), 10 ))
340+ 	buildProperties .Set ("extra.time.zone" , strconv .Itoa (timeutils .TimezoneOffsetNoDST (now )))
341+ 	buildProperties .Set ("extra.time.dst" , strconv .Itoa (timeutils .DaylightSavingsOffset (now )))
342+ 
343+ 	if  ! buildProperties .ContainsKey ("runtime.ide.path" ) {
344+ 		if  ex , err  :=  os .Executable (); err  ==  nil  {
345+ 			buildProperties .Set ("runtime.ide.path" , filepath .Dir (ex ))
346+ 		} else  {
347+ 			buildProperties .Set ("runtime.ide.path" , "" )
307348		}
308- 		buildPlatform  :=  buildPackage .Platforms [fqbn .PlatformArch ]
309- 		if  buildPlatform  ==  nil  {
310- 			return  targetPackage , platformRelease , board , buildProperties , nil ,
311- 				fmt .Errorf (tr ("missing platform %[1]s:%[2]s referenced by board %[3]s" ), referredPackage , fqbn .PlatformArch , fqbn )
349+ 	}
350+ 	buildProperties .Set ("runtime.os" , properties .GetOSSuffix ())
351+ 	buildProperties .Set ("build.library_discovery_phase" , "0" )
352+ 	// Deprecated properties 
353+ 	buildProperties .Set ("ide_version" , "10607" )
354+ 	buildProperties .Set ("runtime.ide.version" , "10607" )
355+ 	if  ! buildProperties .ContainsKey ("software" ) {
356+ 		buildProperties .Set ("software" , "ARDUINO" )
357+ 	}
358+ 
359+ 	buildProperties .Merge (pme .GetCustomGlobalProperties ())
360+ 
361+ 	return  targetPackage , boardPlatformRelease , board , buildProperties , corePlatformRelease , nil 
362+ }
363+ 
364+ func  (pme  * Explorer ) determineReferencedPlatformRelease (boardBuildProperties  * properties.Map , boardPlatformRelease  * cores.PlatformRelease , fqbn  * cores.FQBN ) (string , * cores.PlatformRelease , string , * cores.PlatformRelease , error ) {
365+ 	core  :=  boardBuildProperties .Get ("build.core" )
366+ 	referredCore  :=  "" 
367+ 	if  split  :=  strings .Split (core , ":" ); len (split ) >  1  {
368+ 		referredCore , core  =  split [0 ], split [1 ]
369+ 	}
370+ 
371+ 	variant  :=  boardBuildProperties .Get ("build.variant" )
372+ 	referredVariant  :=  "" 
373+ 	if  split  :=  strings .Split (variant , ":" ); len (split ) >  1  {
374+ 		referredVariant , variant  =  split [0 ], split [1 ]
375+ 	}
376+ 
377+ 	// core and variant cannot refer to two different platforms 
378+ 	if  referredCore  !=  ""  &&  referredVariant  !=  ""  &&  referredCore  !=  referredVariant  {
379+ 		return  "" , nil , "" , nil ,
380+ 			fmt .Errorf (tr ("'build.core' and 'build.variant' refer to different platforms: %[1]s and %[2]s" ), referredCore + ":" + core , referredVariant + ":" + variant )
381+ 	}
382+ 
383+ 	// extract the referred platform 
384+ 	var  referredPlatformRelease  * cores.PlatformRelease 
385+ 	referredPackageName  :=  referredCore 
386+ 	if  referredPackageName  ==  ""  {
387+ 		referredPackageName  =  referredVariant 
388+ 	}
389+ 	if  referredPackageName  !=  ""  {
390+ 		referredPackage  :=  pme .packages [referredPackageName ]
391+ 		if  referredPackage  ==  nil  {
392+ 			return  "" , nil , "" , nil ,
393+ 				fmt .Errorf (tr ("missing package %[1]s referenced by board %[2]s" ), referredPackageName , fqbn )
394+ 		}
395+ 		referredPlatform  :=  referredPackage .Platforms [fqbn .PlatformArch ]
396+ 		if  referredPlatform  ==  nil  {
397+ 			return  "" , nil , "" , nil ,
398+ 				fmt .Errorf (tr ("missing platform %[1]s:%[2]s referenced by board %[3]s" ), referredPackageName , fqbn .PlatformArch , fqbn )
312399		}
313- 		buildPlatformRelease  =  pme .GetInstalledPlatformRelease (buildPlatform )
314- 		if  buildPlatformRelease  ==  nil  {
315- 			return  targetPackage ,  platformRelease ,  board ,  buildProperties , nil ,
316- 				fmt .Errorf (tr ("missing platform release %[1]s:%[2]s referenced by board %[3]s" ), referredPackage , fqbn .PlatformArch , fqbn )
400+ 		referredPlatformRelease  =  pme .GetInstalledPlatformRelease (referredPlatform )
401+ 		if  referredPlatformRelease  ==  nil  {
402+ 			return  "" ,  nil ,  "" , nil ,
403+ 				fmt .Errorf (tr ("missing platform release %[1]s:%[2]s referenced by board %[3]s" ), referredPackageName , fqbn .PlatformArch , fqbn )
317404		}
318405	}
319406
320- 	// No errors... phew! 
321- 	return  targetPackage , platformRelease , board , buildProperties , buildPlatformRelease , nil 
407+ 	corePlatformRelease  :=  boardPlatformRelease 
408+ 	if  referredCore  !=  ""  {
409+ 		corePlatformRelease  =  referredPlatformRelease 
410+ 	}
411+ 
412+ 	variantPlatformRelease  :=  boardPlatformRelease 
413+ 	if  referredVariant  !=  ""  {
414+ 		variantPlatformRelease  =  referredPlatformRelease 
415+ 	}
416+ 
417+ 	return  core , corePlatformRelease , variant , variantPlatformRelease , nil 
322418}
323419
324420// LoadPackageIndex loads a package index by looking up the local cached file from the specified URL 
0 commit comments