mirror of
https://github.com/wled/WLED.git
synced 2025-04-19 12:27:17 +00:00
116 lines
4.2 KiB
Python
116 lines
4.2 KiB
Python
Import('env')
|
|
import os.path
|
|
from collections import deque
|
|
from pathlib import Path # For OS-agnostic path manipulation
|
|
from platformio.package.manager.library import LibraryPackageManager
|
|
|
|
usermod_dir = Path(env["PROJECT_DIR"]) / "usermods"
|
|
all_usermods = [f for f in usermod_dir.iterdir() if f.is_dir() and f.joinpath('library.json').exists()]
|
|
|
|
if env['PIOENV'] == "usermods":
|
|
# Add all usermods
|
|
env.GetProjectConfig().set(f"env:usermods", 'custom_usermods', " ".join([f.name for f in all_usermods]))
|
|
|
|
def find_usermod(mod: str):
|
|
"""Locate this library in the usermods folder.
|
|
We do this to avoid needing to rename a bunch of folders;
|
|
this could be removed later
|
|
"""
|
|
# Check name match
|
|
mp = usermod_dir / mod
|
|
if mp.exists():
|
|
return mp
|
|
mp = usermod_dir / f"{mod}_v2"
|
|
if mp.exists():
|
|
return mp
|
|
mp = usermod_dir / f"usermod_v2_{mod}"
|
|
if mp.exists():
|
|
return mp
|
|
raise RuntimeError(f"Couldn't locate module {mod} in usermods directory!")
|
|
|
|
usermods = env.GetProjectOption("custom_usermods","")
|
|
if usermods:
|
|
# Inject usermods in to project lib_deps
|
|
proj = env.GetProjectConfig()
|
|
deps = env.GetProjectOption('lib_deps')
|
|
src_dir = proj.get("platformio", "src_dir")
|
|
src_dir = src_dir.replace('\\','/')
|
|
mod_paths = {mod: find_usermod(mod) for mod in usermods.split()}
|
|
usermods = [f"{mod} = symlink://{path}" for mod, path in mod_paths.items()]
|
|
proj.set("env:" + env['PIOENV'], 'lib_deps', deps + usermods)
|
|
# Force usermods to be installed in to the environment build state before the LDF runs
|
|
# Otherwise we won't be able to see them until it's too late to change their paths for LDF
|
|
# Logic is largely borrowed from PlaformIO internals
|
|
not_found_specs = []
|
|
for spec in usermods:
|
|
found = False
|
|
for storage_dir in env.GetLibSourceDirs():
|
|
#print(f"Checking {storage_dir} for {spec}")
|
|
lm = LibraryPackageManager(storage_dir)
|
|
if lm.get_package(spec):
|
|
#print("Found!")
|
|
found = True
|
|
break
|
|
if not found:
|
|
#print("Missing!")
|
|
not_found_specs.append(spec)
|
|
if not_found_specs:
|
|
lm = LibraryPackageManager(
|
|
env.subst(os.path.join("$PROJECT_LIBDEPS_DIR", "$PIOENV"))
|
|
)
|
|
for spec in not_found_specs:
|
|
#print(f"LU: forcing install of {spec}")
|
|
lm.install(spec)
|
|
|
|
|
|
# Utility function for assembling usermod include paths
|
|
def cached_add_includes(dep, dep_cache: set, includes: deque):
|
|
""" Add dep's include paths to includes if it's not in the cache """
|
|
if dep not in dep_cache:
|
|
dep_cache.add(dep)
|
|
for include in dep.get_include_dirs():
|
|
if include not in includes:
|
|
includes.appendleft(include)
|
|
if usermod_dir not in Path(dep.src_dir).parents:
|
|
# Recurse, but only for NON-usermods
|
|
for subdep in dep.depbuilders:
|
|
cached_add_includes(subdep, dep_cache, includes)
|
|
|
|
# Monkey-patch ConfigureProjectLibBuilder to mark up the dependencies
|
|
# Save the old value
|
|
old_ConfigureProjectLibBuilder = env.ConfigureProjectLibBuilder
|
|
|
|
# Our new wrapper
|
|
def wrapped_ConfigureProjectLibBuilder(xenv):
|
|
# Update usermod properties
|
|
# Set libArchive before build actions are added
|
|
for um in (um for um in xenv.GetLibBuilders() if usermod_dir in Path(um.src_dir).parents):
|
|
build = um._manifest.get("build", {})
|
|
build["libArchive"] = False
|
|
um._manifest["build"] = build
|
|
|
|
# Call the wrapped function
|
|
result = old_ConfigureProjectLibBuilder.clone(xenv)()
|
|
|
|
# Fix up include paths
|
|
# In PlatformIO >=6.1.17, this could be done prior to ConfigureProjectLibBuilder
|
|
wled_dir = xenv["PROJECT_SRC_DIR"]
|
|
# Build a list of dependency include dirs
|
|
# TODO: Find out if this is the order that PlatformIO/SCons puts them in??
|
|
processed_deps = set()
|
|
extra_include_dirs = deque() # Deque used for fast prepend
|
|
for dep in result.depbuilders:
|
|
cached_add_includes(dep, processed_deps, extra_include_dirs)
|
|
|
|
for um in [dep for dep in result.depbuilders if usermod_dir in Path(dep.src_dir).parents]:
|
|
# Add the wled folder to the include path
|
|
um.env.PrependUnique(CPPPATH=wled_dir)
|
|
# Add WLED's own dependencies
|
|
for dir in extra_include_dirs:
|
|
um.env.PrependUnique(CPPPATH=dir)
|
|
|
|
return result
|
|
|
|
# Apply the wrapper
|
|
env.AddMethod(wrapped_ConfigureProjectLibBuilder, "ConfigureProjectLibBuilder")
|