diff --git a/legacy/builder/constants/constants.go b/legacy/builder/constants/constants.go index 5773f4d770d..7e35760adb3 100644 --- a/legacy/builder/constants/constants.go +++ b/legacy/builder/constants/constants.go @@ -86,7 +86,9 @@ const MSG_ERROR_ARCHIVING_CORE_CACHE = "Error archiving built core (caching) in const MSG_CORE_CACHE_UNAVAILABLE = "Unable to cache built core, please tell {0} maintainers to follow https://arduino.github.io/arduino-cli/latest/platform-specification/#recipes-to-build-the-corea-archive-file" const MSG_BOARD_UNKNOWN = "Board {0} (platform {1}, package {2}) is unknown" const MSG_BOOTLOADER_FILE_MISSING = "Bootloader file specified but missing: {0}" -const MSG_BUILD_OPTIONS_CHANGED = "Build options changed, rebuilding all" +const MSG_REBUILD_ALL = ", rebuilding all" +const MSG_BUILD_OPTIONS_CHANGED = "Build options changed" +const MSG_BUILD_OPTIONS_INVALID = "{0} invalid" const MSG_CANT_FIND_SKETCH_IN_PATH = "Unable to find {0} in {1}" const MSG_FQBN_INVALID = "{0} is not a valid fully qualified board name. Required format is targetPackageName:targetPlatformName:targetBoardName." const MSG_SKIP_PRECOMPILED_LIBRARY = "Skipping dependencies detection for precompiled library {0}" diff --git a/legacy/builder/wipeout_build_path_if_build_options_changed.go b/legacy/builder/wipeout_build_path_if_build_options_changed.go index 57be59838d6..fbb621626ea 100644 --- a/legacy/builder/wipeout_build_path_if_build_options_changed.go +++ b/legacy/builder/wipeout_build_path_if_build_options_changed.go @@ -40,9 +40,15 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error { previousBuildOptionsJson := ctx.BuildOptionsJsonPrevious var opts *properties.Map + if err := json.Unmarshal([]byte(buildOptionsJson), &opts); err != nil || opts == nil { + panic(constants.BUILD_OPTIONS_FILE + " is invalid") + } + var prevOpts *properties.Map - json.Unmarshal([]byte(buildOptionsJson), &opts) - json.Unmarshal([]byte(previousBuildOptionsJson), &prevOpts) + if err := json.Unmarshal([]byte(previousBuildOptionsJson), &prevOpts); err != nil || prevOpts == nil { + ctx.GetLogger().Println(constants.LOG_LEVEL_DEBUG, constants.MSG_BUILD_OPTIONS_INVALID + constants.MSG_REBUILD_ALL, constants.BUILD_OPTIONS_FILE) + return doCleanup(ctx.BuildPath) + } // If SketchLocation path is different but filename is the same, consider it equal if filepath.Base(opts.Get("sketchLocation")) == filepath.Base(prevOpts.Get("sketchLocation")) { @@ -73,7 +79,7 @@ func (s *WipeoutBuildPathIfBuildOptionsChanged) Run(ctx *types.Context) error { func doCleanup(buildPath *paths.Path) error { // FIXME: this should go outside legacy and behind a `logrus` call so users can // control when this should be printed. - // logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED) + // logger.Println(constants.LOG_LEVEL_INFO, constants.MSG_BUILD_OPTIONS_CHANGED + constants.MSG_REBUILD_ALL) if files, err := buildPath.ReadDir(); err != nil { return errors.WithMessage(err, "cleaning build path") diff --git a/test/test_compile.py b/test/test_compile.py index c1374aaf607..ffff1931092 100644 --- a/test/test_compile.py +++ b/test/test_compile.py @@ -1021,3 +1021,29 @@ def test_compile_with_conflicting_libraries_include(run_command, data_dir, copy_ assert 'Multiple libraries were found for "OneWire.h"' in lines assert f"Used: {one_wire_lib_path}" in lines assert f"Not used: {one_wire_ng_lib_path}" in lines + + +def test_compile_with_invalid_build_options_json(run_command, data_dir): + assert run_command("update") + + assert run_command("core install arduino:avr@1.8.3") + + sketch_name = "CompileInvalidBuildOptionsJson" + sketch_path = Path(data_dir, sketch_name) + fqbn = "arduino:avr:uno" + + # Create a test sketch + assert run_command(f"sketch new {sketch_path}") + + # Get the build directory + sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper() + build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}") + + assert run_command(f"compile -b {fqbn} {sketch_path} --verbose") + + # Breaks the build.options.json file + build_options_json = build_dir / "build.options.json" + with open(build_options_json, "w") as f: + f.write("invalid json") + + assert run_command(f"compile -b {fqbn} {sketch_path} --verbose")