Handle specific extra build flags from library.json // Resolve #289

This commit is contained in:
Ivan Kravets
2016-07-15 16:12:07 +03:00
parent 4b622b8603
commit 4997528f6a
7 changed files with 141 additions and 17 deletions

View File

@ -17,6 +17,9 @@ PlatformIO 3.0
C Preprocessor conditional macros, `library deep search <http://docs.platformio.org/en/latest/projectconf.html#lib-deep-search>`__, support for the 3rd party C Preprocessor conditional macros, `library deep search <http://docs.platformio.org/en/latest/projectconf.html#lib-deep-search>`__, support for the 3rd party
manifests (Arduino IDE ``library.properties``, ARM mbed ``module.json``) manifests (Arduino IDE ``library.properties``, ARM mbed ``module.json``)
(`issue #432 <https://github.com/platformio/platformio/issues/432>`_) (`issue #432 <https://github.com/platformio/platformio/issues/432>`_)
* Handle extra build flags and build script from
`library.json <http://docs.platformio.org/en/latest/librarymanager/config.html>`__
(`issue #289 <https://github.com/platformio/platformio/issues/289>`_)
* Show detailed build information about dependent libraries * Show detailed build information about dependent libraries
(`issue #617 <https://github.com/platformio/platformio/issues/617>`_) (`issue #617 <https://github.com/platformio/platformio/issues/617>`_)
* Embedded Board compatibility with more than one development platform * Embedded Board compatibility with more than one development platform

View File

@ -155,12 +155,6 @@ Answered in `issue #144 <https://github.com/platformio/platformio/issues/144#iss
Building Building
~~~~~~~~ ~~~~~~~~
Can not compile a library that compiles without issue with Arduino IDE
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
* `#298: Unable to use Souliss library <https://github.com/platformio/platformio/issues/298>`_
* `#331: Unable to use MySensors library <https://github.com/platformio/platformio/issues/331>`_
ARM toolchain: cc1plus: error while loading shared libraries ARM toolchain: cc1plus: error while loading shared libraries
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

View File

@ -22,6 +22,7 @@ to keep project in own structure and define:
* examples list * examples list
* compatible frameworks and platforms * compatible frameworks and platforms
* library dependencies * library dependencies
* advanced build settings
PlatformIO Library Crawler uses ``library.json`` manifest to extract PlatformIO Library Crawler uses ``library.json`` manifest to extract
source code from developer's location and keeps cleaned library in own source code from developer's location and keeps cleaned library in own
@ -397,7 +398,7 @@ See more ``library.json`` :ref:`library_creating_examples`.
.. _libjson_examples: .. _libjson_examples:
``examples`` ``examples``
---------------- ------------
*Optional* | Type: ``String`` or ``Array`` | *Optional* | Type: ``String`` or ``Array`` |
`Glob Pattern <http://en.wikipedia.org/wiki/Glob_(programming)>`_ `Glob Pattern <http://en.wikipedia.org/wiki/Glob_(programming)>`_
@ -413,3 +414,80 @@ A list of example patterns. This field is predefined with default value:
"[Ee]xamples/*/*.ino", "[Ee]xamples/*/*.ino",
"[Ee]xamples/*/*.pde" "[Ee]xamples/*/*.pde"
] ]
.. _libjson_build:
``build``
------------
*Optional* | Type: ``Object``
Specify advanced settings, options and flags for the build system. Possible
options:
* ``flags`` - extra flags to control preprocessing, compilation, assembly and
linking processes. More details :ref:`projectconf_build_flags`
* ``unflags`` - remove base/initial flags which were set by development
platform. More details :ref:`projectconf_build_unflags`
* ``srcFilter`` - specify which source files should be included/excluded
from build process. More details :ref:`projectconf_src_filter`
* ``extraScript`` - launch extra script before build process.
More details :ref:`projectconf_extra_script`.
**Examples**
1. Custom macros/defines
.. code-block:: javascript
"build": {
"flags": "-D MYLIB_REV=0.1.2 -DRELEASE"
}
2. Extra includes for C preprocessor
.. code-block:: javascript
"build": {
"flags": "-I inc -I inc/target_x13"
}
3. Force to use ``C99`` standard instead ``C11``
.. code-block:: javascript
"build": {
"unflags": "-std=gnu++11",
"flags": "-std=c99"
}
4. Build source files (``c, cpp, h``) only from the root of the library
.. code-block:: javascript
"build": {
"srcFilter": [
"+<*.c>",
"+<*.cpp>",
"+<*.h>"
]
}
5. Extend PlatformIO Build System with own extra script
.. code-block:: javascript
"build": {
"extraScript": "generate_headers.py"
}
``generate_headers.py``
.. code-block:: python
# Import('env')
# print env.Dump()
# some python code that generates headers files "on-the-fly"

View File

@ -422,6 +422,8 @@ but will be applied only for the project source code from
This option can be set by global environment variable This option can be set by global environment variable
:envvar:`PLATFORMIO_SRC_BUILD_FLAGS`. :envvar:`PLATFORMIO_SRC_BUILD_FLAGS`.
.. _projectconf_build_unflags:
``build_unflags`` ``build_unflags``
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

View File

