From 47edfdb043b52f1b6555fada83c5aa4403ee2beb Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 2 Aug 2014 20:47:05 +0300 Subject: [PATCH] Improve nested lookup for libraries --- platformio/builder/scripts/atmelavr.py | 4 +- platformio/builder/scripts/timsp430.py | 4 +- platformio/builder/scripts/titiva.py | 4 +- platformio/builder/tools/platformio.py | 99 +++++++++++++++----------- 4 files changed, 63 insertions(+), 48 deletions(-) diff --git a/platformio/builder/scripts/atmelavr.py b/platformio/builder/scripts/atmelavr.py index 65d1ce41..6fc34534 100644 --- a/platformio/builder/scripts/atmelavr.py +++ b/platformio/builder/scripts/atmelavr.py @@ -99,13 +99,13 @@ env.Append( ) ) -BUILT_LIBS = env.ProcessGeneral() +CORELIBS = env.ProcessGeneral() # # Target: Build executable and linkable firmware # -target_elf = env.BuildFirmware(BUILT_LIBS + ["m"]) +target_elf = env.BuildFirmware(CORELIBS + ["m"]) # # Target: Extract EEPROM data (from EEMEM directive) to .eep file diff --git a/platformio/builder/scripts/timsp430.py b/platformio/builder/scripts/timsp430.py index 2a1ffbec..cd81bce7 100644 --- a/platformio/builder/scripts/timsp430.py +++ b/platformio/builder/scripts/timsp430.py @@ -75,13 +75,13 @@ env.Append( ) ) -BUILT_LIBS = env.ProcessGeneral() +CORELIBS = env.ProcessGeneral() # # Target: Build executable and linkable firmware # -target_elf = env.BuildFirmware(BUILT_LIBS + ["m"]) +target_elf = env.BuildFirmware(CORELIBS + ["m"]) # # Target: Build the .hex diff --git a/platformio/builder/scripts/titiva.py b/platformio/builder/scripts/titiva.py index 1440b33e..8dacd75f 100644 --- a/platformio/builder/scripts/titiva.py +++ b/platformio/builder/scripts/titiva.py @@ -89,13 +89,13 @@ env.Append( ) ) -BUILT_LIBS = env.ProcessGeneral() +CORELIBS = env.ProcessGeneral() # # Target: Build executable and linkable firmware # -target_elf = env.BuildFirmware(BUILT_LIBS + ["c", "gcc", "m"]) +target_elf = env.BuildFirmware(CORELIBS + ["c", "gcc", "m"]) # # Target: Build the .bin file diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 9216c606..599f223a 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -9,7 +9,7 @@ from SCons.Script import SConscript, SConscriptChdir def ProcessGeneral(env): - libs = [] + corelibs = [] if "BUILD_FLAGS" in env: env.MergeFlags(env['BUILD_FLAGS']) @@ -20,55 +20,28 @@ def ProcessGeneral(env): if "FRAMEWORK" in env: SConscriptChdir(0) - libs = SConscript(env.subst(join("$PIOBUILDER_DIR", "scripts", - "frameworks", "${FRAMEWORK}.py")), - exports="env") - return libs + corelibs = SConscript(env.subst(join("$PIOBUILDER_DIR", "scripts", + "frameworks", "${FRAMEWORK}.py")), + exports="env") + return corelibs -def BuildLibrary(env, variant_dir, library_dir): - lib = env.Clone() - vdirs = lib.VariantDirRecursive(variant_dir, library_dir) - return lib.Library( - lib.subst(variant_dir), - [lib.GlobCXXFiles(vdir) for vdir in vdirs] - ) - - -def BuildDependentLibraries(env, src_dir): - libs = [] - for deplibfile in env.GetDependentLibraries(src_dir): - for lsd_dir in env['LIBSOURCE_DIRS']: - lsd_dir = env.subst(lsd_dir) - if not isdir(lsd_dir): - continue - for libname in listdir(lsd_dir): - if not isfile(join(lsd_dir, libname, deplibfile)): - continue - _libbuild_dir = join("$BUILD_DIR", libname) - env.Append(CPPPATH=[_libbuild_dir]) - libs.append( - env.BuildLibrary(_libbuild_dir, join(lsd_dir, libname))) - return libs - - -def BuildFirmware(env, libslist): +def BuildFirmware(env, corelibs): src = env.Clone() vdirs = src.VariantDirRecursive( join("$BUILD_DIR", "src"), join("$PROJECT_DIR", "src")) # build source's dependent libs + deplibs = [] for vdir in vdirs: - _libs = src.BuildDependentLibraries(vdir) - if _libs: - libslist += _libs + deplibs += src.BuildDependentLibraries(vdir) src.MergeFlags(getenv("PIOSRCBUILD_FLAGS", "$SRCBUILD_FLAGS")) return src.Program( join("$BUILD_DIR", "firmware"), [src.GlobCXXFiles(vdir) for vdir in vdirs], - LIBS=libslist, + LIBS=deplibs + corelibs, LIBPATH="$BUILD_DIR", PROGSUFFIX=".elf") @@ -82,12 +55,53 @@ def GlobCXXFiles(env, path): return files +def BuildLibrary(env, variant_dir, library_dir): + lib = env.Clone() + vdirs = lib.VariantDirRecursive(variant_dir, library_dir) + return lib.Library( + lib.subst(variant_dir), + [lib.GlobCXXFiles(vdir) for vdir in vdirs] + ) + + +def BuildDependentLibraries(env, src_dir): + libs = [] + deplibs = env.GetDependentLibraries(src_dir) + env.Append(CPPPATH=[join("$BUILD_DIR", l) for (l, _) in deplibs]) + + for (libname, lsd_dir) in deplibs: + libs.append( + env.BuildLibrary(join("$BUILD_DIR", libname), join(lsd_dir, + libname))) + return libs + + def GetDependentLibraries(env, src_dir): - deplibs = [] - regexp = re.compile(r"^#include\s+<([^>]+)>", re.M) + includes = {} + regexp = re.compile(r"^\s?#include\s+(?:\<|\"|\')([^\>\"\']+)(?:\>|\"|\')", + re.M) for node in env.GlobCXXFiles(src_dir): - deplibs += regexp.findall(node.get_text_contents()) - return deplibs + env.ParseIncludesRecurive(regexp, node, includes) + + includes = sorted(includes.items(), key=lambda s: s[0]) + return set([(i[1][1], i[1][2]) for i in includes]) + + +def ParseIncludesRecurive(env, regexp, source_file, includes): + matches = regexp.findall(source_file.get_text_contents()) + for inc_name in matches: + if inc_name in includes: + continue + for lsd_dir in env['LIBSOURCE_DIRS']: + lsd_dir = env.subst(lsd_dir) + if not isdir(lsd_dir): + continue + for libname in listdir(lsd_dir): + inc_path = join(lsd_dir, libname, inc_name) + if not isfile(inc_path): + continue + includes[inc_name] = (len(includes) + 1, libname, lsd_dir) + env.ParseIncludesRecurive(regexp, env.File(inc_path), includes) def VariantDirRecursive(env, variant_dir, src_dir, duplicate=True): @@ -141,11 +155,12 @@ def exists(_): def generate(env): env.AddMethod(ProcessGeneral) - env.AddMethod(BuildLibrary) - env.AddMethod(BuildDependentLibraries) env.AddMethod(BuildFirmware) env.AddMethod(GlobCXXFiles) + env.AddMethod(BuildLibrary) + env.AddMethod(BuildDependentLibraries) env.AddMethod(GetDependentLibraries) + env.AddMethod(ParseIncludesRecurive) env.AddMethod(VariantDirRecursive) env.AddMethod(ParseBoardOptions) return env