diff --git a/commands/compile/compile.go b/commands/compile/compile.go index 664368e067c..da794cec1f4 100644 --- a/commands/compile/compile.go +++ b/commands/compile/compile.go @@ -133,6 +133,13 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream 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} @@ -315,3 +322,24 @@ func maybePurgeBuildCache() { buildcache.New(paths.TempDir().Join("arduino", "cores")).Purge(cacheTTL) buildcache.New(paths.TempDir().Join("arduino", "sketches")).Purge(cacheTTL) } + +// removeBuildFromSketchFiles removes the files contained in the build directory from +// the list of the sketch files +func removeBuildFromSketchFiles(files paths.PathList, build *paths.Path) (paths.PathList, error) { + var res paths.PathList + ignored := false + for _, file := range files { + if in, err := file.IsInsideDir(build); err != nil { + return nil, &arduino.NotFoundError{Message: tr("Cannot find build path"), Cause: err} + } else if !in { + res = append(res, file) + } else if !ignored { + ignored = true + } + } + // log only if at least a file is ignored + if ignored { + logrus.Tracef("Build path %s is a child of sketch path and it is ignored for additional files.", build.String()) + } + return res, nil +} diff --git a/internal/integrationtest/compile_3/compile_test.go b/internal/integrationtest/compile_3/compile_test.go index 4ed80280c9a..3337392bb00 100644 --- a/internal/integrationtest/compile_3/compile_test.go +++ b/internal/integrationtest/compile_3/compile_test.go @@ -72,3 +72,27 @@ func TestRuntimeToolPropertiesGeneration(t *testing.T) { require.True(t, res.GetPath("runtime.tools.avrdude.path").EquivalentTo(hardwareDir.Join("arduino", "tools", "avrdude", "6.3.0-arduino17"))) } } + +func TestCompileBuildPathInsideSketch(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("core", "update-index") + require.NoError(t, err) + + _, _, err = cli.Run("core", "install", "arduino:avr") + require.NoError(t, err) + + sketch := "sketchSimple" + _, _, err = cli.Run("sketch", "new", sketch) + require.NoError(t, err) + + cli.SetWorkingDir(cli.WorkingDir().Join(sketch)) + // Compile the sketch creating the build directory inside the sketch directory + _, _, err = cli.Run("compile", "-b", "arduino:avr:mega", "--build-path", "build-mega") + require.NoError(t, err) + + // Compile again using the same build path + _, _, err = cli.Run("compile", "-b", "arduino:avr:mega", "--build-path", "build-mega") + require.NoError(t, err) +}