From 3a48f1c40baa6aa72caf3486d26cba91cfd8b578 Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 12 Jun 2015 23:47:17 -0500 Subject: [PATCH 01/37] Updated recommened platforms install $ platformio install [platform] The above line is obsolete, I've changed the recommendation to reflect this latest version of the program. --- platformio/exception.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/exception.py b/platformio/exception.py index 22b5978a..d8cb13fd 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -30,7 +30,7 @@ class UnknownPlatform(PlatformioException): class PlatformNotInstalledYet(PlatformioException): MESSAGE = ("The platform '%s' has not been installed yet. " - "Use `platformio install` command") + "Use `platformio platforms install` command") class UnknownCLICommand(PlatformioException): From 14f84a49a6a3810f25caa390f78a33bb28b17cf6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 17 Jun 2015 13:28:56 +0300 Subject: [PATCH 02/37] Allow to specify library compatibility with the all platforms/frameworks using * symbol in library.json --- HISTORY.rst | 7 +++++++ docs/librarymanager/config.rst | 13 +++++++++++++ platformio/__init__.py | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index f6be44fa..eda258b4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,6 +1,13 @@ Release History =============== +2.1.2 (2015-??-??) +------------------ + +* Allow to specify library compatibility with the all platforms/frameworks using + ``*`` symbol in + `library.json `__ + 2.1.1 (2015-06-09) ------------------ diff --git a/docs/librarymanager/config.rst b/docs/librarymanager/config.rst index 1d0d64d2..8544ac35 100644 --- a/docs/librarymanager/config.rst +++ b/docs/librarymanager/config.rst @@ -249,6 +249,12 @@ patterns. A list with compatible frameworks. The available framework types are defined in the :ref:`platforms` section. +If the library is compatible with the all frameworks, then you can use ``*`` +symbol: + +.. code-block:: javascript + + "frameworks": "*" .. _libjson_platforms: @@ -260,6 +266,13 @@ the :ref:`platforms` section. A list with compatible platforms. The available platform types are defined in :ref:`platforms` section. +If the library is compatible with the all platforms, then you can use ``*`` +symbol: + +.. code-block:: javascript + + "platforms": "*" + .. _libjson_dependencies: diff --git a/platformio/__init__.py b/platformio/__init__.py index d0de4173..6923cb2b 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 1, 1) +VERSION = (2, 1, "2.dev0") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" From ca721d72622f3b4486bf4336053a9ed2890c9990 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 17 Jun 2015 13:29:28 +0300 Subject: [PATCH 03/37] Update dependent test-lib --- .../arduino-external-libs/lib/Adafruit-GFX-Library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library b/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library index 734b107c..ea4c4c55 160000 --- a/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library +++ b/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library @@ -1 +1 @@ -Subproject commit 734b107c393e8a91d8c1d46a42f59a4dfb25b576 +Subproject commit ea4c4c5596aaa91e1e10c89c7817df4e12e312c5 From 4669dc7f16fbd080d4c009c8239c56708b037ce3 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 17 Jun 2015 13:35:10 +0300 Subject: [PATCH 04/37] Fix "stk500v2_command(): command failed" // Resolve #238 --- HISTORY.rst | 2 ++ platformio/builder/scripts/atmelavr.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index eda258b4..82197e67 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,6 +7,8 @@ Release History * Allow to specify library compatibility with the all platforms/frameworks using ``*`` symbol in `library.json `__ +* Fixed ``stk500v2_command(): command failed`` + (`issue #238 `_) 2.1.1 (2015-06-09) ------------------ diff --git a/platformio/builder/scripts/atmelavr.py b/platformio/builder/scripts/atmelavr.py index f86f130f..1027b6a4 100644 --- a/platformio/builder/scripts/atmelavr.py +++ b/platformio/builder/scripts/atmelavr.py @@ -30,7 +30,10 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 env.Replace(UPLOAD_SPEED=None) if env.subst("$UPLOAD_SPEED"): - env.Append(UPLOADERFLAGS=["-b", "$UPLOAD_SPEED"]) + env.Append(UPLOADERFLAGS=[ + "-b", "$UPLOAD_SPEED", + "-D" + ]) if not upload_options.get("require_upload_port", False): return From 5f1f4a1b1983a0df56f457b17b15255bd83fc13b Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 17 Jun 2015 14:08:22 +0300 Subject: [PATCH 05/37] Bump to 2.2.0.dev0 --- HISTORY.rst | 2 +- platformio/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 82197e67..430fff87 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,7 +1,7 @@ Release History =============== -2.1.2 (2015-??-??) +2.2.0 (2015-??-??) ------------------ * Allow to specify library compatibility with the all platforms/frameworks using diff --git a/platformio/__init__.py b/platformio/__init__.py index 6923cb2b..b0fff13e 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 1, "2.dev0") +VERSION = (2, 2, "0.dev0") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" From 89e2f46e6842fb048d8de58c9af2e0d51dca3b6a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 19 Jun 2015 00:10:17 +0300 Subject: [PATCH 06/37] Update dependent test-lib --- .../arduino-external-libs/lib/Adafruit-GFX-Library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library b/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library index ea4c4c55..6d40eb34 160000 --- a/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library +++ b/examples/atmelavr-and-arduino/arduino-external-libs/lib/Adafruit-GFX-Library @@ -1 +1 @@ -Subproject commit ea4c4c5596aaa91e1e10c89c7817df4e12e312c5 +Subproject commit 6d40eb3423c4245bf5725dbf1c65d33057c08579 From 91563b01d2df0f1ef5b9b51a57a17dc0699b56ea Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 19 Jun 2015 00:10:50 +0300 Subject: [PATCH 07/37] Improve path validator --- platformio/commands/ci.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platformio/commands/ci.py b/platformio/commands/ci.py index cf4f5010..b65f09fc 100644 --- a/platformio/commands/ci.py +++ b/platformio/commands/ci.py @@ -4,7 +4,7 @@ import stat from glob import glob from os import chmod, getenv, makedirs, remove -from os.path import abspath, basename, isdir, isfile, join +from os.path import abspath, basename, expanduser, isdir, isfile, join from shutil import copyfile, copytree, rmtree from tempfile import mkdtemp @@ -19,8 +19,12 @@ from platformio.util import get_boards def validate_path(ctx, param, value): # pylint: disable=W0613 invalid_path = None - for p in value: - if not glob(p): + value = list(value) + for i, p in enumerate(value): + if p.startswith("~"): + value[i] = expanduser(p) + value[i] = abspath(value[i]) + if not glob(value[i]): invalid_path = p break try: @@ -109,7 +113,6 @@ def _copy_contents(dst_dir, contents): } for path in contents: - path = abspath(path) if isdir(path): items['dirs'].add(path) elif isfile(path): From 8e95bfb46462e67a71430267bd9bf68d54915f96 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 19 Jun 2015 13:43:30 +0300 Subject: [PATCH 08/37] Allow to specify own path to the linker script (ld) using build_flags option // Resolve #233 --- HISTORY.rst | 7 +++++-- docs/projectconf.rst | 25 ++++++++++++++++--------- platformio/__init__.py | 2 +- platformio/builder/tools/platformio.py | 5 +++-- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 430fff87..1a18015a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,8 +4,11 @@ Release History 2.2.0 (2015-??-??) ------------------ -* Allow to specify library compatibility with the all platforms/frameworks using - ``*`` symbol in +* Allowed to specify own path to the linker script (ld) using + `build_flags `__ option + (`issue #233 `_) +* Allowed to specify library compatibility with the all platforms/frameworks + using ``*`` symbol in `library.json `__ * Fixed ``stk500v2_command(): command failed`` (`issue #238 `_) diff --git a/docs/projectconf.rst b/docs/projectconf.rst index 8aba9efe..6a39b887 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -226,10 +226,6 @@ processes: * - Format - Scope - Description - * - ``-Wp,option`` - - CPPFLAGS - - Bypass the compiler driver and pass *option* directly through to the - preprocessor * - ``-D name`` - CPPDEFINES - Predefine *name* as a macro, with definition 1. @@ -241,6 +237,10 @@ processes: - CPPDEFINES - Cancel any previous definition of *name*, either built in or provided with a ``-D`` option. + * - ``-Wp,option`` + - CPPFLAGS + - Bypass the compiler driver and pass *option* directly through to the + preprocessor * - ``-Wall`` - CCFLAGS - Turns on all optional warnings which are desirable for normal code. @@ -254,10 +254,18 @@ processes: - CCFLAGS - Process *file* as if ``#include "file"`` appeared as the first line of the primary source file. + * - ``-Idir`` + - CPPPATH + - Add the directory *dir* to the list of directories to be searched + for header files. * - ``-Wa,option`` - ASFLAGS, CCFLAGS - Pass *option* as an option to the assembler. If *option* contains commas, it is split into multiple options at the commas. + * - ``-Wl,option`` + - LINKFLAGS + - Pass *option* as an option to the linker. If *option* contains + commas, it is split into multiple options at the commas. * - ``-llibrary`` - LIBS - Search the *library* named library when linking @@ -265,10 +273,6 @@ processes: - LIBPATH - Add directory *dir* to the list of directories to be searched for ``-l``. - * - ``-Idir`` - - CPPPATH - - Add the directory *dir* to the list of directories to be searched - for header files. This option can be set by global environment variable :ref:`envvar_PLATFORMIO_BUILD_FLAGS`. @@ -278,11 +282,14 @@ Example: .. code-block:: ini [env:specific_defines] - build_flags = -O2 -Dfoo -Dbar=1 + build_flags = -Dfoo -Dbar=1 [env:specific_inclibs] build_flags = -I/opt/include -L/opt/lib -lfoo + [env:specific_ld_script] + build_flags = -Wl,-T/path/to/ld_script.ld + For more detailed information about available flags/options go to: diff --git a/platformio/__init__.py b/platformio/__init__.py index b0fff13e..77112693 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 2, "0.dev0") +VERSION = (2, 2, "0.dev1") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 2cd8b44e..79695742 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -35,9 +35,10 @@ def BuildFirmware(env): deplibs = firmenv.BuildDependentLibraries("$PROJECTSRC_DIR") # append specified LD_SCRIPT - if "LDSCRIPT_PATH" in firmenv: + if ("LDSCRIPT_PATH" in firmenv and + not any(["-Wl,-T" in f for f in firmenv['LINKFLAGS']])): firmenv.Append( - LINKFLAGS=["-T", "$LDSCRIPT_PATH"] + LINKFLAGS=["-Wl,-T", "$LDSCRIPT_PATH"] ) # enable "cyclic reference" for linker From 829d5781a5ecaaa5740ba0365d863f4e32ed8045 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 19 Jun 2015 15:29:22 +0300 Subject: [PATCH 09/37] Allow to launch own extra script before firmware building/uploading processes // Resolve #239 --- HISTORY.rst | 9 ++++-- docs/envvars.rst | 7 +++++ docs/projectconf.rst | 37 +++++++++++++++++++++++++ platformio/__init__.py | 2 +- platformio/builder/main.py | 18 ++++++++++-- platformio/builder/tools/platformio.py | 38 +++++++++----------------- 6 files changed, 80 insertions(+), 31 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 1a18015a..7c5e7152 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,10 +4,13 @@ Release History 2.2.0 (2015-??-??) ------------------ -* Allowed to specify own path to the linker script (ld) using - `build_flags `__ option +* Launch own extra script before firmware building/uploading processes + (`issue #239 `_) +* Specify own path to the linker script (ld) using + `build_flags `__ + option (`issue #233 `_) -* Allowed to specify library compatibility with the all platforms/frameworks +* Specify library compatibility with the all platforms/frameworks using ``*`` symbol in `library.json `__ * Fixed ``stk500v2_command(): command failed`` diff --git a/docs/envvars.rst b/docs/envvars.rst index 25414e27..95a441f5 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -84,6 +84,13 @@ PLATFORMIO_LDF_CYCLIC Allows to set :ref:`projectconf` option :ref:`projectconf_ldf_cyclic`. +.. _envvar_PLATFORMIO_EXTRA_SCRIPT: + +PLATFORMIO_EXTRA_SCRIPT +~~~~~~~~~~~~~~~~~~~~~~~ + +Allows to set :ref:`projectconf` option :ref:`projectconf_extra_script`. + Settings -------- diff --git a/docs/projectconf.rst b/docs/projectconf.rst index 6a39b887..1d8462c4 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -384,6 +384,43 @@ Example: [env:libs_with_enabled_ldf_cyclic] ldf_cyclic = True +.. _projectconf_extra_script: + +``extra_script`` +^^^^^^^^^^^^^^^^ + +Allows to launch extra script using `SCons `_ software +construction tool. For more details please follow to "Construction Environments" +section of +`SCons documentation `_. + +This option can be set by global environment variable +:ref:`envvar_PLATFORMIO_EXTRA_SCRIPT`. + +Example, specify own upload command for :ref:`platform_atmelavr`: + +``platformio.ini``: + +.. code-block:: ini + + [env:env_with_specific_extra_script] + platform = atmelavr + extra_script = /path/to/extra_script.py + +``extra_script.py``: + +.. code-block:: python + + from SCons.Script import DefaultEnvironment + + env = DefaultEnvironment() + + env.Replace(UPLOADHEXCMD='"$UPLOADER" --uploader --flags') + + # uncomment line below to see environment variables + # print env.Dump() + +See built-in examples of `PlatformIO build scripts `_. .. _projectconf_examples: diff --git a/platformio/__init__.py b/platformio/__init__.py index 77112693..6dbbfe25 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 2, "0.dev1") +VERSION = (2, 2, "0.dev2") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/main.py b/platformio/builder/main.py index a9f06099..073c7f71 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -11,11 +11,13 @@ except ImportError: break from platformio import util +import json +from os import getenv from os.path import isfile, join from time import time -from SCons.Script import (DefaultEnvironment, Exit, SConscript, - SConscriptChdir, Variables) +from SCons.Script import (COMMAND_LINE_TARGETS, DefaultEnvironment, Exit, + SConscript, SConscriptChdir, Variables) from platformio.exception import UnknownBoard @@ -25,6 +27,7 @@ from platformio.exception import UnknownBoard commonvars = Variables(None) commonvars.AddVariables( ("BUILD_SCRIPT",), + ("EXTRA_SCRIPT",), ("PIOENV",), ("PLATFORM",), @@ -123,3 +126,14 @@ env.PrependENVPath( SConscriptChdir(0) SConscript(env.subst("$BUILD_SCRIPT")) + +if getenv("PLATFORMIO_EXTRA_SCRIPT", env.get("EXTRA_SCRIPT", None)): + SConscript(getenv("PLATFORMIO_EXTRA_SCRIPT", env.get("EXTRA_SCRIPT"))) + +if "envdump" in COMMAND_LINE_TARGETS: + print env.Dump() + Exit() + +if "idedata" in COMMAND_LINE_TARGETS: + print json.dumps(env.DumpIDEData()) + Exit() diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 79695742..5e373105 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -2,14 +2,12 @@ # See LICENSE for details. import atexit -import json import re from glob import glob from os import getenv, listdir, remove, sep, walk from os.path import basename, dirname, isdir, isfile, join, normpath -from SCons.Script import (COMMAND_LINE_TARGETS, DefaultEnvironment, Exit, - SConscript, SConscriptChdir) +from SCons.Script import DefaultEnvironment, Exit, SConscript from SCons.Util import case_sensitive_suffixes from platformio.util import pioversion_to_intstr @@ -27,50 +25,41 @@ def BuildFirmware(env): env.ProcessFlags() env.BuildFramework() - firmenv = env.Clone() - vdirs = firmenv.VariantDirRecursive( + vdirs = env.VariantDirRecursive( join("$BUILD_DIR", "src"), "$PROJECTSRC_DIR", duplicate=False) # build dependent libs - deplibs = firmenv.BuildDependentLibraries("$PROJECTSRC_DIR") + deplibs = env.BuildDependentLibraries("$PROJECTSRC_DIR") # append specified LD_SCRIPT - if ("LDSCRIPT_PATH" in firmenv and - not any(["-Wl,-T" in f for f in firmenv['LINKFLAGS']])): - firmenv.Append( + if ("LDSCRIPT_PATH" in env and + not any(["-Wl,-T" in f for f in env['LINKFLAGS']])): + env.Append( LINKFLAGS=["-Wl,-T", "$LDSCRIPT_PATH"] ) # enable "cyclic reference" for linker - firmenv.Prepend( + env.Prepend( _LIBFLAGS="-Wl,--start-group " ) - firmenv.Append( + env.Append( _LIBFLAGS=" -Wl,--end-group" ) # Handle SRCBUILD_FLAGS if getenv("PLATFORMIO_SRCBUILD_FLAGS", None): - firmenv.MergeFlags(getenv("PLATFORMIO_SRCBUILD_FLAGS")) + env.MergeFlags(getenv("PLATFORMIO_SRCBUILD_FLAGS")) if "SRCBUILD_FLAGS" in env: - firmenv.MergeFlags(env['SRCBUILD_FLAGS']) + env.MergeFlags(env['SRCBUILD_FLAGS']) - firmenv.Append( + env.Append( CPPDEFINES=["PLATFORMIO={0:02d}{1:02d}{2:02d}".format( *pioversion_to_intstr())] ) - if "envdump" in COMMAND_LINE_TARGETS: - print env.Dump() - Exit() - - if "idedata" in COMMAND_LINE_TARGETS: - print json.dumps(env.DumpIDEData()) - Exit() - - return firmenv.Program( + return env.Program( join("$BUILD_DIR", "firmware"), - [firmenv.GlobCXXFiles(vdir) for vdir in vdirs], + [env.GlobCXXFiles(vdir) for vdir in vdirs], LIBS=env.get("LIBS", []) + deplibs, LIBPATH=env.get("LIBPATH", []) + ["$BUILD_DIR"], PROGSUFFIX=".elf" @@ -136,7 +125,6 @@ def BuildFramework(env): for f in env['FRAMEWORK'].split(","): framework = f.strip().lower() if framework in env.get("BOARD_OPTIONS", {}).get("frameworks"): - SConscriptChdir(0) SConscript( env.subst(join("$PIOBUILDER_DIR", "scripts", "frameworks", "%s.py" % framework)) From 3232ba6a6c1053de7f6710b1d6063d4f1cc35302 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 22 Jun 2015 15:06:39 +0300 Subject: [PATCH 10/37] Allow to exclude/include source files from build process using src_filter // Resolve #240 --- HISTORY.rst | 3 + docs/envvars.rst | 7 + docs/projectconf.rst | 22 ++ platformio/__init__.py | 2 +- platformio/builder/main.py | 4 +- platformio/builder/scripts/frameworks/spl.py | 17 +- platformio/builder/tools/piomisc.py | 165 ++++++++++++ platformio/builder/tools/platformio.py | 257 +++++-------------- 8 files changed, 278 insertions(+), 199 deletions(-) create mode 100644 platformio/builder/tools/piomisc.py diff --git a/HISTORY.rst b/HISTORY.rst index 656ebfcd..398550c6 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -4,6 +4,9 @@ Release History 2.2.0 (2015-??-??) ------------------ +* Allowed to exclude/include source files from build process using + `src_filter `__ + (`issue #240 `_) * Launch own extra script before firmware building/uploading processes (`issue #239 `_) * Specify own path to the linker script (ld) using diff --git a/docs/envvars.rst b/docs/envvars.rst index 95a441f5..d3d0c084 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -77,6 +77,13 @@ PLATFORMIO_SRCBUILD_FLAGS Allows to set :ref:`projectconf` option :ref:`projectconf_srcbuild_flags`. +.. _envvar_PLATFORMIO_SRC_FILTER: + +PLATFORMIO_SRC_FILTER +~~~~~~~~~~~~~~~~~~~~~ + +Allows to set :ref:`projectconf` option :ref:`projectconf_src_filter`. + .. _envvar_PLATFORMIO_LDF_CYCLIC: PLATFORMIO_LDF_CYCLIC diff --git a/docs/projectconf.rst b/docs/projectconf.rst index 1d8462c4..8db258c4 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -319,6 +319,28 @@ but will be applied only for the project source code from This option can be set by global environment variable :ref:`envvar_PLATFORMIO_SRCBUILD_FLAGS`. +.. _projectconf_src_filter: + +``src_filter`` +^^^^^^^^^^^^^^ + +This option allows to specify which source files should be included/excluded +from build process. Filter supports 2 templates: + +* ``+`` include template +* ``-`` exclude template + +``PATH`` MAST BE related from :ref:`projectconf_pio_src_dir`. All patterns will +be applied in theirs order. +`GLOB Patterns `_ are allowed. + +By default, ``src_filter`` is predefined to +``+<*> -<.git/> - -``, which means "includes ALL files, then +exclude ``.git`` and ``svn`` repository folders and exclude ``examples`` folder. + +This option can be set by global environment variable +:ref:`envvar_PLATFORMIO_SRC_FILTER`. + ``install_libs`` ^^^^^^^^^^^^^^^^ diff --git a/platformio/__init__.py b/platformio/__init__.py index 6dbbfe25..cfeb39e7 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 2, "0.dev2") +VERSION = (2, 2, "0.dev3") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 073c7f71..5db1f0df 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -39,6 +39,7 @@ commonvars.AddVariables( ("FRAMEWORK",), ("BUILD_FLAGS",), ("SRCBUILD_FLAGS",), + ("SRC_FILTER",), ("IGNORE_LIBS",), ("USE_LIBS",), ("LDF_CYCLIC",), @@ -57,7 +58,7 @@ commonvars.AddVariables( DefaultEnvironment( tools=[ "gcc", "g++", "as", "ar", "gnulink", - "platformio", "pioupload", "pioar" + "platformio", "pioupload", "pioar", "piomisc" ], toolpath=[join("$PIOBUILDER_DIR", "tools")], variables=commonvars, @@ -74,6 +75,7 @@ DefaultEnvironment( PIOPACKAGES_DIR=join("$PIOHOME_DIR", "packages"), BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"), + BUILDSRC_DIR=join("$BUILD_DIR", "ProjectSrc"), LIBSOURCE_DIRS=[ "$PROJECTLIB_DIR", util.get_lib_dir(), diff --git a/platformio/builder/scripts/frameworks/spl.py b/platformio/builder/scripts/frameworks/spl.py index 130d8bf2..857de8c5 100644 --- a/platformio/builder/scripts/frameworks/spl.py +++ b/platformio/builder/scripts/frameworks/spl.py @@ -38,10 +38,7 @@ env.Append( envsafe = env.Clone() envsafe.Append( - CPPPATH=[ - join("$BUILD_DIR", "src") - ], - + CPPPATH=["$BUILDSRC_DIR"], CPPDEFINES=[ "USE_STDPERIPH_DRIVER" ] @@ -52,22 +49,22 @@ envsafe.Append( # extra_flags = env.get("BOARD_OPTIONS", {}).get("build", {}).get("extra_flags") -ignore_files = [] +src_filter_patterns = ["+<*>"] if "STM32F40_41xxx" in extra_flags: - ignore_files += ["stm32f4xx_fmc.c"] + src_filter_patterns += ["-"] if "STM32F427_437xx" in extra_flags: - ignore_files += ["stm32f4xx_fsmc.c"] + src_filter_patterns += ["-"] elif "STM32F303xC" in extra_flags: - ignore_files += ["stm32f30x_hrtim.c"] + src_filter_patterns += ["-"] elif "STM32L1XX_MD" in extra_flags: - ignore_files += ["stm32l1xx_flash_ramfunc.c"] + src_filter_patterns += ["-"] libs = [] libs.append(envsafe.BuildLibrary( join("$BUILD_DIR", "FrameworkSPL"), join("$PLATFORMFW_DIR", "${BOARD_OPTIONS['build']['core']}", "variants", "${BOARD_OPTIONS['build']['variant']}", "src"), - ignore_files + src_filter=" ".join(src_filter_patterns) )) env.Append(LIBS=libs) diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py new file mode 100644 index 00000000..80539c09 --- /dev/null +++ b/platformio/builder/tools/piomisc.py @@ -0,0 +1,165 @@ +# Copyright (C) Ivan Kravets +# See LICENSE for details. + +import atexit +import re +from glob import glob +from os import remove +from os.path import basename, join + + +class InoToCPPConverter(object): + + PROTOTYPE_RE = re.compile( + r"""^( + (\s*[a-z_\d]+){1,2} # return type + (\s+[a-z_\d]+\s*) # name of prototype + \([a-z_,\.\*\&\[\]\s\d]*\) # arguments + )\s*\{ # must end with { + """, + re.X | re.M | re.I + ) + + DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I) + + STRIPCOMMENTS_RE = re.compile(r"(/\*.*?\*/|(^|\s+)//[^\r\n]*$)", + re.M | re.S) + + def __init__(self, nodes): + self.nodes = nodes + + def is_main_node(self, contents): + return self.DETECTMAIN_RE.search(contents) + + @staticmethod + def _replace_comments_callback(match): + if "\n" in match.group(1): + return "\n" * match.group(1).count("\n") + else: + return " " + + def _parse_prototypes(self, contents): + prototypes = [] + reserved_keywords = set(["if", "else", "while"]) + for item in self.PROTOTYPE_RE.findall(contents): + if set([item[1].strip(), item[2].strip()]) & reserved_keywords: + continue + prototypes.append(item[0]) + return prototypes + + def append_prototypes(self, fname, contents, prototypes): + contents = self.STRIPCOMMENTS_RE.sub(self._replace_comments_callback, + contents) + result = [] + is_appended = False + linenum = 0 + for line in contents.splitlines(): + linenum += 1 + line = line.strip() + + if not is_appended and line and not line.startswith("#"): + is_appended = True + result.append("%s;" % ";\n".join(prototypes)) + result.append('#line %d "%s"' % (linenum, fname)) + + result.append(line) + + return result + + def convert(self): + prototypes = [] + data = [] + for node in self.nodes: + ino_contents = node.get_text_contents() + prototypes += self._parse_prototypes(ino_contents) + + item = (basename(node.get_path()), ino_contents) + if self.is_main_node(ino_contents): + data = [item] + data + else: + data.append(item) + + if not data: + return None + + result = ["#include "] + is_first = True + + for name, contents in data: + if is_first and prototypes: + result += self.append_prototypes(name, contents, prototypes) + else: + result.append('#line 1 "%s"' % name) + result.append(contents) + is_first = False + + return "\n".join(result) + + +def ConvertInoToCpp(env): + + def delete_tmpcpp_file(file_): + remove(file_) + + ino_nodes = (env.Glob(join("$PROJECTSRC_DIR", "*.ino")) + + env.Glob(join("$PROJECTSRC_DIR", "*.pde"))) + + c = InoToCPPConverter(ino_nodes) + data = c.convert() + + if not data: + return + + tmpcpp_file = join(env.subst("$PROJECTSRC_DIR"), "tmp_ino_to.cpp") + with open(tmpcpp_file, "w") as f: + f.write(data) + + atexit.register(delete_tmpcpp_file, tmpcpp_file) + + +def DumpIDEData(env): + data = { + "defines": [], + "includes": [] + } + + # includes from framework and libs + for item in env.get("VARIANT_DIRS", []): + if "$BUILDSRC_DIR" in item[0]: + continue + data['includes'].append(env.subst(item[1])) + + # includes from toolchain + toolchain_dir = env.subst( + join("$PIOPACKAGES_DIR", "$PIOPACKAGE_TOOLCHAIN")) + toolchain_incglobs = [ + join(toolchain_dir, "*", "include"), + join(toolchain_dir, "lib", "gcc", "*", "*", "include") + ] + for g in toolchain_incglobs: + data['includes'].extend(glob(g)) + + # global symbols + for item in env.get("CPPDEFINES", []): + data['defines'].append(env.subst(item)) + + # special symbol for Atmel AVR MCU + board = env.get("BOARD_OPTIONS", {}) + if board and board['platform'] == "atmelavr": + data['defines'].append( + "__AVR_%s__" % board['build']['mcu'].upper() + .replace("ATMEGA", "ATmega") + .replace("ATTINY", "ATtiny") + ) + + return data + + +def exists(_): + return True + + +def generate(env): + env.AddMethod(ConvertInoToCpp) + env.AddMethod(DumpIDEData) + return env diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index 5e373105..a0e2edff 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -1,10 +1,9 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -import atexit import re from glob import glob -from os import getenv, listdir, remove, sep, walk +from os import getenv, listdir, sep, walk from os.path import basename, dirname, isdir, isfile, join, normpath from SCons.Script import DefaultEnvironment, Exit, SConscript @@ -13,6 +12,13 @@ from SCons.Util import case_sensitive_suffixes from platformio.util import pioversion_to_intstr +SRC_BUILD_EXT = ["c", "cpp", "S", "spp", "SPP", "sx", "s", "asm", "ASM"] +SRC_HEADER_EXT = ["h", "hpp"] +SRC_DEFAULT_FILTER = " ".join([ + "+<*>", "-<.git%s>" % sep, "-" % sep, "-" % sep +]) + + def BuildFirmware(env): # fix ASM handling under non-casitive OS @@ -25,9 +31,6 @@ def BuildFirmware(env): env.ProcessFlags() env.BuildFramework() - vdirs = env.VariantDirRecursive( - join("$BUILD_DIR", "src"), "$PROJECTSRC_DIR", duplicate=False) - # build dependent libs deplibs = env.BuildDependentLibraries("$PROJECTSRC_DIR") @@ -59,7 +62,10 @@ def BuildFirmware(env): return env.Program( join("$BUILD_DIR", "firmware"), - [env.GlobCXXFiles(vdir) for vdir in vdirs], + env.LookupSources( + "$BUILDSRC_DIR", "$PROJECTSRC_DIR", duplicate=False, + src_filter=getenv("PLATFORMIO_SRC_FILTER", + env.get("SRC_FILTER", None))), LIBS=env.get("LIBS", []) + deplibs, LIBPATH=env.get("LIBPATH", []) + ["$BUILD_DIR"], PROGSUFFIX=".elf" @@ -85,13 +91,13 @@ def ProcessFlags(env): env.Append(_CPPDEFFLAGS=" %s" % " ".join(undefines)) -def GlobCXXFiles(env, path): - files = [] - for suff in ["c", "cpp", "S", "spp", "SPP", "sx", "s", "asm", "ASM"]: - _list = env.Glob(join(path, "*.%s" % suff)) - if _list: - files += _list - return files +def IsFileWithExt(env, file_, ext): # pylint: disable=W0613 + if basename(file_).startswith("."): + return False + for e in ext: + if file_.endswith(".%s" % e): + return True + return False def VariantDirWrap(env, variant_dir, src_dir, duplicate=True): @@ -99,20 +105,51 @@ def VariantDirWrap(env, variant_dir, src_dir, duplicate=True): env.VariantDir(variant_dir, src_dir, duplicate) -def VariantDirRecursive(env, variant_dir, src_dir, duplicate=True, - ignore_pattern=None): - if not ignore_pattern: - ignore_pattern = (".git", ".svn") +def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): + + SRC_FILTER_PATTERNS_RE = re.compile(r"(\+|\-)<([^>]+)>") + + def _append_build_item(items, item, src_dir): + if env.IsFileWithExt(item, SRC_BUILD_EXT + SRC_HEADER_EXT): + items.add(item.replace(src_dir + sep, "")) + + def _match_sources(src_dir, src_filter): + matches = set() + for (action, pattern) in SRC_FILTER_PATTERNS_RE.findall(src_filter): + items = set() + for item in glob(join(src_dir, pattern)): + if isdir(item): + for root, _, files in walk(item, followlinks=True): + for f in files: + _append_build_item(items, join(root, f), src_dir) + else: + _append_build_item(items, item, src_dir) + if action == "+": + matches |= items + else: + matches -= items + return sorted(list(matches)) + + sources = [] variants = [] + src_dir = env.subst(src_dir) - for root, _, _ in walk(src_dir, followlinks=True): - _src_dir = root - _var_dir = variant_dir + root.replace(src_dir, "") - if any([s in _var_dir.lower() for s in ignore_pattern]): - continue - env.VariantDirWrap(_var_dir, _src_dir, duplicate) - variants.append(_var_dir) - return variants + if src_dir.endswith(sep): + src_dir = src_dir[:-1] + + for item in _match_sources(src_dir, src_filter or SRC_DEFAULT_FILTER): + _reldir = dirname(item) + _src_dir = join(src_dir, _reldir) + _var_dir = join(variant_dir, _reldir) + + if _var_dir not in variants: + variants.append(_var_dir) + env.VariantDirWrap(_var_dir, _src_dir, duplicate) + + if env.IsFileWithExt(item, SRC_BUILD_EXT): + sources.append(env.File(join(_var_dir, basename(item)))) + + return sources def BuildFramework(env): @@ -134,18 +171,11 @@ def BuildFramework(env): framework) -def BuildLibrary(env, variant_dir, library_dir, ignore_files=None): +def BuildLibrary(env, variant_dir, library_dir, src_filter=None): lib = env.Clone() - vdirs = lib.VariantDirRecursive( - variant_dir, library_dir, ignore_pattern=(".git", ".svn", "examples")) - srcfiles = [] - for vdir in vdirs: - for item in lib.GlobCXXFiles(vdir): - if not ignore_files or item.name not in ignore_files: - srcfiles.append(item) return lib.Library( lib.subst(variant_dir), - srcfiles + lib.LookupSources(variant_dir, library_dir, src_filter=src_filter) ) @@ -239,10 +269,10 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 return result def _process_src_dir(state, src_dir): - for root, _, _ in walk(src_dir, followlinks=True): - for node in (env.GlobCXXFiles(root) + - env.Glob(join(root, "*.h"))): - state = _parse_includes(state, node) + for root, _, files in walk(src_dir, followlinks=True): + for f in files: + if env.IsFileWithExt(f, SRC_BUILD_EXT + SRC_HEADER_EXT): + state = _parse_includes(state, env.File(join(root, f))) return state def _parse_includes(state, node): @@ -295,151 +325,6 @@ def BuildDependentLibraries(env, src_dir): # pylint: disable=R0914 return libs -class InoToCPPConverter(object): - - PROTOTYPE_RE = re.compile( - r"""^( - (\s*[a-z_\d]+){1,2} # return type - (\s+[a-z_\d]+\s*) # name of prototype - \([a-z_,\.\*\&\[\]\s\d]*\) # arguments - )\s*\{ # must end with { - """, - re.X | re.M | re.I - ) - - DETECTMAIN_RE = re.compile(r"void\s+(setup|loop)\s*\(", re.M | re.I) - - STRIPCOMMENTS_RE = re.compile(r"(/\*.*?\*/|(^|\s+)//[^\r\n]*$)", - re.M | re.S) - - def __init__(self, nodes): - self.nodes = nodes - - def is_main_node(self, contents): - return self.DETECTMAIN_RE.search(contents) - - @staticmethod - def _replace_comments_callback(match): - if "\n" in match.group(1): - return "\n" * match.group(1).count("\n") - else: - return " " - - def _parse_prototypes(self, contents): - prototypes = [] - reserved_keywords = set(["if", "else", "while"]) - for item in self.PROTOTYPE_RE.findall(contents): - if set([item[1].strip(), item[2].strip()]) & reserved_keywords: - continue - prototypes.append(item[0]) - return prototypes - - def append_prototypes(self, fname, contents, prototypes): - contents = self.STRIPCOMMENTS_RE.sub(self._replace_comments_callback, - contents) - result = [] - is_appended = False - linenum = 0 - for line in contents.splitlines(): - linenum += 1 - line = line.strip() - - if not is_appended and line and not line.startswith("#"): - is_appended = True - result.append("%s;" % ";\n".join(prototypes)) - result.append('#line %d "%s"' % (linenum, fname)) - - result.append(line) - - return result - - def convert(self): - prototypes = [] - data = [] - for node in self.nodes: - ino_contents = node.get_text_contents() - prototypes += self._parse_prototypes(ino_contents) - - item = (basename(node.get_path()), ino_contents) - if self.is_main_node(ino_contents): - data = [item] + data - else: - data.append(item) - - if not data: - return None - - result = ["#include "] - is_first = True - - for name, contents in data: - if is_first and prototypes: - result += self.append_prototypes(name, contents, prototypes) - else: - result.append('#line 1 "%s"' % name) - result.append(contents) - is_first = False - - return "\n".join(result) - - -def ConvertInoToCpp(env): - - def delete_tmpcpp_file(file_): - remove(file_) - - ino_nodes = (env.Glob(join("$PROJECTSRC_DIR", "*.ino")) + - env.Glob(join("$PROJECTSRC_DIR", "*.pde"))) - - c = InoToCPPConverter(ino_nodes) - data = c.convert() - - if not data: - return - - tmpcpp_file = join(env.subst("$PROJECTSRC_DIR"), "tmp_ino_to.cpp") - with open(tmpcpp_file, "w") as f: - f.write(data) - - atexit.register(delete_tmpcpp_file, tmpcpp_file) - - -def DumpIDEData(env): - data = { - "defines": [], - "includes": [] - } - - # includes from framework and libs - for item in env.get("VARIANT_DIRS", []): - data['includes'].append(env.subst(item[1])) - - # includes from toolchain - toolchain_dir = env.subst( - join("$PIOPACKAGES_DIR", "$PIOPACKAGE_TOOLCHAIN")) - toolchain_incglobs = [ - join(toolchain_dir, "*", "include"), - join(toolchain_dir, "lib", "gcc", "*", "*", "include") - ] - for g in toolchain_incglobs: - data['includes'].extend(glob(g)) - - # global symbols - for item in env.get("CPPDEFINES", []): - data['defines'].append(env.subst(item)) - - # special symbol for Atmel AVR MCU - board = env.get("BOARD_OPTIONS", {}) - if board and board['platform'] == "atmelavr": - data['defines'].append( - "__AVR_%s__" % board['build']['mcu'].upper() - .replace("ATMEGA", "ATmega") - .replace("ATTINY", "ATtiny") - ) - - return data - - def exists(_): return True @@ -447,12 +332,10 @@ def exists(_): def generate(env): env.AddMethod(BuildFirmware) env.AddMethod(ProcessFlags) - env.AddMethod(GlobCXXFiles) + env.AddMethod(IsFileWithExt) env.AddMethod(VariantDirWrap) - env.AddMethod(VariantDirRecursive) + env.AddMethod(LookupSources) env.AddMethod(BuildFramework) env.AddMethod(BuildLibrary) env.AddMethod(BuildDependentLibraries) - env.AddMethod(ConvertInoToCpp) - env.AddMethod(DumpIDEData) return env From 6c7e26412a0bec1ee62452e2616981d79ab73964 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 22 Jun 2015 17:27:32 +0300 Subject: [PATCH 11/37] Change source dir to "src" --- platformio/builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 5db1f0df..7f9374f6 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -75,7 +75,7 @@ DefaultEnvironment( PIOPACKAGES_DIR=join("$PIOHOME_DIR", "packages"), BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"), - BUILDSRC_DIR=join("$BUILD_DIR", "ProjectSrc"), + BUILDSRC_DIR=join("$BUILD_DIR", "src"), LIBSOURCE_DIRS=[ "$PROJECTLIB_DIR", util.get_lib_dir(), From e240e0ee32b95331b437fd74b99ab852b9225c74 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 22 Jun 2015 18:45:20 +0300 Subject: [PATCH 12/37] Add to FAQ ARM toolchain issue with "error while loading shared libraries" --- docs/faq.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index 6065be35..59e8d400 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -100,3 +100,9 @@ Please upgrade *SetupTools* package: # Then re-install PlatformIO $ [sudo] pip uninstall platformio $ [sudo] pip install platformio + +ARM toolchain: ``cc1plus: error while loading shared libraries`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See related answers for +`error while loading shared libraries `_. From 43205b8cd5bd2d85e9375d9e6599a483d89a0484 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 23 Jun 2015 14:24:46 +0300 Subject: [PATCH 13/37] Correct fs directory separator // Issue #240 --- platformio/builder/tools/platformio.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platformio/builder/tools/platformio.py b/platformio/builder/tools/platformio.py index a0e2edff..9c4e2fb9 100644 --- a/platformio/builder/tools/platformio.py +++ b/platformio/builder/tools/platformio.py @@ -115,6 +115,8 @@ def LookupSources(env, variant_dir, src_dir, duplicate=True, src_filter=None): def _match_sources(src_dir, src_filter): matches = set() + # correct fs directory separator + src_filter = src_filter.replace("/", sep).replace("\\", sep) for (action, pattern) in SRC_FILTER_PATTERNS_RE.findall(src_filter): items = set() for item in glob(join(src_dir, pattern)): From 82864d38e2fa14ee49af01f43aa724d3fef8658d Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 27 Jun 2015 15:13:27 +0300 Subject: [PATCH 14/37] Fix IDE project generator when board is specified // Resolve #242 --- HISTORY.rst | 2 ++ platformio/__init__.py | 2 +- platformio/builder/tools/piomisc.py | 2 ++ platformio/commands/init.py | 2 +- platformio/ide/projectgenerator.py | 8 ++++++-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 398550c6..dd3dbf73 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -18,6 +18,8 @@ Release History `library.json `__ * Fixed ``stk500v2_command(): command failed`` (`issue #238 `_) +* Fixed IDE project generator when board is specified + (`issue #242 `_) 2.1.2 (2015-06-21) ------------------ diff --git a/platformio/__init__.py b/platformio/__init__.py index cfeb39e7..d69071fd 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 2, "0.dev3") +VERSION = (2, 2, "0.dev4") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 80539c09..0098d63b 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -141,6 +141,8 @@ def DumpIDEData(env): # global symbols for item in env.get("CPPDEFINES", []): + if isinstance(item, list): + item = "=".join(item) data['defines'].append(env.subst(item)) # special symbol for Atmel AVR MCU diff --git a/platformio/commands/init.py b/platformio/commands/init.py index 4799d5fc..3346b635 100644 --- a/platformio/commands/init.py +++ b/platformio/commands/init.py @@ -86,7 +86,7 @@ def cli(project_dir, board, ide, disable_auto_uploading, env_prefix): project_file, board, disable_auto_uploading, env_prefix) if ide: - pg = ProjectGenerator(project_dir, ide) + pg = ProjectGenerator(project_dir, ide, board[0] if board else None) pg.generate() click.secho( diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index c3ee89c9..3ee2b1e9 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -13,9 +13,10 @@ from platformio import util class ProjectGenerator(object): - def __init__(self, project_dir, ide): + def __init__(self, project_dir, ide, board=None): self.project_dir = project_dir self.ide = ide + self.board = board self._tplvars = {} self._gather_tplvars() @@ -26,6 +27,7 @@ class ProjectGenerator(object): return sorted([d for d in listdir(tpls_dir) if isdir(join(tpls_dir, d))]) + @util.memoized def get_project_env(self): data = {"env_name": "PlatformIO"} with util.cd(self.project_dir): @@ -33,9 +35,11 @@ class ProjectGenerator(object): for section in config.sections(): if not section.startswith("env:"): continue - data['env_name'] = section[4:] + data = {"env_name": section[4:]} for k, v in config.items(section): data[k] = v + if self.board and self.board == data.get("board"): + break return data @util.memoized From 53b005bbed306988cc56ec3cac163c75d5828703 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 27 Jun 2015 15:18:51 +0300 Subject: [PATCH 15/37] Simplify installation process for development version --- docs/installation.rst | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 619253e7..26d6460f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -122,18 +122,12 @@ Development Version .. warning:: We don't recommend to use ``develop`` version in production. -1. If you had have already installed PlatformIO, please uninstall it: - -.. code-block:: bash - - $ pip uninstall platformio - -2. Install the latest PlatformIO from the ``develop`` branch: +Install the latest PlatformIO from the ``develop`` branch: .. code-block:: bash $ pip install https://github.com/platformio/platformio/archive/develop.zip If you want to be up-to-date with the latest ``develop`` version of PlatformIO, -then you need to perform step #2 each time if you see the new commits in -`PlatformIO GitHub repository `_. +then you need to re-install PlatformIO each time if you see the new commits in +`PlatformIO GitHub repository (branch: develop) `_. From 31840bbc11aeabb6b9c5bb35a121961a6971bc1a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 27 Jun 2015 17:57:21 +0300 Subject: [PATCH 16/37] Update PlatformIO logo --- docs/_static/platformio-logo.png | Bin 10651 -> 13461 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/_static/platformio-logo.png b/docs/_static/platformio-logo.png index 62bde5cafc90baa676f01b25cb1fd2a79dfb859f..8cbe937ad619a01ebec6b0d8830e5bff2498a7d2 100644 GIT binary patch literal 13461 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 M{de(_a3k8 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 D+CSAO literal 10651 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 Date: Sat, 27 Jun 2015 21:18:33 +0300 Subject: [PATCH 17/37] Fix project generator for Microsoft Visual Studio --- platformio/ide/projectgenerator.py | 12 ++++---- .../platformio.vcxproj.filters.tpl | 28 +++++++++---------- .../tpls/visualstudio/platformio.vcxproj.tpl | 25 +++++++++++------ 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index 3ee2b1e9..c97b8bbd 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -4,7 +4,7 @@ import json from glob import glob from os import listdir, walk -from os.path import basename, isdir, join +from os.path import abspath, basename, expanduser, isdir, join, relpath import bottle @@ -67,12 +67,12 @@ class ProjectGenerator(object): def get_project_name(self): return basename(self.project_dir) - @staticmethod - def get_srcfiles(): + def get_srcfiles(self): result = [] - for root, _, files in walk(util.get_projectsrc_dir()): - for f in files: - result.append(join(root, f)) + with util.cd(self.project_dir): + for root, _, files in walk(util.get_projectsrc_dir()): + for f in files: + result.append(relpath(join(root, f))) return result def get_tpls(self): diff --git a/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl b/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl index 1b4a764e..716218f9 100644 --- a/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl +++ b/platformio/ide/tpls/visualstudio/platformio.vcxproj.filters.tpl @@ -3,27 +3,27 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;ino;pde {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {cad450ef-1a84-42d4-a5b5-a1736b8833d3} - - - - - - Source Files\src - + % for file in srcfiles: + + % if any([file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")]): + + Header Files + + % else: + + Source Files + + %end + + % end diff --git a/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl b/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl index 2b3aa1f9..031cef8d 100644 --- a/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl +++ b/platformio/ide/tpls/visualstudio/platformio.vcxproj.tpl @@ -49,16 +49,23 @@ - - - - - - % for file in srcfiles: - - % end - + + + + % for file in srcfiles: + + % if any([file.endswith(".%s" % e) for e in ("h", "hh", "hpp", "inc")]): + + Header Files + + % else: + + Source Files + + %end + + % end From ae4918bdb7bb5e39b029e2937bad2ad5d7da7902 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 27 Jun 2015 21:20:44 +0300 Subject: [PATCH 18/37] Fix relative path for includes when generating project for IDE // Resolve #243 --- platformio/__init__.py | 2 +- platformio/ide/projectgenerator.py | 1 + platformio/ide/tpls/eclipse/.cproject.tpl | 12 ++++++++++++ platformio/ide/tpls/qtcreator/platformio.pro.tpl | 4 ++++ .../ide/tpls/visualstudio/platformio.vcxproj.tpl | 4 ++-- 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/platformio/__init__.py b/platformio/__init__.py index d69071fd..44e5dbb5 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -1,7 +1,7 @@ # Copyright (C) Ivan Kravets # See LICENSE for details. -VERSION = (2, 2, "0.dev4") +VERSION = (2, 2, "0.dev5") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/ide/projectgenerator.py b/platformio/ide/projectgenerator.py index c97b8bbd..2d6dbcc6 100644 --- a/platformio/ide/projectgenerator.py +++ b/platformio/ide/projectgenerator.py @@ -103,5 +103,6 @@ class ProjectGenerator(object): "defines": (build_data['defines'] if build_data and "defines" in build_data else []), "srcfiles": self.get_srcfiles(), + "user_home_dir": abspath(expanduser("~")), "project_dir": self.project_dir }) diff --git a/platformio/ide/tpls/eclipse/.cproject.tpl b/platformio/ide/tpls/eclipse/.cproject.tpl index ccd645ed..c6f6e077 100644 --- a/platformio/ide/tpls/eclipse/.cproject.tpl +++ b/platformio/ide/tpls/eclipse/.cproject.tpl @@ -24,8 +24,12 @@