@ -14,7 +14,7 @@
import sys import sys
VERSION = (3, 0, "0.dev4") VERSION = (3, 0, "0.dev5")
__version__ = ".".join([str(s) for s in VERSION]) __version__ = ".".join([str(s) for s in VERSION])
__title__ = "platformio" __title__ = "platformio"

View File

@ -17,7 +17,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import os import os
from os.path import basename, commonprefix, isdir, isfile, join from os.path import basename, commonprefix, isdir, isfile, join, realpath
from sys import modules from sys import modules
import SCons.Scanner import SCons.Scanner
@ -73,7 +73,7 @@ class LibBuilderFactory(object):
class LibBuilderBase(object): class LibBuilderBase(object):
def __init__(self, env, path): def __init__(self, env, path):
self.env = env.Clone() self.env = env
self.path = path self.path = path
self._is_built = False self._is_built = False
self._manifest = self.load_manifest() self._manifest = self.load_manifest()
@ -108,6 +108,18 @@ class LibBuilderBase(object):
def build_dir(self): def build_dir(self):
return join("$BUILD_DIR", "lib", self.name) return join("$BUILD_DIR", "lib", self.name)
@property
def build_flags(self):
return None
@property
def build_unflags(self):
return None
@property
def extra_script(self):
return None
@property @property
def is_built(self): def is_built(self):
return self._is_built return self._is_built
@ -118,8 +130,8 @@ class LibBuilderBase(object):
def get_path_dirs(self, use_build_dir=False): def get_path_dirs(self, use_build_dir=False):
return [self.build_dir if use_build_dir else self.src_dir] return [self.build_dir if use_build_dir else self.src_dir]
def append_to_cpppath(self, env): def append_to_cpppath(self):
env.AppendUnique( self.env.AppendUnique(
CPPPATH=self.get_path_dirs(use_build_dir=True) CPPPATH=self.get_path_dirs(use_build_dir=True)
) )
@ -130,8 +142,20 @@ class LibBuilderBase(object):
print "Depends on <%s>" % self.name print "Depends on <%s>" % self.name
assert self._is_built is False assert self._is_built is False
self._is_built = True self._is_built = True
return self.env.BuildLibrary( self.append_to_cpppath()
self.build_dir, self.src_dir, self.src_filter)
env = self.env.Clone()
with util.cd(self.path):
env.ProcessUnFlags(self.build_unflags)
env.ProcessFlags(self.build_flags)
if self.extra_script:
env.SConscript(realpath(self.extra_script), exports="env")
# copy some data to global env
for key in ("CPPPATH", "LIBPATH", "LIBS", "LINKFLAGS"):
self.env.AppendUnique(**{key: env.get(key)})
return env.BuildLibrary(self.build_dir, self.src_dir, self.src_filter)
class UnknownLibBuilder(LibBuilderBase): class UnknownLibBuilder(LibBuilderBase):
@ -199,6 +223,30 @@ class PlatformIOLibBuilder(LibBuilderBase):
assert "name" in manifest assert "name" in manifest
return manifest return manifest
@property
def src_filter(self):
if "srcFilter" in self._manifest.get("build", {}):
return self._manifest.get("build").get("srcFilter")
return LibBuilderBase.src_filter.fget(self)
@property
def build_flags(self):
if "flags" in self._manifest.get("build", {}):
return self._manifest.get("build").get("flags")
return LibBuilderBase.build_flags.fget(self)
@property
def build_unflags(self):
if "unflags" in self._manifest.get("build", {}):
return self._manifest.get("build").get("unflags")
return LibBuilderBase.build_unflags.fget(self)
@property
def extra_script(self):
if "extra_script" in self._manifest.get("build", {}):
return self._manifest.get("build").get("extra_script")
return LibBuilderBase.extra_script.fget(self)
def find_deps(env, scanner, path_dirs, src_dir, src_filter): def find_deps(env, scanner, path_dirs, src_dir, src_filter):
result = [] result = []
@ -232,7 +280,7 @@ def find_and_build_deps(env, lib_builders, scanner,
libs = [] libs = []
# append PATH directories to global CPPPATH before build starts # append PATH directories to global CPPPATH before build starts
for lb in target_lbs: for lb in target_lbs:
lb.append_to_cpppath(env) lb.append_to_cpppath()
# start builder # start builder
for lb in target_lbs: for lb in target_lbs:
libs.append(lb.build()) libs.append(lb.build())
@ -277,7 +325,6 @@ def BuildDependentLibraries(env, src_dir):
libs.extend(find_and_build_deps( libs.extend(find_and_build_deps(
env, lib_builders, scanner, lb.src_dir, lb.src_filter)) env, lib_builders, scanner, lb.src_dir, lb.src_filter))
if not lb.is_built: if not lb.is_built:
lb.append_to_cpppath(env)
libs.append(lb.build()) libs.append(lb.build())
# process project source code # process project source code

View File

@ -154,7 +154,7 @@ def ProcessUnFlags(env, flags):
all_flags = set(all_flags) all_flags = set(all_flags)
for key in parsed_flags: for key in parsed_flags:
cur_flags = set(env.get(key, [])) cur_flags = set(env.Flatten(env.get(key, [])))
for item in cur_flags & all_flags: for item in cur_flags & all_flags:
while item in env[key]: while item in env[key]:
env[key].remove(item) env[key].remove(item)