From 3c8e0b17a7c42691e8fe4e0c418e88e926d8c453 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 9 Jun 2020 18:43:50 +0300 Subject: [PATCH] Added support for custom targets --- HISTORY.rst | 9 ++- docs | 2 +- platformio/builder/main.py | 3 +- platformio/builder/tools/pioide.py | 4 +- platformio/builder/tools/piomisc.py | 58 ++++---------- platformio/builder/tools/piotarget.py | 109 ++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 46 deletions(-) create mode 100644 platformio/builder/tools/piotarget.py diff --git a/HISTORY.rst b/HISTORY.rst index 250e680a..65392477 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -6,9 +6,16 @@ Release Notes PlatformIO Core 4 ----------------- -4.3.5 (2020-??-??) +4.4.0 (2020-??-??) ~~~~~~~~~~~~~~~~~~ +* New `Account Management System `__ (preview) + + - Manage own organizations + - Manage organization teams + - Manage resource access + +* Added support for `custom targets `__ (user cases: command shortcuts, pre/post processing based on dependencies, custom command launcher with options, etc.) * Added support for "globstar/`**`" (recursive) pattern for the different commands and configuration options (`platformio ci `__, `src_filter `__, `check_patterns `__, `library.json > srcFilter `__). Python 3.5+ is required. 4.3.4 (2020-05-23) diff --git a/docs b/docs index cfba4f45..439f402c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit cfba4f456843f1069d9ebd083e359186054c8659 +Subproject commit 439f402c5b882af01b48068180810a58fc6db5ae diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 7184da7c..a0a8ab12 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -55,6 +55,7 @@ DEFAULT_ENV_OPTIONS = dict( "c++", "link", "platformio", + "piotarget", "pioplatform", "pioproject", "piomaxlen", @@ -217,7 +218,7 @@ if "idedata" in COMMAND_LINE_TARGETS: click.echo( "\n%s\n" % dump_json_to_unicode( - projenv.DumpIDEData() # pylint: disable=undefined-variable + projenv.DumpIDEData(env) # pylint: disable=undefined-variable ) ) env.Exit(0) diff --git a/platformio/builder/tools/pioide.py b/platformio/builder/tools/pioide.py index 65203ab7..acb36ae4 100644 --- a/platformio/builder/tools/pioide.py +++ b/platformio/builder/tools/pioide.py @@ -143,7 +143,8 @@ def _escape_build_flag(flags): return [flag if " " not in flag else '"%s"' % flag for flag in flags] -def DumpIDEData(env): +def DumpIDEData(env, globalenv): + """ env here is `projenv`""" env["__escape_build_flag"] = _escape_build_flag @@ -169,6 +170,7 @@ def DumpIDEData(env): ], "svd_path": _get_svd_path(env), "compiler_type": env.GetCompilerType(), + "targets": globalenv.DumpTargets(), } env_ = env.Clone() diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 1079f402..aa5158fe 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -16,15 +16,12 @@ from __future__ import absolute_import import atexit import io +import os import re import sys -from os import environ, remove, walk -from os.path import basename, isdir, isfile, join, realpath, relpath, sep from tempfile import mkstemp import click -from SCons.Action import Action # pylint: disable=import-error -from SCons.Script import ARGUMENTS # pylint: disable=import-error from platformio import fs, util from platformio.compat import get_filesystem_encoding, get_locale_encoding, glob_escape @@ -126,11 +123,11 @@ class InoToCPPConverter(object): '$CXX -o "{0}" -x c++ -fpreprocessed -dD -E "{1}"'.format( out_file, tmp_path ), - "Converting " + basename(out_file[:-4]), + "Converting " + os.path.basename(out_file[:-4]), ) ) atexit.register(_delete_file, tmp_path) - return isfile(out_file) + return os.path.isfile(out_file) def _join_multiline_strings(self, contents): if "\\\n" not in contents: @@ -233,7 +230,9 @@ class InoToCPPConverter(object): def ConvertInoToCpp(env): src_dir = glob_escape(env.subst("$PROJECT_SRC_DIR")) - ino_nodes = env.Glob(join(src_dir, "*.ino")) + env.Glob(join(src_dir, "*.pde")) + ino_nodes = env.Glob(os.path.join(src_dir, "*.ino")) + env.Glob( + os.path.join(src_dir, "*.pde") + ) if not ino_nodes: return c = InoToCPPConverter(env) @@ -244,8 +243,8 @@ def ConvertInoToCpp(env): def _delete_file(path): try: - if isfile(path): - remove(path) + if os.path.isfile(path): + os.remove(path) except: # pylint: disable=bare-except pass @@ -255,7 +254,7 @@ def _get_compiler_type(env): if env.subst("$CC").endswith("-gcc"): return "gcc" try: - sysenv = environ.copy() + sysenv = os.environ.copy() sysenv["PATH"] = str(env["ENV"]["PATH"]) result = exec_command([env.subst("$CC"), "-v"], env=sysenv) except OSError: @@ -277,8 +276,8 @@ def GetCompilerType(env): def GetActualLDScript(env): def _lookup_in_ldpath(script): for d in env.get("LIBPATH", []): - path = join(env.subst(d), script) - if isfile(path): + path = os.path.join(env.subst(d), script) + if os.path.isfile(path): return path return None @@ -297,7 +296,7 @@ def GetActualLDScript(env): else: continue script = env.subst(raw_script.replace('"', "").strip()) - if isfile(script): + if os.path.isfile(script): return script path = _lookup_in_ldpath(script) if path: @@ -319,29 +318,6 @@ def GetActualLDScript(env): env.Exit(1) -def VerboseAction(_, act, actstr): - if int(ARGUMENTS.get("PIOVERBOSE", 0)): - return act - return Action(act, actstr) - - -def PioClean(env, clean_dir): - if not isdir(clean_dir): - print("Build environment is clean") - env.Exit(0) - clean_rel_path = relpath(clean_dir) - for root, _, files in walk(clean_dir): - for f in files: - dst = join(root, f) - remove(dst) - print( - "Removed %s" % (dst if clean_rel_path.startswith(".") else relpath(dst)) - ) - print("Done cleaning") - fs.rmtree(clean_dir) - env.Exit(0) - - def ConfigureDebugFlags(env): def _cleanup_debug_flags(scope): if scope not in env: @@ -370,16 +346,16 @@ def ConfigureDebugFlags(env): def ConfigureTestTarget(env): env.Append( CPPDEFINES=["UNIT_TEST", "UNITY_INCLUDE_CONFIG_H"], - CPPPATH=[join("$BUILD_DIR", "UnityTestLib")], + CPPPATH=[os.path.join("$BUILD_DIR", "UnityTestLib")], ) unitylib = env.BuildLibrary( - join("$BUILD_DIR", "UnityTestLib"), get_core_package_dir("tool-unity") + os.path.join("$BUILD_DIR", "UnityTestLib"), get_core_package_dir("tool-unity") ) env.Prepend(LIBS=[unitylib]) src_filter = ["+<*.cpp>", "+<*.c>"] if "PIOTEST_RUNNING_NAME" in env: - src_filter.append("+<%s%s>" % (env["PIOTEST_RUNNING_NAME"], sep)) + src_filter.append("+<%s%s>" % (env["PIOTEST_RUNNING_NAME"], os.path.sep)) env.Replace(PIOTEST_SRC_FILTER=src_filter) @@ -393,7 +369,7 @@ def GetExtraScripts(env, scope): if not items: return items with fs.cd(env.subst("$PROJECT_DIR")): - return [realpath(item) for item in items] + return [os.path.realpath(item) for item in items] def exists(_): @@ -404,8 +380,6 @@ def generate(env): env.AddMethod(ConvertInoToCpp) env.AddMethod(GetCompilerType) env.AddMethod(GetActualLDScript) - env.AddMethod(VerboseAction) - env.AddMethod(PioClean) env.AddMethod(ConfigureDebugFlags) env.AddMethod(ConfigureTestTarget) env.AddMethod(GetExtraScripts) diff --git a/platformio/builder/tools/piotarget.py b/platformio/builder/tools/piotarget.py new file mode 100644 index 00000000..cbe90455 --- /dev/null +++ b/platformio/builder/tools/piotarget.py @@ -0,0 +1,109 @@ +# Copyright (c) 2014-present PlatformIO +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import absolute_import + +import os + +from SCons.Action import Action # pylint: disable=import-error +from SCons.Script import ARGUMENTS # pylint: disable=import-error +from SCons.Script import AlwaysBuild # pylint: disable=import-error + +from platformio import fs + + +def VerboseAction(_, act, actstr): + if int(ARGUMENTS.get("PIOVERBOSE", 0)): + return act + return Action(act, actstr) + + +def PioClean(env, clean_dir): + if not os.path.isdir(clean_dir): + print("Build environment is clean") + env.Exit(0) + clean_rel_path = os.path.relpath(clean_dir) + for root, _, files in os.walk(clean_dir): + for f in files: + dst = os.path.join(root, f) + os.remove(dst) + print( + "Removed %s" + % (dst if clean_rel_path.startswith(".") else os.path.relpath(dst)) + ) + print("Done cleaning") + fs.rmtree(clean_dir) + env.Exit(0) + + +def _add_pio_target( # pylint: disable=too-many-arguments + env, + scope, + name, + dependencies, + actions, + title=None, + description=None, + always_build=True, +): + if "__PIO_TARGETS" not in env: + env["__PIO_TARGETS"] = {} + assert name not in env["__PIO_TARGETS"] + env["__PIO_TARGETS"][name] = dict( + name=name, scope=scope, title=title, description=description + ) + target = env.Alias(name, dependencies, actions) + if always_build: + AlwaysBuild(target) + return target + + +def AddSystemTarget(env, *args, **kwargs): + return _add_pio_target(env, "system", *args, **kwargs) + + +def AddCustomTarget(env, *args, **kwargs): + return _add_pio_target(env, "custom", *args, **kwargs) + + +def DumpTargets(env): + print("DumpTargets", id(env)) + targets = env.get("__PIO_TARGETS") or {} + # pre-fill default system targets + if ( + not any(t["scope"] == "system" for t in targets.values()) + and env.PioPlatform().is_embedded() + ): + targets["upload"] = dict(name="upload", scope="system", title="Upload") + targets["compiledb"] = dict( + name="compiledb", + scope="system", + title="Compilation database", + description="Generate compilation database `compile_commands.json`", + ) + targets["clean"] = dict(name="clean", scope="system", title="Clean") + return list(targets.values()) + + +def exists(_): + return True + + +def generate(env): + env.AddMethod(VerboseAction) + env.AddMethod(PioClean) + env.AddMethod(AddSystemTarget) + env.AddMethod(AddCustomTarget) + env.AddMethod(DumpTargets) + return env