Update support for ESP-IDF v4.1

This commit is contained in:
valeros
2020-09-01 21:26:55 +03:00
parent 78be15e0d1
commit ff997d3677
4 changed files with 280 additions and 178 deletions
+261 -168
View File
@@ -24,53 +24,52 @@ import copy
import json
import subprocess
import sys
from os import environ, listdir, makedirs, rename, pathsep
from os.path import (
abspath,
basename,
dirname,
getmtime,
isabs,
isdir,
isfile,
join,
realpath,
relpath,
)
import os
import click
from SCons.Script import (
ARGUMENTS,
COMMAND_LINE_TARGETS,
AlwaysBuild,
DefaultEnvironment,
)
from platformio.builder.tools.piolib import ProjectAsLibBuilder
from platformio.fs import to_unix_path
from platformio.proc import exec_command, where_is_program
from platformio import fs
from platformio.proc import exec_command
from platformio.util import get_systype
from platformio.builder.tools.piolib import ProjectAsLibBuilder
env = DefaultEnvironment()
platform = env.PioPlatform()
env.SConscript("_embed_files.py", exports="env")
FRAMEWORK_DIR = platform.get_package_dir("framework-espidf")
assert FRAMEWORK_DIR and isdir(FRAMEWORK_DIR)
platform = env.PioPlatform()
board = env.BoardConfig()
mcu = board.get("build.mcu", "esp32")
idf_variant = board.get(
"build.esp-idf.variant", "esp32s2beta" if mcu == "esp32s2" else "esp32"
)
FRAMEWORK_DIR = platform.get_package_dir("framework-espidf")
TOOLCHAIN_DIR = platform.get_package_dir(
"toolchain-xtensa%s" % ("32s2" if mcu == "esp32s2" else "32")
)
assert os.path.isdir(FRAMEWORK_DIR)
# Arduino framework as a component is not compatible with ESP-IDF >=4.1
if "arduino" in env.subst("$PIOFRAMEWORK"):
ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
# Possible package names in 'package@version' format is not compatible with CMake
if "@" in basename(ARDUINO_FRAMEWORK_DIR):
new_path = join(
dirname(ARDUINO_FRAMEWORK_DIR),
basename(ARDUINO_FRAMEWORK_DIR).replace("@", "-"),
if "@" in os.path.basename(ARDUINO_FRAMEWORK_DIR):
new_path = os.path.join(
os.path.dirname(ARDUINO_FRAMEWORK_DIR),
os.path.basename(ARDUINO_FRAMEWORK_DIR).replace("@", "-"),
)
rename(ARDUINO_FRAMEWORK_DIR, new_path)
os.rename(ARDUINO_FRAMEWORK_DIR, new_path)
ARDUINO_FRAMEWORK_DIR = new_path
assert ARDUINO_FRAMEWORK_DIR and isdir(ARDUINO_FRAMEWORK_DIR)
assert ARDUINO_FRAMEWORK_DIR and os.path.isdir(ARDUINO_FRAMEWORK_DIR)
BUILD_DIR = env.subst("$BUILD_DIR")
CMAKE_API_REPLY_PATH = os.path.join(".cmake", "api", "v1", "reply")
try:
import future
@@ -79,23 +78,28 @@ try:
except ImportError:
env.Execute(
env.VerboseAction(
'$PYTHONEXE -m pip install "cryptography>=2.1.4" "future>=0.15.2" "pyparsing>=2.0.3,<2.4.0"',
'$PYTHONEXE -m pip install "cryptography>=2.1.4" "future>=0.15.2" "pyparsing>=2.0.3,<2.4.0" ',
"Installing ESP-IDF's Python dependencies",
)
)
platform = env.PioPlatform()
board = env.BoardConfig()
# a special "esp-windows-curses" python package is required on Windows for Menuconfig
if "windows" in get_systype():
import pkg_resources
FRAMEWORK_DIR = platform.get_package_dir("framework-espidf")
assert isdir(FRAMEWORK_DIR)
BUILD_DIR = env.subst("$BUILD_DIR")
CMAKE_API_REPLY_PATH = join(".cmake", "api", "v1", "reply")
if "esp-windows-curses" not in {pkg.key for pkg in pkg_resources.working_set}:
env.Execute(
env.VerboseAction(
'$PYTHONEXE -m pip install "file://%s/tools/kconfig_new/esp-windows-curses"'
% FRAMEWORK_DIR,
"Installing windows-curses package",
)
)
def get_project_lib_includes(env):
project = ProjectAsLibBuilder(env, "$PROJECT_DIR")
project.install_dependencies()
project.search_deps_recursive()
paths = []
@@ -111,25 +115,27 @@ def get_project_lib_includes(env):
def is_cmake_reconfigure_required(cmake_api_reply_dir):
cmake_cache_file = join(BUILD_DIR, "CMakeCache.txt")
cmake_cache_file = os.path.join(BUILD_DIR, "CMakeCache.txt")
cmake_txt_files = [
join(env.subst("$PROJECT_DIR"), "CMakeLists.txt"),
join(env.subst("$PROJECT_SRC_DIR"), "CMakeLists.txt")
os.path.join(env.subst("$PROJECT_DIR"), "CMakeLists.txt"),
os.path.join(env.subst("$PROJECT_SRC_DIR"), "CMakeLists.txt"),
]
cmake_preconf_dir = join(BUILD_DIR, "config")
sdkconfig = join(env.subst("$PROJECT_DIR"), "sdkconfig")
cmake_preconf_dir = os.path.join(BUILD_DIR, "config")
sdkconfig = os.path.join(env.subst("$PROJECT_DIR"), "sdkconfig")
for d in (cmake_api_reply_dir, cmake_preconf_dir):
if not isdir(d) or not listdir(d):
if not os.path.isdir(d) or not os.listdir(d):
return True
if not isfile(cmake_cache_file):
if not os.path.isfile(cmake_cache_file):
return True
if not isfile(join(BUILD_DIR, "build.ninja")):
if not os.path.isfile(os.path.join(BUILD_DIR, "build.ninja")):
return True
if isfile(sdkconfig) and getmtime(sdkconfig) > getmtime(cmake_cache_file):
if os.path.isfile(sdkconfig) and os.path.getmtime(sdkconfig) > os.path.getmtime(
cmake_cache_file
):
return True
if any(
getmtime(f) > getmtime(cmake_cache_file)
os.path.getmtime(f) > os.path.getmtime(cmake_cache_file)
for f in cmake_txt_files + [cmake_preconf_dir]
):
return True
@@ -139,10 +145,10 @@ def is_cmake_reconfigure_required(cmake_api_reply_dir):
def is_proper_idf_project():
return all(
isfile(path)
os.path.isfile(path)
for path in (
join(env.subst("$PROJECT_DIR"), "CMakeLists.txt"),
join(env.subst("$PROJECT_SRC_DIR"), "CMakeLists.txt"),
os.path.join(env.subst("$PROJECT_DIR"), "CMakeLists.txt"),
os.path.join(env.subst("$PROJECT_SRC_DIR"), "CMakeLists.txt"),
)
)
@@ -159,7 +165,7 @@ def normalize_path(path):
project_dir = env.subst("$PROJECT_DIR")
if project_dir in path:
path = path.replace(project_dir, "${CMAKE_SOURCE_DIR}")
return to_unix_path(path)
return fs.to_unix_path(path)
def create_default_project_files():
@@ -175,33 +181,30 @@ FILE(GLOB_RECURSE app_sources %s/*.*)
idf_component_register(SRCS ${app_sources})
"""
if not listdir(join(env.subst("$PROJECT_SRC_DIR"))):
if not os.listdir(os.path.join(env.subst("$PROJECT_SRC_DIR"))):
# create a default main file to make CMake happy during first init
with open(join(env.subst("$PROJECT_SRC_DIR"), "main.c"), "w") as fp:
with open(os.path.join(env.subst("$PROJECT_SRC_DIR"), "main.c"), "w") as fp:
fp.write("void app_main() {}")
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))
if not os.path.isfile(os.path.join(project_dir, "CMakeLists.txt")):
with open(os.path.join(project_dir, "CMakeLists.txt"), "w") as fp:
fp.write(root_cmake_tpl % os.path.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
% normalize_path(env.subst("$PROJECT_SRC_DIR"))
)
if not os.path.isfile(os.path.join(project_src_dir, "CMakeLists.txt")):
with open(os.path.join(project_src_dir, "CMakeLists.txt"), "w") as fp:
fp.write(prj_cmake_tpl % normalize_path(env.subst("$PROJECT_SRC_DIR")))
def get_cmake_code_model(src_dir, build_dir, extra_args=None):
cmake_api_dir = join(build_dir, ".cmake", "api", "v1")
cmake_api_query_dir = join(cmake_api_dir, "query")
cmake_api_reply_dir = join(cmake_api_dir, "reply")
query_file = join(cmake_api_query_dir, "codemodel-v2")
cmake_api_dir = os.path.join(build_dir, ".cmake", "api", "v1")
cmake_api_query_dir = os.path.join(cmake_api_dir, "query")
cmake_api_reply_dir = os.path.join(cmake_api_dir, "reply")
query_file = os.path.join(cmake_api_query_dir, "codemodel-v2")
if not isfile(query_file):
makedirs(dirname(query_file))
if not os.path.isfile(query_file):
os.makedirs(os.path.dirname(query_file))
open(query_file, "a").close() # create an empty file
if not is_proper_idf_project():
@@ -210,14 +213,14 @@ def get_cmake_code_model(src_dir, build_dir, extra_args=None):
if is_cmake_reconfigure_required(cmake_api_reply_dir):
run_cmake(src_dir, build_dir, extra_args)
if not isdir(cmake_api_reply_dir) or not listdir(cmake_api_reply_dir):
if not os.path.isdir(cmake_api_reply_dir) or not os.listdir(cmake_api_reply_dir):
sys.stderr.write("Error: Couldn't find CMake API response file\n")
env.Exit(1)
codemodel = {}
for target in listdir(cmake_api_reply_dir):
for target in os.listdir(cmake_api_reply_dir):
if target.startswith("codemodel-v2"):
with open(join(cmake_api_reply_dir, target), "r") as fp:
with open(os.path.join(cmake_api_reply_dir, target), "r") as fp:
codemodel = json.load(fp)
assert codemodel["version"]["major"] == 2
@@ -225,26 +228,25 @@ def get_cmake_code_model(src_dir, build_dir, extra_args=None):
def populate_idf_env_vars(idf_env):
idf_env["IDF_PATH"] = platform.get_package_dir("framework-espidf")
idf_env["IDF_PATH"] = FRAMEWORK_DIR
additional_packages = [
join(platform.get_package_dir("toolchain-xtensa32"), "bin"),
join(platform.get_package_dir("toolchain-esp32ulp"), "bin"),
os.path.join(TOOLCHAIN_DIR, "bin"),
os.path.join(platform.get_package_dir("toolchain-%sulp" % mcu), "bin"),
platform.get_package_dir("tool-ninja"),
join(platform.get_package_dir("tool-cmake"), "bin"),
dirname(where_is_program("python")),
os.path.join(platform.get_package_dir("tool-cmake"), "bin"),
os.path.dirname(env.subst("$PYTHONEXE")),
]
if "windows" in get_systype():
additional_packages.append(platform.get_package_dir("tool-mconf"))
idf_env["PATH"] = pathsep.join(additional_packages + [idf_env["PATH"]])
idf_env["PATH"] = os.pathsep.join(additional_packages + [idf_env["PATH"]])
def get_target_config(project_configs, target_index, cmake_api_reply_dir):
target_json = project_configs.get("targets")[target_index].get("jsonFile", "")
target_config_file = join(cmake_api_reply_dir, target_json)
if not isfile(target_config_file):
target_config_file = os.path.join(cmake_api_reply_dir, target_json)
if not os.path.isfile(target_config_file):
sys.stderr.write("Error: Couldn't find target config %s\n" % target_json)
env.Exit(1)
@@ -269,12 +271,12 @@ def build_library(default_env, lib_config, project_src_dir, prepend_dir=None):
lib_name = lib_config["nameOnDisk"]
lib_path = lib_config["paths"]["build"]
if prepend_dir:
lib_path = join(prepend_dir, lib_path)
lib_path = os.path.join(prepend_dir, lib_path)
lib_objects = compile_source_files(
lib_config, default_env, project_src_dir, prepend_dir
)
return default_env.Library(
target=join("$BUILD_DIR", lib_path, lib_name), source=lib_objects
target=os.path.join("$BUILD_DIR", lib_path, lib_name), source=lib_objects
)
@@ -331,17 +333,17 @@ def extract_link_args(target_config):
elif fragment.startswith("-") and not fragment.startswith("-l"):
# CMake mistakenly marks LINKFLAGS as libraries
link_args["LINKFLAGS"].extend(args)
elif isfile(fragment) and isabs(fragment):
elif os.path.isfile(fragment) and os.path.isabs(fragment):
# In case of precompiled archives from framework package
lib_path = dirname(fragment)
lib_path = os.path.dirname(fragment)
if lib_path not in link_args["LIBPATH"]:
link_args["LIBPATH"].append(dirname(fragment))
link_args["LIBPATH"].append(os.path.dirname(fragment))
link_args["LIBS"].extend(
[basename(l) for l in args if l.endswith(".a")]
[os.path.basename(lib) for lib in args if lib.endswith(".a")]
)
elif fragment.endswith(".a"):
link_args["__LIB_DEPS"].extend(
[basename(l) for l in args if l.endswith(".a")]
[os.path.basename(lib) for lib in args if lib.endswith(".a")]
)
return link_args
@@ -394,8 +396,8 @@ def get_app_flags(app_config, default_config):
def get_sdk_configuration():
config_path = join(env.subst("$BUILD_DIR"), "config", "sdkconfig.json")
if not isfile(config_path):
config_path = os.path.join(BUILD_DIR, "config", "sdkconfig.json")
if not os.path.isfile(config_path):
print('Warning: Could not find "sdkconfig.json" file\n')
try:
@@ -410,38 +412,56 @@ def find_framework_service_files(search_path, sdk_config):
result["lf_files"] = list()
result["kconfig_files"] = list()
result["kconfig_build_files"] = list()
for d in listdir(search_path):
path = join(search_path, d)
if not isdir(path):
for d in os.listdir(search_path):
path = os.path.join(search_path, d)
if not os.path.isdir(path):
continue
for f in listdir(path):
if f == "linker.lf":
result["lf_files"].append(join(path, f))
for f in os.listdir(path):
# Skip hardware specific files as they will be added later
if f == "linker.lf" and not os.path.basename(path).startswith("esp32"):
result["lf_files"].append(os.path.join(path, f))
elif f == "Kconfig.projbuild":
result["kconfig_build_files"].append(join(path, f))
result["kconfig_build_files"].append(os.path.join(path, f))
elif f == "Kconfig":
result["kconfig_files"].append(join(path, f))
result["kconfig_files"].append(os.path.join(path, f))
result["lf_files"].extend([
join(FRAMEWORK_DIR, "components", "esp32", "ld", "esp32_fragments.lf"),
join(FRAMEWORK_DIR, "components", "newlib", "newlib.lf")
])
result["lf_files"].extend(
[
os.path.join(
FRAMEWORK_DIR,
"components",
idf_variant,
"ld",
"%s_fragments.lf" % idf_variant,
),
os.path.join(
FRAMEWORK_DIR,
"components",
idf_variant,
"linker.lf",
),
os.path.join(FRAMEWORK_DIR, "components", "newlib", "newlib.lf"),
]
)
if sdk_config.get("SPIRAM_CACHE_WORKAROUND", False):
result["lf_files"].append(join(
FRAMEWORK_DIR, "components", "newlib", "esp32-spiram-rom-functions-c.lf"))
result["lf_files"].append(
os.path.join(
FRAMEWORK_DIR, "components", "newlib", "esp32-spiram-rom-functions-c.lf"
)
)
return result
def create_custom_libraries_list(ldgen_libraries_file, ignore_targets):
if not isfile(ldgen_libraries_file):
if not os.path.isfile(ldgen_libraries_file):
sys.stderr.write("Error: Couldn't find the list of framework libraries\n")
env.Exit(1)
pio_libraries_file = ldgen_libraries_file + "_pio"
if isfile(pio_libraries_file):
if os.path.isfile(pio_libraries_file):
return pio_libraries_file
lib_paths = []
@@ -462,26 +482,24 @@ def create_custom_libraries_list(ldgen_libraries_file, ignore_targets):
def generate_project_ld_script(sdk_config, ignore_targets=None):
ignore_targets = ignore_targets or []
project_files = find_framework_service_files(
join(FRAMEWORK_DIR, "components"), sdk_config
os.path.join(FRAMEWORK_DIR, "components"), sdk_config
)
# Create a new file to avoid automatically generated library entry as files from
# this library are built internally by PlatformIO
libraries_list = create_custom_libraries_list(
join(env.subst("$BUILD_DIR"), "ldgen_libraries"), ignore_targets
os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets
)
args = {
"script": join(FRAMEWORK_DIR, "tools", "ldgen", "ldgen.py"),
"config": join(env.subst("$PROJECT_DIR"), "sdkconfig"),
"script": os.path.join(FRAMEWORK_DIR, "tools", "ldgen", "ldgen.py"),
"config": os.path.join(env.subst("$PROJECT_DIR"), "sdkconfig"),
"fragments": " ".join(['"%s"' % f for f in project_files.get("lf_files")]),
"kconfig": join(FRAMEWORK_DIR, "Kconfig"),
"env_file": join("$BUILD_DIR", "config.env"),
"kconfig": os.path.join(FRAMEWORK_DIR, "Kconfig"),
"env_file": os.path.join("$BUILD_DIR", "config.env"),
"libraries_list": libraries_list,
"objdump": join(
platform.get_package_dir("toolchain-xtensa32"),
"bin",
env.subst("$CC").replace("-gcc", "-objdump"),
"objdump": os.path.join(
TOOLCHAIN_DIR, "bin", env.subst("$CC").replace("-gcc", "-objdump"),
),
}
@@ -494,8 +512,14 @@ def generate_project_ld_script(sdk_config, ignore_targets=None):
).format(**args)
return env.Command(
join("$BUILD_DIR", "esp32.project.ld"),
join(FRAMEWORK_DIR, "components", "esp32", "ld", "esp32.project.ld.in"),
os.path.join("$BUILD_DIR", "%s.project.ld" % idf_variant),
os.path.join(
FRAMEWORK_DIR,
"components",
idf_variant,
"ld",
"%s.project.ld.in" % idf_variant,
),
env.VerboseAction(cmd, "Generating project linker script $TARGET"),
)
@@ -546,17 +570,21 @@ def compile_source_files(config, default_env, project_src_dir, prepend_dir=None)
compile_group_idx = source.get("compileGroupIndex")
if compile_group_idx is not None:
src_path = source.get("path")
if not isabs(src_path):
if not os.path.isabs(src_path):
# For cases when sources are located near CMakeLists.txt
src_path = join(project_src_dir, src_path)
src_path = os.path.join(project_src_dir, src_path)
local_path = config["paths"]["source"]
if not isabs(local_path):
local_path = join(project_src_dir, config["paths"]["source"])
obj_path = join("$BUILD_DIR", prepend_dir or "", config["paths"]["build"])
if not os.path.isabs(local_path):
local_path = os.path.join(project_src_dir, config["paths"]["source"])
obj_path = os.path.join(
"$BUILD_DIR", prepend_dir or "", config["paths"]["build"]
)
objects.append(
build_envs[compile_group_idx].StaticObject(
target=join(obj_path, relpath(src_path, local_path) + ".o"),
source=realpath(src_path),
target=os.path.join(
obj_path, os.path.relpath(src_path, local_path) + ".o"
),
source=os.path.realpath(src_path),
)
)
@@ -564,7 +592,7 @@ def compile_source_files(config, default_env, project_src_dir, prepend_dir=None)
def run_tool(cmd):
idf_env = environ.copy()
idf_env = os.environ.copy()
populate_idf_env_vars(idf_env)
result = exec_command(cmd, env=idf_env)
@@ -579,14 +607,14 @@ def run_tool(cmd):
def RunMenuconfig(target, source, env):
idf_env = environ.copy()
idf_env = os.environ.copy()
populate_idf_env_vars(idf_env)
rc = subprocess.call(
[
join(platform.get_package_dir("tool-cmake"), "bin", "cmake"),
os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"),
"--build",
env.subst("$BUILD_DIR"),
BUILD_DIR,
"--target",
"menuconfig",
],
@@ -598,9 +626,29 @@ def RunMenuconfig(target, source, env):
env.Exit(1)
def ReconfigureProject(target, source, env):
idf_env = os.environ.copy()
populate_idf_env_vars(idf_env)
rc = subprocess.call(
[
os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"),
"--build",
BUILD_DIR,
"--target",
"reconfigure",
],
env=idf_env,
)
if rc != 0:
sys.stderr.write("Error: Couldn't execute 'reconfigure' target.\n")
env.Exit(1)
def run_cmake(src_dir, build_dir, extra_args=None):
cmd = [
join(platform.get_package_dir("tool-cmake") or "", "bin", "cmake"),
os.path.join(platform.get_package_dir("tool-cmake") or "", "bin", "cmake"),
"-S",
src_dir,
"-B",
@@ -642,16 +690,21 @@ def find_lib_deps(components_map, elf_config, link_args, ignore_components=None)
def build_bootloader():
bootloader_src_dir = join(FRAMEWORK_DIR, "components", "bootloader", "subproject")
bootloader_src_dir = os.path.join(
FRAMEWORK_DIR, "components", "bootloader", "subproject"
)
code_model = get_cmake_code_model(
bootloader_src_dir,
join(BUILD_DIR, "bootloader"),
os.path.join(BUILD_DIR, "bootloader"),
[
"-DIDF_TARGET=esp32",
"-DIDF_TARGET=" + idf_variant,
"-DPYTHON_DEPS_CHECKED=1",
"-DIDF_PATH=" + platform.get_package_dir("framework-espidf"),
"-DSDKCONFIG=" + join(env.subst("$PROJECT_DIR"), "sdkconfig"),
"-DEXTRA_COMPONENT_DIRS=" + join(FRAMEWORK_DIR, "components", "bootloader"),
"-DPYTHON=" + env.subst("$PYTHONEXE"),
"-DIDF_PATH=" + FRAMEWORK_DIR,
"-DSDKCONFIG=" + os.path.join(env.subst("$PROJECT_DIR"), "sdkconfig"),
"-DLEGACY_INCLUDE_COMMON_HEADERS=",
"-DEXTRA_COMPONENT_DIRS="
+ os.path.join(FRAMEWORK_DIR, "components", "bootloader"),
],
)
@@ -660,7 +713,8 @@ def build_bootloader():
env.Exit(1)
target_configs = load_target_configurations(
code_model, join(BUILD_DIR, "bootloader", CMAKE_API_REPLY_PATH)
code_model,
os.path.join(BUILD_DIR, "bootloader", ".cmake", "api", "v1", "reply"),
)
elf_config = get_project_elf(target_configs)
@@ -692,8 +746,10 @@ def build_bootloader():
)
return bootloader_env.ElfToBin(
join("$BUILD_DIR", "bootloader"),
bootloader_env.Program(join("$BUILD_DIR", "bootloader.elf"), bootloader_libs),
os.path.join("$BUILD_DIR", "bootloader"),
bootloader_env.Program(
os.path.join("$BUILD_DIR", "bootloader.elf"), bootloader_libs
),
)
@@ -743,17 +799,17 @@ def generate_default_component():
file(GLOB component_sources *.c* *.S)
idf_component_register(SRCS ${component_sources})
"""
dummy_component_path = join(BUILD_DIR, "__pio_env")
if not isdir(dummy_component_path):
makedirs(dummy_component_path)
dummy_component_path = os.path.join(BUILD_DIR, "__pio_env")
if not os.path.isdir(dummy_component_path):
os.makedirs(dummy_component_path)
for ext in (".cpp", ".c", ".S"):
dummy_file = join(dummy_component_path, "__dummy" + ext)
if not isfile(dummy_file):
dummy_file = os.path.join(dummy_component_path, "__dummy" + ext)
if not os.path.isfile(dummy_file):
open(dummy_file, "a").close()
component_cmake = join(dummy_component_path, "CMakeLists.txt")
if not isfile(component_cmake):
component_cmake = os.path.join(dummy_component_path, "CMakeLists.txt")
if not os.path.isfile(component_cmake):
with open(component_cmake, "w") as fp:
fp.write(prj_cmake_tpl)
@@ -767,16 +823,32 @@ def find_default_component(target_configs):
return ""
def create_verion_file():
version_file = os.path.join(FRAMEWORK_DIR, "version.txt")
if not os.path.isfile(version_file):
with open(version_file, "w") as fp:
fp.write(platform.get_package_version("framework-espidf"))
#
# ESP-IDF package doesn't contain .git folder, instead package version is specified
# in a special file "version.h" in the root folder of the package
#
create_verion_file()
#
# Generate final linker script
#
if not board.get("build.ldscript", ""):
linker_script = env.Command(
join("$BUILD_DIR", "esp32_out.ld"),
os.path.join("$BUILD_DIR", "%s_out.ld" % idf_variant),
board.get(
"build.esp-idf.ldscript",
join(FRAMEWORK_DIR, "components", "esp32", "ld", "esp32.ld"),
os.path.join(
FRAMEWORK_DIR, "components", idf_variant, "ld", "%s.ld" % idf_variant
),
),
env.VerboseAction(
'$CC -I"$BUILD_DIR/config" -C -P -x c -E $SOURCE -o $TARGET',
@@ -785,29 +857,31 @@ if not board.get("build.ldscript", ""):
)
env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", linker_script)
env.Replace(LDSCRIPT_PATH="esp32_out.ld")
env.Replace(LDSCRIPT_PATH="%s_out.ld" % idf_variant)
#
# Generate partition table
#
fwpartitions_dir = join(FRAMEWORK_DIR, "components", "partition_table")
fwpartitions_dir = os.path.join(FRAMEWORK_DIR, "components", "partition_table")
partitions_csv = board.get("build.partitions", "partitions_singleapp.csv")
env.Replace(
PARTITIONS_TABLE_CSV=abspath(
join(fwpartitions_dir, partitions_csv)
if isfile(join(fwpartitions_dir, partitions_csv))
PARTITIONS_TABLE_CSV=os.path.abspath(
os.path.join(fwpartitions_dir, partitions_csv)
if os.path.isfile(os.path.join(fwpartitions_dir, partitions_csv))
else partitions_csv
)
)
partition_table = env.Command(
join("$BUILD_DIR", "partitions.bin"),
os.path.join("$BUILD_DIR", "partitions.bin"),
"$PARTITIONS_TABLE_CSV",
env.VerboseAction(
'"$PYTHONEXE" "%s" -q --flash-size "%s" $SOURCE $TARGET'
% (
join(FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py"),
os.path.join(
FRAMEWORK_DIR, "components", "partition_table", "gen_esp32part.py"
),
board.get("upload.flash_size", "4MB"),
),
"Generating partitions $TARGET",
@@ -833,7 +907,7 @@ if env.subst("$SRC_FILTER"):
)
)
if isfile(join(env.subst("$PROJECT_SRC_DIR"), "sdkconfig.h")):
if os.path.isfile(os.path.join(env.subst("$PROJECT_SRC_DIR"), "sdkconfig.h")):
print(
"Warning! Starting with ESP-IDF v4.0, new project structure is required: \n"
"https://docs.platformio.org/en/latest/frameworks/espidf.html#project-structure"
@@ -847,7 +921,7 @@ if isfile(join(env.subst("$PROJECT_SRC_DIR"), "sdkconfig.h")):
# default 'src' folder we need to add this as an extra component. If there is no 'main'
# folder CMake won't generate dependencies properly
extra_components = [generate_default_component()]
if env.subst("$PROJECT_SRC_DIR") != join(env.subst("$PROJECT_DIR"), "main"):
if env.subst("$PROJECT_SRC_DIR") != os.path.join(env.subst("$PROJECT_DIR"), "main"):
extra_components.append(env.subst("$PROJECT_SRC_DIR"))
if "arduino" in env.subst("$PIOFRAMEWORK"):
extra_components.append(ARDUINO_FRAMEWORK_DIR)
@@ -856,8 +930,11 @@ print("Reading CMake configuration...")
project_codemodel = get_cmake_code_model(
env.subst("$PROJECT_DIR"),
BUILD_DIR,
["-DEXTRA_COMPONENT_DIRS:PATH=" + ";".join(extra_components)] +
click.parser.split_arg_string(board.get("build.cmake_extra_args", ""))
[
"-DIDF_TARGET=" + idf_variant,
"-DEXTRA_COMPONENT_DIRS:PATH=" + ";".join(extra_components),
]
+ click.parser.split_arg_string(board.get("build.cmake_extra_args", "")),
)
if not project_codemodel:
@@ -865,13 +942,13 @@ if not project_codemodel:
env.Exit(1)
target_configs = load_target_configurations(
project_codemodel, join(BUILD_DIR, CMAKE_API_REPLY_PATH)
project_codemodel, os.path.join(BUILD_DIR, CMAKE_API_REPLY_PATH)
)
sdk_config = get_sdk_configuration()
project_target_name = "__idf_%s" % basename(env.subst("$PROJECT_SRC_DIR"))
project_target_name = "__idf_%s" % os.path.basename(env.subst("$PROJECT_SRC_DIR"))
if project_target_name not in target_configs:
sys.stderr.write("Error: Couldn't find the main target of the project!\n")
env.Exit(1)
@@ -887,7 +964,8 @@ if project_target_name != "__idf_main" and "__idf_main" in target_configs:
env.Exit(1)
project_ld_scipt = generate_project_ld_script(
sdk_config, [project_target_name, "__pio_env"])
sdk_config, [project_target_name, "__pio_env"]
)
env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", project_ld_scipt)
elf_config = get_project_elf(target_configs)
@@ -925,8 +1003,21 @@ env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", build_bootloader())
# Target: ESP-IDF menuconfig
#
env.AddPlatformTarget("menuconfig", None, [env.VerboseAction(
RunMenuconfig, "Running menuconfig...")], "Run Menuconfig")
env.AddPlatformTarget(
"menuconfig",
None,
[env.VerboseAction(RunMenuconfig, "Running menuconfig...")],
"Run Menuconfig",
)
env.AddPlatformTarget(
"reconfigure",
None,
[env.VerboseAction(ReconfigureProject, "Reconfiguring project...")],
"Reconfigure Project",
)
#
# Process main parts of the framework
@@ -943,7 +1034,7 @@ link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_fla
# remove the main linker script flags '-T esp32_out.ld'
try:
ld_index = extra_flags.index("esp32_out.ld")
ld_index = extra_flags.index("%s_out.ld" % idf_variant)
extra_flags.pop(ld_index)
extra_flags.pop(ld_index - 1)
except:
@@ -953,6 +1044,7 @@ except:
# Process project sources
#
# Remove project source files from following build stages as they're
# built as part of the framework
def _skip_prj_source_files(node):
@@ -1002,8 +1094,8 @@ env.Prepend(
LINKFLAGS=extra_flags,
LIBS=libs,
FLASH_EXTRA_IMAGES=[
("0x1000", join("$BUILD_DIR", "bootloader.bin")),
("0x8000", join("$BUILD_DIR", "partitions.bin")),
("0x1000", os.path.join("$BUILD_DIR", "bootloader.bin")),
("0x8000", os.path.join("$BUILD_DIR", "partitions.bin")),
],
)
@@ -1013,13 +1105,14 @@ env.Prepend(
action = copy.deepcopy(env["BUILDERS"]["ElfToBin"].action)
action.cmd_list = env["BUILDERS"]["ElfToBin"].action.cmd_list.replace(
"-o", "--elf-sha256-offset 0xb0 -o")
"-o", "--elf-sha256-offset 0xb0 -o"
)
env["BUILDERS"]["ElfToBin"].action = action
#
# Compile ULP sources in 'ulp' folder
#
ulp_dir = join(env.subst("$PROJECT_DIR"), "ulp")
if isdir(ulp_dir) and listdir(ulp_dir):
env.SConscript("ulp.py", exports="env project_config")
ulp_dir = os.path.join(env.subst("$PROJECT_DIR"), "ulp")
if os.path.isdir(ulp_dir) and os.listdir(ulp_dir):
env.SConscript("ulp.py", exports="env project_config idf_variant")
+4 -5
View File
@@ -13,14 +13,13 @@
# limitations under the License.
import os
import sys
from SCons.Script import COMMAND_LINE_TARGETS, Import, Return
from SCons.Script import Import
from platformio.util import get_systype
from platformio.proc import where_is_program
Import("env project_config")
Import("env project_config idf_variant")
ulp_env = env.Clone()
platform = ulp_env.PioPlatform()
@@ -79,7 +78,7 @@ def generate_ulp_config(target_config):
"components",
"ulp",
"cmake",
"toolchain-ulp.cmake",
"toolchain-%s-ulp.cmake" % idf_variant,
),
'-DULP_S_SOURCES="%s"' % ";".join(ulp_sources),
"-DULP_APP_NAME=ulp_main",
@@ -87,7 +86,7 @@ def generate_ulp_config(target_config):
'-DCOMPONENT_INCLUDES="%s"' % ";".join(get_component_includes(target_config)),
"-DIDF_PATH=" + FRAMEWORK_DIR,
"-DSDKCONFIG=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"),
"-DPYTHON=python",
"-DPYTHON=" + env.subst("$PYTHONEXE"),
"-GNinja",
"-B",
ULP_BUILD_DIR,
+8 -2
View File
@@ -68,7 +68,13 @@
"type": "toolchain",
"optional": true,
"owner": "platformio",
"version": "~1.22851.190618"
"version": "~1.22851.0"
},
"toolchain-esp32s2ulp": {
"type": "toolchain",
"optional": true,
"owner": "platformio",
"version": "~1.22851.0"
},
"framework-arduinoespressif32": {
"type": "framework",
@@ -86,7 +92,7 @@
"type": "framework",
"optional": true,
"owner": "platformio",
"version": "~3.40001.0"
"version": "~3.40100.0"
},
"framework-simba": {
"type": "framework",
+7 -3
View File
@@ -26,25 +26,29 @@ class Espressif32Platform(PlatformBase):
self, variables, targets)
board_config = self.board_config(variables.get("board"))
mcu = variables.get("board_build.mcu", board_config.get(
"build.mcu", "esp32"))
mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32"))
frameworks = variables.get("pioframework", [])
if "buildfs" in targets:
self.packages['tool-mkspiffs']['optional'] = False
if variables.get("upload_protocol"):
self.packages['tool-openocd-esp32']['optional'] = False
if isdir("ulp"):
self.packages['toolchain-esp32ulp']['optional'] = False
if "espidf" in variables.get("pioframework", []):
if "espidf" in frameworks:
for p in self.packages:
if p in ("tool-cmake", "tool-ninja", "toolchain-%sulp" % mcu):
self.packages[p]["optional"] = False
elif p in ("tool-mconf", "tool-idf") and "windows" in get_systype():
self.packages[p]['optional'] = False
self.packages['toolchain-xtensa32']['version'] = "~2.80200.0"
if "arduino" in frameworks:
# Arduino component is not compatible with ESP-IDF >=4.1
self.packages['framework-espidf']['version'] = "~3.40001.0"
# ESP32-S2 toolchain is identical for both Arduino and ESP-IDF
if mcu == "esp32s2":
self.packages.pop("toolchain-xtensa32", None)
self.packages['toolchain-xtensa32s2']['optional'] = False
self.packages['toolchain-esp32s2ulp']['optional'] = False
self.packages['tool-esptoolpy']['version'] = "~1.30000.0"
build_core = variables.get(