def configure_debug_session(self, debug_config): build_extra_data = debug_config.build_data.get("extra", {}) flash_images = build_extra_data.get("flash_images", []) if "openocd" in (debug_config.server or {}).get("executable", ""): debug_config.server["arguments"].extend( ["-c", "adapter_khz %s" % (debug_config.speed or "5000")]) ignore_conds = [ debug_config.load_cmds != ["load"], not flash_images, not all([os.path.isfile(item["path"]) for item in flash_images]), ] if any(ignore_conds): return load_cmds = [ 'monitor program_esp "{{{path}}}" {offset} verify'.format( path=fs.to_unix_path(item["path"]), offset=item["offset"]) for item in flash_images ] load_cmds.append('monitor program_esp "{%s.bin}" %s verify' % ( fs.to_unix_path(debug_config.build_data["prog_path"][:-4]), build_extra_data.get("application_offset", "0x10000"), )) debug_config.load_cmds = load_cmds
def configure_esp32_load_cmds(debug_options, configuration): """ DEPRECATED: Moved to ESP32 dev-platform See platform.py::configure_debug_options """ flash_images = configuration.get("extra", {}).get("flash_images") ignore_conds = [ debug_options["load_cmds"] != ["load"], "xtensa-esp32" not in configuration.get("cc_path", ""), not flash_images, not all([isfile(item["path"]) for item in flash_images]), ] if any(ignore_conds): return debug_options["load_cmds"] mon_cmds = [ 'monitor program_esp32 "{{{path}}}" {offset} verify'.format( path=fs.to_unix_path(item["path"]), offset=item["offset"] ) for item in flash_images ] mon_cmds.append( 'monitor program_esp32 "{%s.bin}" 0x10000 verify' % fs.to_unix_path(configuration["prog_path"][:-4]) ) return mon_cmds
def configure_debug_options(self, initial_debug_options, ide_data): """ Deprecated. Remove method when PlatformIO Core 5.2 is released """ ide_extra_data = ide_data.get("extra", {}) flash_images = ide_extra_data.get("flash_images", []) debug_options = copy.deepcopy(initial_debug_options) if "openocd" in debug_options["server"].get("executable", ""): debug_options["server"]["arguments"].extend([ "-c", "adapter_khz %s" % (initial_debug_options.get("speed") or "5000"), ]) ignore_conds = [ initial_debug_options["load_cmds"] != ["load"], not flash_images, not all([os.path.isfile(item["path"]) for item in flash_images]), ] if any(ignore_conds): return debug_options load_cmds = [ 'monitor program_esp "{{{path}}}" {offset} verify'.format( path=fs.to_unix_path(item["path"]), offset=item["offset"]) for item in flash_images ] load_cmds.append('monitor program_esp "{%s.bin}" %s verify' % ( fs.to_unix_path(ide_data["prog_path"][:-4]), ide_extra_data.get("application_offset", "0x10000"), )) debug_options["load_cmds"] = load_cmds return debug_options
def extract_includes_from_compile_group(compile_group, path_prefix=None): def _normalize_prefix(prefix): prefix = fs.to_unix_path(prefix) if not prefix.endswith("/"): prefix = prefix + "/" return prefix if path_prefix: path_prefix = _normalize_prefix(path_prefix) includes = [] sys_includes = [] prefixed_includes = [] for inc in compile_group.get("includes", []): inc_path = fs.to_unix_path(inc["path"]) if inc.get("isSystem", False): sys_includes.append(inc_path) elif path_prefix and inc_path.startswith(path_prefix): prefixed_includes.append( fs.to_unix_path(os.path.relpath(inc_path, path_prefix))) else: includes.append(inc_path) return { "plain_includes": includes, "sys_includes": sys_includes, "prefixed_includes": prefixed_includes, }
def _load_tplvars(self): tpl_vars = { "config": self.config, "systype": util.get_systype(), "project_name": basename(self.project_dir), "project_dir": self.project_dir, "env_name": self.env_name, "user_home_dir": realpath(fs.expanduser("~")), "platformio_path": sys.argv[0] if isfile(sys.argv[0]) else where_is_program("platformio"), "env_path": os.getenv("PATH"), "env_pathsep": os.pathsep, } # default env configuration tpl_vars.update(self.config.items(env=self.env_name, as_dict=True)) # build data tpl_vars.update( load_project_ide_data(self.project_dir, self.env_name) or {}) with fs.cd(self.project_dir): tpl_vars.update({ "src_files": self.get_src_files(), "project_src_dir": self.config.get_optional_dir("src"), "project_lib_dir": self.config.get_optional_dir("lib"), "project_libdeps_dir": join(self.config.get_optional_dir("libdeps"), self.env_name), }) for key, value in tpl_vars.items(): if key.endswith(("_path", "_dir")): tpl_vars[key] = fs.to_unix_path(value) for key in ("src_files", "libsource_dirs"): if key not in tpl_vars: continue tpl_vars[key] = [fs.to_unix_path(inc) for inc in tpl_vars[key]] tpl_vars["to_unix_path"] = fs.to_unix_path tpl_vars["filter_includes"] = self.filter_includes return tpl_vars
def generate_ulp_config(target_config): riscv_ulp_enabled = sdk_config.get("ESP32S2_ULP_COPROC_RISCV", False) ulp_sources = collect_ulp_sources() cmd = ( os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), "-DCMAKE_GENERATOR=Ninja", "-DCMAKE_TOOLCHAIN_FILE=" + os.path.join( FRAMEWORK_DIR, "components", "ulp", "cmake", "toolchain-%s-ulp%s.cmake" % (idf_variant, "-riscv" if riscv_ulp_enabled else ""), ), '-DULP_S_SOURCES="%s"' % ";".join(ulp_sources), "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), '-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)), "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), "-DULP_COCPU_IS_RISCV=%s" % ("ON" if riscv_ulp_enabled else "OFF"), "-GNinja", "-B", ULP_BUILD_DIR, os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake"), ) return ulp_env.Command( os.path.join(ULP_BUILD_DIR, "build.ninja"), ulp_sources, ulp_env.VerboseAction(" ".join(cmd), "Generating ULP configuration"), )
def apply_patterns(self, source, patterns=None): _patterns = self.COMMON_PATTERNS.copy() _patterns.update(patterns or {}) for key, value in _patterns.items(): if key.endswith(("_DIR", "_PATH")): _patterns[key] = fs.to_unix_path(value) def _replace(text): for key, value in _patterns.items(): pattern = "$%s" % key text = text.replace(pattern, value or "") return text if isinstance(source, string_types): source = _replace(source) elif isinstance(source, (list, dict)): items = enumerate(source) if isinstance(source, list) else source.items() for key, value in items: if isinstance(value, string_types): source[key] = _replace(value) elif isinstance(value, (list, dict)): source[key] = self.apply_patterns(value, patterns) return source
def create_default_project_files(): root_cmake_tpl = """cmake_minimum_required(VERSION 3.16.0) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(%s) """ prj_cmake_tpl = """# Warning! This code was automatically generated for projects # without default 'CMakeLists.txt' file. set(app_sources %s) idf_component_register(SRCS ${app_sources}) """ if not listdir(join(env.subst("$PROJECT_SRC_DIR"))): # create an empty file to make CMake happy during first init open(join(env.subst("$PROJECT_SRC_DIR"), "empty.c"), "a").close() project_dir = env.subst("$PROJECT_DIR") if not isfile(join(project_dir, "CMakeLists.txt")): with open(join(project_dir, "CMakeLists.txt"), "w") as fp: fp.write(root_cmake_tpl % basename(project_dir)) project_src_dir = env.subst("$PROJECT_SRC_DIR") if not isfile(join(project_src_dir, "CMakeLists.txt")): with open(join(project_src_dir, "CMakeLists.txt"), "w") as fp: fp.write(prj_cmake_tpl % "".join('\t"%s"\n' % to_unix_path(f) for f in collect_src_files()))
def configure_esp32_load_cmds(debug_options, configuration): ignore_conds = [ debug_options['load_cmds'] != ["load"], "xtensa-esp32" not in configuration.get("cc_path", ""), not configuration.get("flash_extra_images"), not all([ isfile(item['path']) for item in configuration.get("flash_extra_images") ]) ] if any(ignore_conds): return debug_options['load_cmds'] mon_cmds = [ 'monitor program_esp32 "{{{path}}}" {offset} verify'.format( path=fs.to_unix_path(item['path']), offset=item['offset']) for item in configuration.get("flash_extra_images") ] mon_cmds.append('monitor program_esp32 "{%s.bin}" 0x10000 verify' % fs.to_unix_path(configuration['prog_path'][:-4])) return mon_cmds
def build_bootloader(): bootloader_src_dir = join(FRAMEWORK_DIR, "components", "bootloader", "subproject") code_model = get_cmake_code_model( bootloader_src_dir, join(BUILD_DIR, "bootloader"), [ "-DIDF_TARGET=esp8266", "-DPYTHON_DEPS_CHECKED=1", "-DIDF_PATH=" + env.subst("$FRAMEWORK_DIR"), #platform.get_package_dir("framework-espidf"), "-DSDKCONFIG=" + to_unix_path(join(env.subst("$PROJECT_DIR"), "sdkconfig")), "-DEXTRA_COMPONENT_DIRS=" + join("$FRAMEWORK_DIR", "components", "bootloader"), ], ) if not code_model: sys.stderr.write("Error: Couldn't find code model for bootloader\n") env.Exit(1) target_configs = load_target_configurations( code_model, join(BUILD_DIR, "bootloader", CMAKE_API_REPLY_PATH) ) elf_config = get_project_elf(target_configs) if not elf_config: sys.stderr.write( "Error: Couldn't load the main firmware target of the project\n" ) env.Exit(1) bootloader_env = env.Clone() components_map = get_components_map( target_configs, ["STATIC_LIBRARY", "OBJECT_LIBRARY"] ) build_components(bootloader_env, components_map, bootloader_src_dir, "bootloader") link_args = extract_link_args(elf_config) extra_flags = filter_args(link_args["LINKFLAGS"], ["-T", "-u"]) link_args["LINKFLAGS"] = sorted( list(set(link_args["LINKFLAGS"]) - set(extra_flags)) ) bootloader_env.MergeFlags(link_args) bootloader_env.Append(LINKFLAGS=extra_flags) bootloader_libs = find_lib_deps(components_map, elf_config, link_args) bootloader_env.Prepend(__RPATH="-Wl,--start-group ") bootloader_env.Append( CPPDEFINES=["__BOOTLOADER_BUILD"], _LIBDIRFLAGS=" -Wl,--end-group" ) return bootloader_env.ElfToBin( join("$BUILD_DIR", "bootloader"), bootloader_env.Program(join("$BUILD_DIR", "bootloader.elf"), bootloader_libs), )
def filter_includes(includes_map, ignore_scopes=None, to_unix_path=True): ignore_scopes = ignore_scopes or [] result = [] for scope, includes in includes_map.items(): if scope in ignore_scopes: continue for include in includes: if to_unix_path: include = fs.to_unix_path(include) if include not in result: result.append(include) return result
def configure_debug_options(self, initial_debug_options, ide_data): ide_extra_data = ide_data.get("extra", {}) flash_images = ide_extra_data.get("flash_images", []) ignore_conds = [ initial_debug_options["load_cmds"] != ["load"], not flash_images, not all([os.path.isfile(item["path"]) for item in flash_images]), ] if any(ignore_conds): return initial_debug_options debug_options = copy.deepcopy(initial_debug_options) load_cmds = [ 'monitor program_esp "{{{path}}}" {offset} verify'.format( path=fs.to_unix_path(item["path"]), offset=item["offset"]) for item in flash_images ] load_cmds.append('monitor program_esp "{%s.bin}" %s verify' % ( fs.to_unix_path(ide_data["prog_path"][:-4]), ide_extra_data.get("application_offset", "0x10000"), )) debug_options["load_cmds"] = load_cmds return debug_options
def prepare_build_envs(config, default_env): build_envs = [] target_compile_groups = config.get("compileGroups", []) is_build_type_debug = ( set(["debug", "sizedata"]) & set(COMMAND_LINE_TARGETS) or default_env.GetProjectOption("build_type") == "debug") for cg in target_compile_groups: includes = extract_includes_from_compile_group( cg, path_prefix=FRAMEWORK_DIR) defines = extract_defines_from_compile_group(cg) build_env = default_env.Clone() compile_commands = cg.get("compileCommandFragments", []) i = 0 length = len(compile_commands) while i < length: build_flags = compile_commands[i].get("fragment", "") if build_flags.strip() in ("-imacros", "-include"): i += 1 file_path = compile_commands[i].get("fragment", "") build_env.Append(CCFLAGS=[build_flags + file_path]) elif build_flags.strip() and not build_flags.startswith("-D"): build_env.AppendUnique(**build_env.ParseFlags(build_flags)) i += 1 build_env.AppendUnique(CPPDEFINES=defines, CPPPATH=includes["plain_includes"]) if includes["prefixed_includes"]: build_env.Append( CCFLAGS=["-iprefix", fs.to_unix_path(FRAMEWORK_DIR)]) build_env.Append(CCFLAGS=[ "-iwithprefixbefore/" + inc for inc in includes["prefixed_includes"] ]) if includes["sys_includes"]: build_env.Append( CCFLAGS=["-isystem" + inc for inc in includes["sys_includes"]]) build_env.Append(ASFLAGS=build_env.get("CCFLAGS", [])[:]) build_env.ProcessUnFlags(default_env.get("BUILD_UNFLAGS")) if is_build_type_debug: build_env.ConfigureDebugFlags() build_envs.append(build_env) return build_envs
def compile_source_files(config, default_env, project_src_dir, prepend_dir=None): build_envs = prepare_build_envs(config, default_env) objects = [] components_dir = fs.to_unix_path(os.path.join(FRAMEWORK_DIR, "components")) for source in config.get("sources", []): if source["path"].endswith(".rule"): continue compile_group_idx = source.get("compileGroupIndex") if compile_group_idx is not None: src_dir = config["paths"]["source"] if not os.path.isabs(src_dir): src_dir = os.path.join(project_src_dir, config["paths"]["source"]) src_path = source.get("path") if not os.path.isabs(src_path): # For cases when sources are located near CMakeLists.txt src_path = os.path.join(project_src_dir, src_path) obj_path = os.path.join("$BUILD_DIR", prepend_dir or "") if src_path.startswith(components_dir): obj_path = os.path.join( obj_path, os.path.relpath(src_path, components_dir)) else: if not os.path.isabs(source["path"]): obj_path = os.path.join(obj_path, source["path"]) else: obj_path = os.path.join(obj_path, os.path.basename(src_path)) objects.append(build_envs[compile_group_idx].StaticObject( target=os.path.splitext(obj_path)[0] + ".o", source=os.path.realpath(src_path), )) return objects
def test_check_skip_includes_from_packages(clirunner, validate_cliresult, tmpdir): config = """ [env:test] platform = nordicnrf52 board = nrf52_dk framework = arduino """ tmpdir.join("platformio.ini").write(config) tmpdir.mkdir("src").join("main.c").write(TEST_CODE) result = clirunner.invoke( cmd_check, ["--project-dir", str(tmpdir), "--skip-packages", "-v"] ) validate_cliresult(result) project_path = fs.to_unix_path(str(tmpdir)) for l in result.output.split("\n"): if not l.startswith("Includes:"): continue for inc in l.split(" "): if inc.startswith("-I") and project_path not in inc: pytest.fail("Detected an include path from packages: " + inc)
def normalize_path(path): project_dir = env.subst("$PROJECT_DIR") if project_dir in path: path = path.replace(project_dir, "${CMAKE_SOURCE_DIR}") return fs.to_unix_path(path)
def spawn(self, patterns): # pylint: disable=too-many-branches systype = util.get_systype() server = self.debug_options.get("server") if not server: return None server = self.apply_patterns(server, patterns) server_executable = server['executable'] if not server_executable: return None if server['cwd']: server_executable = join(server['cwd'], server_executable) if ("windows" in systype and not server_executable.endswith(".exe") and isfile(server_executable + ".exe")): server_executable = server_executable + ".exe" if not isfile(server_executable): server_executable = where_is_program(server_executable) if not isfile(server_executable): raise exception.DebugInvalidOptions( "\nCould not launch Debug Server '%s'. Please check that it " "is installed and is included in a system PATH\n\n" "See documentation or contact [email protected]:\n" "http://docs.platformio.org/page/plus/debugging.html\n" % server_executable) self._debug_port = ":3333" openocd_pipe_allowed = all([ not self.debug_options['port'], "openocd" in server_executable ]) # yapf: disable if openocd_pipe_allowed: args = [] if server['cwd']: args.extend(["-s", server['cwd']]) args.extend([ "-c", "gdb_port pipe; tcl_port disabled; telnet_port disabled" ]) args.extend(server['arguments']) str_args = " ".join( [arg if arg.startswith("-") else '"%s"' % arg for arg in args]) self._debug_port = '| "%s" %s' % (server_executable, str_args) self._debug_port = fs.to_unix_path(self._debug_port) else: env = os.environ.copy() # prepend server "lib" folder to LD path if ("windows" not in systype and server['cwd'] and isdir(join(server['cwd'], "lib"))): ld_key = ("DYLD_LIBRARY_PATH" if "darwin" in systype else "LD_LIBRARY_PATH") env[ld_key] = join(server['cwd'], "lib") if os.environ.get(ld_key): env[ld_key] = "%s:%s" % (env[ld_key], os.environ.get(ld_key)) # prepend BIN to PATH if server['cwd'] and isdir(join(server['cwd'], "bin")): env['PATH'] = "%s%s%s" % ( join(server['cwd'], "bin"), os.pathsep, os.environ.get("PATH", os.environ.get("Path", ""))) self._transport = reactor.spawnProcess( self, server_executable, [server_executable] + server['arguments'], path=server['cwd'], env=env) if "mspdebug" in server_executable.lower(): self._debug_port = ":2000" elif "jlink" in server_executable.lower(): self._debug_port = ":2331" elif "qemu" in server_executable.lower(): self._debug_port = ":1234" return self._transport
def normalize_path(path): if PROJECT_DIR in path: path = path.replace(PROJECT_DIR, "${CMAKE_SOURCE_DIR}") return fs.to_unix_path(path)
def collect_ulp_sources(): return [ fs.to_unix_path(os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp", f)) for f in os.listdir(os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp")) if f.endswith((".c", ".S", ".s")) ]
def _normalize_prefix(prefix): prefix = fs.to_unix_path(prefix) if not prefix.endswith("/"): prefix = prefix + "/" return prefix
def long_incflags_hook(incflags): return '@"%s"' % _file_long_data( env, "\n".join(fs.to_unix_path(f) if WINDOWS else f for f in incflags) )
def _long_includes_hook(self, includes): data = [] for inc in includes: data.append('-I"%s"' % fs.to_unix_path(inc)) return '@"%s"' % self._create_tmp_file(" ".join(data))