Skip to content

feat: allow to show compilation properties without providing a sketch #2089

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 79 additions & 53 deletions commands/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,14 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
return nil, &arduino.MissingSketchPathError{}
}
sketchPath := paths.New(req.GetSketchPath())
sk, err := sketch.New(sketchPath)
if err != nil {
return nil, &arduino.CantOpenSketchError{Cause: err}
builderCtx := &types.Context{}
builderCtx.PackageManager = pme
if pme.GetProfile() != nil {
builderCtx.LibrariesManager = lm
}

sk, newSketchErr := sketch.New(sketchPath)

fqbnIn := req.GetFqbn()
if fqbnIn == "" && sk != nil {
fqbnIn = sk.GetDefaultFQBN()
Expand Down Expand Up @@ -111,13 +114,13 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
securityKeysOverride = append(securityKeysOverride, "build.keys.keychain="+req.KeysKeychain, "build.keys.sign_key="+req.GetSignKey(), "build.keys.encrypt_key="+req.EncryptKey)
}

builderCtx := &types.Context{}
builderCtx.PackageManager = pme
if pme.GetProfile() != nil {
builderCtx.LibrariesManager = lm
}
builderCtx.UseCachedLibrariesResolution = req.GetSkipLibrariesDiscovery()
builderCtx.FQBN = fqbn
defer func() {
appendBuildProperties(r, builderCtx)
}()
r = &rpc.CompileResponse{}

builderCtx.Sketch = sk
builderCtx.ProgressCB = progressCB

Expand All @@ -129,30 +132,11 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
builderCtx.OtherLibrariesDirs = paths.NewPathList(req.GetLibraries()...)
builderCtx.OtherLibrariesDirs.Add(configuration.LibrariesDir(configuration.Settings))
builderCtx.LibraryDirs = paths.NewPathList(req.Library...)
if req.GetBuildPath() == "" {
builderCtx.BuildPath = sk.DefaultBuildPath()
} else {
builderCtx.BuildPath = paths.New(req.GetBuildPath()).Canonical()
if in, err := builderCtx.BuildPath.IsInsideDir(sk.FullPath); err != nil {
return nil, &arduino.NotFoundError{Message: tr("Cannot find build path"), Cause: err}
} else if in && builderCtx.BuildPath.IsDir() {
if sk.AdditionalFiles, err = removeBuildFromSketchFiles(sk.AdditionalFiles, builderCtx.BuildPath); err != nil {
return nil, err
}
}
}
if err = builderCtx.BuildPath.MkdirAll(); err != nil {
return nil, &arduino.PermissionDeniedError{Message: tr("Cannot create build directory"), Cause: err}
err = prepareBuildPath(sk, req.GetBuildPath(), builderCtx)
if err != nil {
return r, err
}

buildcache.New(builderCtx.BuildPath.Parent()).GetOrCreate(builderCtx.BuildPath.Base())
// cache is purged after compilation to not remove entries that might be required
defer maybePurgeBuildCache()

builderCtx.CompilationDatabase = bldr.NewCompilationDatabase(
builderCtx.BuildPath.Join("compile_commands.json"),
)

builderCtx.Verbose = req.GetVerbose()

// Optimize for debug
Expand Down Expand Up @@ -187,7 +171,6 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
builderCtx.OnlyUpdateCompilationDatabase = req.GetCreateCompilationDatabaseOnly()
builderCtx.SourceOverride = req.GetSourceOverride()

r = &rpc.CompileResponse{}
defer func() {
if p := builderCtx.BuildPath; p != nil {
r.BuildPath = p.String()
Expand All @@ -200,18 +183,6 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
}
}()

defer func() {
buildProperties := builderCtx.BuildProperties
if buildProperties == nil {
return
}
keys := buildProperties.Keys()
sort.Strings(keys)
for _, key := range keys {
r.BuildProperties = append(r.BuildProperties, key+"="+buildProperties.Get(key))
}
}()

if req.GetShowProperties() {
// Just get build properties and exit
compileErr := builder.RunParseHardware(builderCtx)
Expand All @@ -221,6 +192,15 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
return r, compileErr
}

if newSketchErr != nil {
// newSketchErr causes to exit only here since the request could have
// been to only show properties until now
return r, &arduino.CantOpenSketchError{Cause: err}
}

// cache is purged after compilation to not remove entries that might be required
defer maybePurgeBuildCache()

if req.GetPreprocess() {
// Just output preprocessed source code and exit
compileErr := builder.RunPreprocess(builderCtx)
Expand All @@ -231,16 +211,7 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
}

defer func() {
importedLibs := []*rpc.Library{}
for _, lib := range builderCtx.ImportedLibraries {
rpcLib, err := lib.ToRPCLibrary()
if err != nil {
msg := tr("Error getting information for library %s", lib.Name) + ": " + err.Error() + "\n"
errStream.Write([]byte(msg))
}
importedLibs = append(importedLibs, rpcLib)
}
r.UsedLibraries = importedLibs
appendUserLibraries(r, builderCtx, errStream)
}()

// if it's a regular build, go on...
Expand Down Expand Up @@ -309,6 +280,61 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
return r, nil
}

func prepareBuildPath(sk *sketch.Sketch, requestedBuildPath string, builderCtx *types.Context) error {
if sk == nil {
return nil
}

if requestedBuildPath == "" {
builderCtx.BuildPath = sk.DefaultBuildPath()
} else {
builderCtx.BuildPath = paths.New(requestedBuildPath).Canonical()
if in, err := builderCtx.BuildPath.IsInsideDir(sk.FullPath); err != nil {
return &arduino.NotFoundError{Message: tr("Cannot find build path"), Cause: err}
} else if in && builderCtx.BuildPath.IsDir() {
if sk.AdditionalFiles, err = removeBuildFromSketchFiles(sk.AdditionalFiles, builderCtx.BuildPath); err != nil {
return err
}
}
}

if err := builderCtx.BuildPath.MkdirAll(); err != nil {
return &arduino.PermissionDeniedError{Message: tr("Cannot create build directory"), Cause: err}
}

builderCtx.CompilationDatabase = bldr.NewCompilationDatabase(
builderCtx.BuildPath.Join("compile_commands.json"),
)
buildcache.New(builderCtx.BuildPath.Parent()).GetOrCreate(builderCtx.BuildPath.Base())
return nil
}

func appendUserLibraries(r *rpc.CompileResponse, builderCtx *types.Context, errStream io.Writer) {
importedLibs := []*rpc.Library{}
for _, lib := range builderCtx.ImportedLibraries {
rpcLib, err := lib.ToRPCLibrary()
if err != nil {
msg := tr("Error getting information for library %s", lib.Name) + ": " + err.Error() + "\n"
errStream.Write([]byte(msg))
}
importedLibs = append(importedLibs, rpcLib)
}
r.UsedLibraries = importedLibs
}

func appendBuildProperties(r *rpc.CompileResponse, builderCtx *types.Context) bool {
buildProperties := builderCtx.BuildProperties
if buildProperties == nil {
return true
}
keys := buildProperties.Keys()
sort.Strings(keys)
for _, key := range keys {
r.BuildProperties = append(r.BuildProperties, key+"="+buildProperties.Get(key))
}
return false
}

// maybePurgeBuildCache runs the build files cache purge if the policy conditions are met.
func maybePurgeBuildCache() {

Expand Down
8 changes: 7 additions & 1 deletion internal/cli/arguments/sketch.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ func InitSketchPath(path string) (sketchPath *paths.Path) {
}

// NewSketch is a helper function useful to create a sketch instance
func NewSketch(sketchPath *paths.Path) *sketch.Sketch {
func NewSketch(sketchPath *paths.Path) (*sketch.Sketch, error) {
return sketch.New(sketchPath)
}

// MustNewSketch is a helper function useful to create a sketch instance, exits if the
// initialization fails
func MustNewSketch(sketchPath *paths.Path) *sketch.Sketch {
sketch, err := sketch.New(sketchPath)
if err != nil {
feedback.Fatal(tr("Error opening sketch: %v", err), feedback.ErrGeneric)
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/board/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func initAttachCommand() *cobra.Command {

func runAttachCommand(path string, port *arguments.Port, fqbn string) {
sketchPath := arguments.InitSketchPath(path)
sk := arguments.NewSketch(sketchPath)
sk := arguments.MustNewSketch(sketchPath)

var currentPort *boardAttachPortResult
if currentAddress, currentProtocol := sk.GetDefaultPortAddressAndProtocol(); currentAddress != "" {
Expand Down
22 changes: 16 additions & 6 deletions internal/cli/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,29 @@ func runCompileCommand(cmd *cobra.Command, args []string) {
feedback.Fatal(tr("You cannot use the %s flag while compiling with a profile.", "--library"), feedback.ErrBadArgument)
}
}
showPropertiesM, err := parseShowPropertiesMode(showProperties)
if err != nil {
feedback.Fatal(tr("Error parsing --show-properties flag: %v", err), feedback.ErrGeneric)
}

path := ""
if len(args) > 0 {
path = args[0]
}

sketchPath := arguments.InitSketchPath(path)
sk := arguments.NewSketch(sketchPath)
sk, err := arguments.NewSketch(sketchPath)

if err != nil {
showPropertiesWithEmptySketchPath := path == "" && showPropertiesM != showPropertiesModeDisabled
if showPropertiesWithEmptySketchPath {
// only properties were requested and no sketch path was provided
// an empty sketch is used to collect properties without sketch related values
sk = nil
} else {
feedback.Fatal(tr("Error opening sketch: %v", err), feedback.ErrGeneric)
}
}

inst, profile := instance.CreateAndInitWithProfile(profileArg.Get(), sketchPath)
if fqbnArg.String() == "" {
Expand Down Expand Up @@ -215,11 +230,6 @@ func runCompileCommand(cmd *cobra.Command, args []string) {
overrides = o.Overrides
}

showPropertiesM, err := parseShowPropertiesMode(showProperties)
if err != nil {
feedback.Fatal(tr("Error parsing --show-properties flag: %v", err), feedback.ErrGeneric)
}

var stdOut, stdErr io.Writer
var stdIORes func() *feedback.OutputStreamsResult
if showPropertiesM != showPropertiesModeDisabled {
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func runDebugCommand(command *cobra.Command, args []string) {
}

sketchPath := arguments.InitSketchPath(path)
sk := arguments.NewSketch(sketchPath)
sk := arguments.MustNewSketch(sketchPath)
fqbn, port := arguments.CalculateFQBNAndPort(&portArgs, &fqbnArg, instance, sk)
debugConfigRequested := &dbg.DebugConfigRequest{
Instance: instance,
Expand Down
3 changes: 3 additions & 0 deletions legacy/builder/fail_if_buildpath_equals_sketchpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
type FailIfBuildPathEqualsSketchPath struct{}

func (s *FailIfBuildPathEqualsSketchPath) Run(ctx *types.Context) error {
if ctx.BuildPath == nil || ctx.Sketch == nil {
return nil
}
buildPath := ctx.BuildPath.Canonical()
sketchPath := ctx.Sketch.FullPath.Canonical()
if buildPath.EqualsTo(sketchPath) {
Expand Down
4 changes: 3 additions & 1 deletion legacy/builder/setup_build_properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ func (s *SetupBuildProperties) Run(ctx *types.Context) error {
}
ctx.OptimizationFlags = buildProperties.Get("compiler.optimization_flags")

buildProperties.SetPath("build.source.path", ctx.Sketch.FullPath)
if ctx.Sketch != nil {
buildProperties.SetPath("build.source.path", ctx.Sketch.FullPath)
}

keychainProp := buildProperties.ContainsKey("build.keys.keychain")
signProp := buildProperties.ContainsKey("build.keys.sign_key")
Expand Down