mirror of https://github.com/ARMmbed/mbed-os.git
Update project generator script to allow working with any source
Update test exporters script Update travis build script Added config system CLI script Fixed building of legacy libraries and layoutspull/1893/head
parent
c2e3001739
commit
9f62d70fbf
|
@ -192,7 +192,7 @@ if __name__ == '__main__':
|
|||
if options.usb_host:
|
||||
libraries.append("usb_host")
|
||||
if options.dsp:
|
||||
libraries.extend(["cmsis_dsp", "dsp"])
|
||||
libraries.extend(["dsp"])
|
||||
if options.fat:
|
||||
libraries.extend(["fat"])
|
||||
if options.ublox:
|
||||
|
|
|
@ -394,33 +394,145 @@ def build_library(src_paths, build_path, target, toolchain_name,
|
|||
# Let Exception propagate
|
||||
raise e
|
||||
|
||||
def build_lib(lib_id, target, toolchain, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
|
||||
""" Wrapper for build_library function.
|
||||
######################
|
||||
### Legacy methods ###
|
||||
######################
|
||||
|
||||
def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
|
||||
""" Legacy method for building mbed libraries
|
||||
Function builds library in proper directory using all dependencies and macros defined by user.
|
||||
"""
|
||||
lib = Library(lib_id)
|
||||
if lib.is_supported(target, toolchain):
|
||||
# We need to combine macros from parameter list with macros from library definition
|
||||
MACROS = lib.macros if lib.macros else []
|
||||
if macros:
|
||||
MACROS.extend(macros)
|
||||
|
||||
return build_library(lib.source_dir, lib.build_dir, target, toolchain, lib.dependencies, options,
|
||||
verbose=verbose,
|
||||
silent=silent,
|
||||
clean=clean,
|
||||
macros=MACROS,
|
||||
notify=notify,
|
||||
inc_dirs=lib.inc_dirs,
|
||||
inc_dirs_ext=lib.inc_dirs_ext,
|
||||
jobs=jobs,
|
||||
report=report,
|
||||
properties=properties,
|
||||
extra_verbose=extra_verbose)
|
||||
else:
|
||||
if not lib.is_supported(target, toolchain_name):
|
||||
print 'Library "%s" is not yet supported on target %s with toolchain %s' % (lib_id, target.name, toolchain)
|
||||
return False
|
||||
|
||||
# We need to combine macros from parameter list with macros from library definition
|
||||
MACROS = lib.macros if lib.macros else []
|
||||
if macros:
|
||||
macros.extend(MACROS)
|
||||
else:
|
||||
macros = MACROS
|
||||
|
||||
src_paths = lib.source_dir
|
||||
build_path = lib.build_dir
|
||||
dependencies_paths = lib.dependencies
|
||||
inc_dirs = lib.inc_dirs
|
||||
inc_dirs_ext = lib.inc_dirs_ext
|
||||
|
||||
""" src_path: the path of the source directory
|
||||
build_path: the path of the build directory
|
||||
target: ['LPC1768', 'LPC11U24', 'LPC2368']
|
||||
toolchain: ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
|
||||
library_paths: List of paths to additional libraries
|
||||
clean: Rebuild everything if True
|
||||
notify: Notify function for logs
|
||||
verbose: Write the actual tools command lines if True
|
||||
inc_dirs: additional include directories which should be included in build
|
||||
inc_dirs_ext: additional include directories which should be copied to library directory
|
||||
"""
|
||||
if type(src_paths) != ListType:
|
||||
src_paths = [src_paths]
|
||||
|
||||
# The first path will give the name to the library
|
||||
name = basename(src_paths[0])
|
||||
|
||||
if report != None:
|
||||
start = time()
|
||||
id_name = name.upper()
|
||||
description = name
|
||||
vendor_label = target.extra_labels[0]
|
||||
cur_result = None
|
||||
prep_report(report, target.name, toolchain_name, id_name)
|
||||
cur_result = create_result(target.name, toolchain_name, id_name, description)
|
||||
|
||||
if properties != None:
|
||||
prep_properties(properties, target.name, toolchain_name, vendor_label)
|
||||
|
||||
for src_path in src_paths:
|
||||
if not exists(src_path):
|
||||
error_msg = "The library source folder does not exist: %s", src_path
|
||||
|
||||
if report != None:
|
||||
cur_result["output"] = error_msg
|
||||
cur_result["result"] = "FAIL"
|
||||
add_result_to_report(report, cur_result)
|
||||
|
||||
raise Exception(error_msg)
|
||||
|
||||
try:
|
||||
# Toolchain instance
|
||||
toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
|
||||
toolchain.VERBOSE = verbose
|
||||
toolchain.jobs = jobs
|
||||
toolchain.build_all = clean
|
||||
|
||||
toolchain.info("Building library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
|
||||
|
||||
# Scan Resources
|
||||
resources = []
|
||||
for src_path in src_paths:
|
||||
resources.append(toolchain.scan_resources(src_path))
|
||||
|
||||
# Add extra include directories / files which are required by library
|
||||
# This files usually are not in the same directory as source files so
|
||||
# previous scan will not include them
|
||||
if inc_dirs_ext is not None:
|
||||
for inc_ext in inc_dirs_ext:
|
||||
resources.append(toolchain.scan_resources(inc_ext))
|
||||
|
||||
# Dependencies Include Paths
|
||||
dependencies_include_dir = []
|
||||
if dependencies_paths is not None:
|
||||
for path in dependencies_paths:
|
||||
lib_resources = toolchain.scan_resources(path)
|
||||
dependencies_include_dir.extend(lib_resources.inc_dirs)
|
||||
|
||||
if inc_dirs:
|
||||
dependencies_include_dir.extend(inc_dirs)
|
||||
|
||||
# Create the desired build directory structure
|
||||
bin_path = join(build_path, toolchain.obj_path)
|
||||
mkdir(bin_path)
|
||||
tmp_path = join(build_path, '.temp', toolchain.obj_path)
|
||||
mkdir(tmp_path)
|
||||
|
||||
# Copy Headers
|
||||
for resource in resources:
|
||||
toolchain.copy_files(resource.headers, build_path, rel_path=resource.base_path)
|
||||
dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
|
||||
|
||||
# Compile Sources
|
||||
objects = []
|
||||
for resource in resources:
|
||||
objects.extend(toolchain.compile_sources(resource, tmp_path, dependencies_include_dir))
|
||||
|
||||
needed_update = toolchain.build_library(objects, bin_path, name)
|
||||
|
||||
if report != None and needed_update:
|
||||
end = time()
|
||||
cur_result["elapsed_time"] = end - start
|
||||
cur_result["output"] = toolchain.get_output()
|
||||
cur_result["result"] = "OK"
|
||||
|
||||
add_result_to_report(report, cur_result)
|
||||
|
||||
except Exception, e:
|
||||
if report != None:
|
||||
end = time()
|
||||
cur_result["result"] = "FAIL"
|
||||
cur_result["elapsed_time"] = end - start
|
||||
|
||||
toolchain_output = toolchain.get_output()
|
||||
if toolchain_output:
|
||||
cur_result["output"] += toolchain_output
|
||||
|
||||
cur_result["output"] += str(e)
|
||||
|
||||
add_result_to_report(report, cur_result)
|
||||
|
||||
# Let Exception propagate
|
||||
raise e
|
||||
|
||||
# We do have unique legacy conventions about how we build and package the mbed library
|
||||
def build_mbed_libs(target, toolchain_name, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
|
||||
|
@ -543,6 +655,7 @@ def build_mbed_libs(target, toolchain_name, options=None, verbose=False, clean=F
|
|||
# Let Exception propagate
|
||||
raise e
|
||||
|
||||
|
||||
def get_unique_supported_toolchains():
|
||||
""" Get list of all unique toolchains supported by targets """
|
||||
unique_supported_toolchains = []
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
#! /usr/bin/env python2
|
||||
"""
|
||||
mbed SDK
|
||||
Copyright (c) 2011-2013 ARM Limited
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
import sys
|
||||
from os.path import isdir, abspath, dirname, join
|
||||
from os import _exit
|
||||
|
||||
# Be sure that the tools directory is in the search path
|
||||
ROOT = abspath(join(dirname(__file__), ".."))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.utils import args_error
|
||||
from tools.options import get_default_options_parser
|
||||
from tools.build_api import get_config
|
||||
from config import Config
|
||||
try:
|
||||
import tools.private_settings as ps
|
||||
except:
|
||||
ps = object()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Parse Options
|
||||
parser = get_default_options_parser(add_clean=False, add_options=False)
|
||||
parser.add_option("--source", dest="source_dir",
|
||||
default=None, help="The source (input) directory", action="append")
|
||||
parser.add_option("--prefix", dest="prefix", action="append",
|
||||
default=None, help="Restrict listing to parameters that have this prefix")
|
||||
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
|
||||
default=False, help="Verbose diagnostic output")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
for path in options.source_dir :
|
||||
if not isdir(path) :
|
||||
args_error(parser, "[ERROR] you passed \"{}\" to --source, which does not exist".
|
||||
format(path))
|
||||
# Target
|
||||
if options.mcu is None :
|
||||
args_error(parser, "[ERROR] You should specify an MCU")
|
||||
target = options.mcu
|
||||
|
||||
# Toolchain
|
||||
if options.tool is None:
|
||||
args_error(parser, "[ERROR] You should specify a TOOLCHAIN")
|
||||
toolchain = options.tool
|
||||
|
||||
options.prefix = options.prefix or [""]
|
||||
|
||||
try:
|
||||
params, macros = get_config(options.source_dir, target, toolchain)
|
||||
if not params and not macros:
|
||||
print "No configuration data available."
|
||||
_exit(0)
|
||||
if params:
|
||||
print "Configuration parameters"
|
||||
print "------------------------"
|
||||
for p in params:
|
||||
for s in options.prefix:
|
||||
if p.startswith(s):
|
||||
print(str(params[p]) if not options.verbose else params[p].get_verbose_description())
|
||||
break
|
||||
print ""
|
||||
|
||||
print "Macros"
|
||||
print "------"
|
||||
if macros:
|
||||
print 'Defined with "macros":', macros
|
||||
print "Generated from configuration parameters:", Config.parameters_to_macros(params)
|
||||
|
||||
except KeyboardInterrupt, e:
|
||||
print "\n[CTRL+c] exit"
|
||||
except Exception,e:
|
||||
if options.verbose:
|
||||
import traceback
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
else:
|
||||
print "[ERROR] %s" % str(e)
|
||||
|
||||
sys.exit(1)
|
|
@ -59,17 +59,11 @@ LIBRARIES = [
|
|||
},
|
||||
|
||||
# DSP libraries
|
||||
{
|
||||
"id": "cmsis_dsp",
|
||||
"source_dir": DSP_CMSIS,
|
||||
"build_dir": DSP_LIBRARIES,
|
||||
"dependencies": [MBED_LIBRARIES],
|
||||
},
|
||||
{
|
||||
"id": "dsp",
|
||||
"source_dir": DSP_ABSTRACTION,
|
||||
"source_dir": [DSP_ABSTRACTION, DSP_CMSIS],
|
||||
"build_dir": DSP_LIBRARIES,
|
||||
"dependencies": [MBED_LIBRARIES, DSP_CMSIS],
|
||||
"dependencies": [MBED_LIBRARIES]
|
||||
},
|
||||
|
||||
# File system libraries
|
||||
|
|
131
tools/project.py
131
tools/project.py
|
@ -1,21 +1,22 @@
|
|||
import sys
|
||||
from os.path import join, abspath, dirname, exists
|
||||
from os.path import join, abspath, dirname, exists, basename
|
||||
ROOT = abspath(join(dirname(__file__), ".."))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from shutil import move, rmtree
|
||||
from optparse import OptionParser
|
||||
from os import path
|
||||
|
||||
from tools.paths import EXPORT_DIR, EXPORT_WORKSPACE, EXPORT_TMP
|
||||
from tools.paths import MBED_BASE, MBED_LIBRARIES
|
||||
from tools.export import export, setup_user_prj, EXPORTERS, mcu_ide_matrix
|
||||
from tools.utils import args_error
|
||||
from tools.utils import args_error, mkdir
|
||||
from tools.tests import TESTS, Test, TEST_MAP
|
||||
from tools.targets import TARGET_NAMES
|
||||
from tools.libraries import LIBRARIES
|
||||
|
||||
try:
|
||||
import mbed_settings as ps
|
||||
import tools.private_settings as ps
|
||||
except:
|
||||
ps = object()
|
||||
|
||||
|
@ -77,6 +78,17 @@ if __name__ == '__main__':
|
|||
default=False,
|
||||
help="writes tools/export/README.md")
|
||||
|
||||
parser.add_option("--source",
|
||||
action="append",
|
||||
dest="source_dir",
|
||||
default=None,
|
||||
help="The source (input) directory")
|
||||
|
||||
parser.add_option("-D", "",
|
||||
action="append",
|
||||
dest="macros",
|
||||
help="Add a macro definition")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
# Print available tests in order and exit
|
||||
|
@ -123,63 +135,86 @@ if __name__ == '__main__':
|
|||
# Export results
|
||||
successes = []
|
||||
failures = []
|
||||
zip = True
|
||||
clean = True
|
||||
|
||||
# source_dir = use relative paths, otherwise sources are copied
|
||||
sources_relative = True if options.source_dir else False
|
||||
|
||||
for mcu in mcus.split(','):
|
||||
# Program Number or name
|
||||
p, n = options.program, options.program_name
|
||||
p, n, src, ide = options.program, options.program_name, options.source_dir, options.ide
|
||||
|
||||
if n is not None and p is not None:
|
||||
args_error(parser, "[ERROR] specify either '-n' or '-p', not both")
|
||||
if n:
|
||||
if not n in TEST_MAP.keys():
|
||||
# Check if there is an alias for this in mbed_settings.py
|
||||
if getattr(ps, "test_alias", None) is not None:
|
||||
alias = ps.test_alias.get(n, "")
|
||||
if not alias in TEST_MAP.keys():
|
||||
args_error(parser, "[ERROR] Program with name '%s' not found" % n)
|
||||
if src is not None:
|
||||
# --source is used to generate IDE files to toolchain directly in the source tree and doesn't generate zip file
|
||||
project_dir = options.source_dir
|
||||
project_name = n if n else "Unnamed_Project"
|
||||
project_temp = path.join(options.source_dir[0], 'projectfiles', ide)
|
||||
mkdir(project_temp)
|
||||
lib_symbols = []
|
||||
if options.macros:
|
||||
lib_symbols += options.macros
|
||||
zip = False # don't create zip
|
||||
clean = False # don't cleanup because we use the actual source tree to generate IDE files
|
||||
else:
|
||||
if n is not None and p is not None:
|
||||
args_error(parser, "[ERROR] specify either '-n' or '-p', not both")
|
||||
if n:
|
||||
if not n in TEST_MAP.keys():
|
||||
# Check if there is an alias for this in private_settings.py
|
||||
if getattr(ps, "test_alias", None) is not None:
|
||||
alias = ps.test_alias.get(n, "")
|
||||
if not alias in TEST_MAP.keys():
|
||||
args_error(parser, "[ERROR] Program with name '%s' not found" % n)
|
||||
else:
|
||||
n = alias
|
||||
else:
|
||||
n = alias
|
||||
else:
|
||||
args_error(parser, "[ERROR] Program with name '%s' not found" % n)
|
||||
p = TEST_MAP[n].n
|
||||
if p is None or (p < 0) or (p > (len(TESTS)-1)):
|
||||
message = "[ERROR] You have to specify one of the following tests:\n"
|
||||
message += '\n'.join(map(str, sorted(TEST_MAP.values())))
|
||||
args_error(parser, message)
|
||||
args_error(parser, "[ERROR] Program with name '%s' not found" % n)
|
||||
p = TEST_MAP[n].n
|
||||
|
||||
if p is None or (p < 0) or (p > (len(TESTS)-1)):
|
||||
message = "[ERROR] You have to specify one of the following tests:\n"
|
||||
message += '\n'.join(map(str, sorted(TEST_MAP.values())))
|
||||
args_error(parser, message)
|
||||
|
||||
# Project
|
||||
if p is None or (p < 0) or (p > (len(TESTS)-1)):
|
||||
message = "[ERROR] You have to specify one of the following tests:\n"
|
||||
message += '\n'.join(map(str, sorted(TEST_MAP.values())))
|
||||
args_error(parser, message)
|
||||
test = Test(p)
|
||||
# Project
|
||||
if p is None or (p < 0) or (p > (len(TESTS)-1)):
|
||||
message = "[ERROR] You have to specify one of the following tests:\n"
|
||||
message += '\n'.join(map(str, sorted(TEST_MAP.values())))
|
||||
args_error(parser, message)
|
||||
test = Test(p)
|
||||
|
||||
# Some libraries have extra macros (called by exporter symbols) to we need to pass
|
||||
# them to maintain compilation macros integrity between compiled library and
|
||||
# header files we might use with it
|
||||
lib_symbols = []
|
||||
for lib in LIBRARIES:
|
||||
if lib['build_dir'] in test.dependencies:
|
||||
lib_macros = lib.get('macros', None)
|
||||
if lib_macros is not None:
|
||||
lib_symbols.extend(lib_macros)
|
||||
# Some libraries have extra macros (called by exporter symbols) to we need to pass
|
||||
# them to maintain compilation macros integrity between compiled library and
|
||||
# header files we might use with it
|
||||
lib_symbols = []
|
||||
if options.macros:
|
||||
lib_symbols += options.macros
|
||||
for lib in LIBRARIES:
|
||||
if lib['build_dir'] in test.dependencies:
|
||||
lib_macros = lib.get('macros', None)
|
||||
if lib_macros is not None:
|
||||
lib_symbols.extend(lib_macros)
|
||||
|
||||
if not options.build:
|
||||
# Substitute the library builds with the sources
|
||||
# TODO: Substitute also the other library build paths
|
||||
if MBED_LIBRARIES in test.dependencies:
|
||||
test.dependencies.remove(MBED_LIBRARIES)
|
||||
test.dependencies.append(MBED_BASE)
|
||||
if not options.build:
|
||||
# Substitute the library builds with the sources
|
||||
# TODO: Substitute also the other library build paths
|
||||
if MBED_LIBRARIES in test.dependencies:
|
||||
test.dependencies.remove(MBED_LIBRARIES)
|
||||
test.dependencies.append(MBED_BASE)
|
||||
|
||||
# Build the project with the same directory structure of the mbed online IDE
|
||||
project_dir = join(EXPORT_WORKSPACE, test.id)
|
||||
setup_user_prj(project_dir, test.source_dir, test.dependencies)
|
||||
# Build the project with the same directory structure of the mbed online IDE
|
||||
project_name = test.id
|
||||
project_dir = join(EXPORT_WORKSPACE, project_name)
|
||||
project_temp = EXPORT_TMP
|
||||
setup_user_prj(project_dir, test.source_dir, test.dependencies)
|
||||
|
||||
# Export to selected toolchain
|
||||
tmp_path, report = export(project_dir, test.id, ide, mcu, EXPORT_WORKSPACE, EXPORT_TMP, extra_symbols=lib_symbols)
|
||||
tmp_path, report = export(project_dir, project_name, ide, mcu, project_dir, project_temp, clean=clean, zip=zip, extra_symbols=lib_symbols, relative=sources_relative)
|
||||
if report['success']:
|
||||
zip_path = join(EXPORT_DIR, "%s_%s_%s.zip" % (test.id, ide, mcu))
|
||||
move(tmp_path, zip_path)
|
||||
zip_path = join(EXPORT_DIR, "%s_%s_%s.zip" % (project_name, ide, mcu))
|
||||
if zip:
|
||||
move(tmp_path, zip_path)
|
||||
successes.append("%s::%s\t%s"% (mcu, ide, zip_path))
|
||||
else:
|
||||
failures.append("%s::%s\t%s"% (mcu, ide, report['errormsg']))
|
||||
|
|
|
@ -17,7 +17,8 @@ limitations under the License.
|
|||
Author: Przemyslaw Wirkus <Przemyslaw.wirkus@arm.com>
|
||||
"""
|
||||
|
||||
from tools.utils import construct_enum
|
||||
from tools.utils import construct_enum, mkdir
|
||||
import os
|
||||
|
||||
|
||||
ResultExporterType = construct_enum(HTML='Html_Exporter',
|
||||
|
@ -97,6 +98,9 @@ class ReportExporter():
|
|||
|
||||
def write_to_file(self, report, file_name):
|
||||
if report is not None:
|
||||
dirname = os.path.dirname(file_name)
|
||||
if dirname:
|
||||
mkdir(dirname)
|
||||
with open(file_name, 'w') as f:
|
||||
f.write(report)
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ class IAR(mbedToolchain):
|
|||
|
||||
IAR_BIN = join(IAR_PATH, "bin")
|
||||
main_cc = join(IAR_BIN, "iccarm")
|
||||
if target.core == "Cortex-M7F":
|
||||
|
||||
if target.core == "Cortex-M7F":
|
||||
self.asm = [join(IAR_BIN, "iasmarm")] + ["--cpu", cpuchoice] + ["--fpu", "VFPv5_sp"]
|
||||
else:
|
||||
self.asm = [join(IAR_BIN, "iasmarm")] + ["--cpu", cpuchoice]
|
||||
|
|
Loading…
Reference in New Issue