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
manifests (Arduino IDE ``library.properties``, ARM mbed ``module.json``)
(`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
(`issue #617 <https://github.com/platformio/platformio/issues/617>`_)
* 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
~~~~~~~~
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
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

View File

@ -22,6 +22,7 @@ to keep project in own structure and define:
* examples list
* compatible frameworks and platforms
* library dependencies
* advanced build settings
PlatformIO Library Crawler uses ``library.json`` manifest to extract
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:
``examples``
----------------
------------
*Optional* | Type: ``String`` or ``Array`` |
`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/*/*.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
:envvar:`PLATFORMIO_SRC_BUILD_FLAGS`.
.. _projectconf_build_unflags:
``build_unflags``
^^^^^^^^^^^^^^^^^

View File

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

View File

@ -17,7 +17,7 @@
from __future__ import absolute_import
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
import SCons.Scanner
@ -73,7 +73,7 @@ class LibBuilderFactory(object):
class LibBuilderBase(object):
def __init__(self, env, path):
self.env = env.Clone()
self.env = env
self.path = path
self._is_built = False
self._manifest = self.load_manifest()
@ -108,6 +108,18 @@ class LibBuilderBase(object):
def build_dir(self):
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
def is_built(self):
return self._is_built
@ -118,8 +130,8 @@ class LibBuilderBase(object):
def get_path_dirs(self, use_build_dir=False):
return [self.build_dir if use_build_dir else self.src_dir]
def append_to_cpppath(self, env):
env.AppendUnique(
def append_to_cpppath(self):
self.env.AppendUnique(
CPPPATH=self.get_path_dirs(use_build_dir=True)
)
@ -130,8 +142,20 @@ class LibBuilderBase(object):
print "Depends on <%s>" % self.name
assert self._is_built is False
self._is_built = True
return self.env.BuildLibrary(
self.build_dir, self.src_dir, self.src_filter)
self.append_to_cpppath()
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):
@ -199,6 +223,30 @@ class PlatformIOLibBuilder(LibBuilderBase):
assert "name" in 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):
result = []
@ -232,7 +280,7 @@ def find_and_build_deps(env, lib_builders, scanner,
libs = []
# append PATH directories to global CPPPATH before build starts
for lb in target_lbs:
lb.append_to_cpppath(env)
lb.append_to_cpppath()
# start builder
for lb in target_lbs:
libs.append(lb.build())
@ -277,7 +325,6 @@ def BuildDependentLibraries(env, src_dir):
libs.extend(find_and_build_deps(
env, lib_builders, scanner, lb.src_dir, lb.src_filter))
if not lb.is_built:
lb.append_to_cpppath(env)
libs.append(lb.build())
# process project source code

View File

@ -154,7 +154,7 @@ def ProcessUnFlags(env, flags):
all_flags = set(all_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:
while item in env[key]:
env[key].remove(item)