mbed-os/workspace_tools/build_api.py

144 lines
5.0 KiB
Python
Raw Normal View History

from os.path import join, exists, basename
from shutil import copyfile, rmtree
from copy import copy
import json
from types import ListType
from workspace_tools.utils import mkdir
from workspace_tools.toolchains import TOOLCHAIN_CLASSES, Resources
"""
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_CS', '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
"""
def build_library(src_paths, build_path, target, toolchain_name,
libraries_paths=None, name=None, clean=False, notify=None, verbose=False):
if type(src_paths) != ListType: src_paths = [src_paths]
for src_path in src_paths:
if not exists(src_path):
raise Exception("The library source folder does not exist: %s", src_path)
# Toolchain instance
toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, notify)
toolchain.VERBOSE = verbose
toolchain.build_all = clean
# Options
# By convention the first path should contain the build configuration
main_src = src_paths[0]
options_file = join(main_src, 'options.json')
if exists(options_file):
try:
options = json.load(open(options_file))
except Exception, e:
raise Exception("Error parsing option file: %s\n\t%s" % (options_file, e))
else:
options = {}
toolchain.set_options(options)
# Library name can be set by: function parameter, option file, or directory name (in that order)
if name is None:
if 'lib_name' in options:
name = options['lib_name']
else:
name = basename(main_src)
toolchain.info("\n>>> BUILD 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))
# Just for the include paths
lib_resources = Resources()
if libraries_paths is not None:
for path in libraries_paths:
lib_resources.add(toolchain.scan_resources(path))
# 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 Files
for resource in resources:
files_to_be_copied = resource.headers
if resource.linker_script is not None:
# Linker script
files_to_be_copied.append(resource.linker_script)
toolchain.copy_files(resource.base_path, build_path, files_to_be_copied)
# Compile sources
objects = []
for resource in resources:
objects.extend(toolchain.compile_sources(resource, tmp_path, lib_resources.inc_dirs))
# Same objects need to remain stand alone
if 'objects' in options:
for object in copy(objects):
filename = basename(object)
if filename in options['objects']:
objects.remove(object)
target = join(bin_path, filename)
if toolchain.need_update(target, [object]):
toolchain.info("Copy: %s" % filename)
copyfile(object, target)
# Archive objects in a library
if objects:
toolchain.build_library(objects, bin_path, name)
def build_project(src_path, build_path, target, toolchain_name,
libraries_paths=None, clean=False, notify=None, verbose=False, name=None):
# Toolchain instance
toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, notify)
toolchain.VERBOSE = verbose
toolchain.build_all = clean
if name is None:
name = basename(src_path)
toolchain.info("\n>>> BUILD PROJECT: %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
# Scan src_path and libraries_paths for resources
resources = toolchain.scan_resources(src_path)
if libraries_paths is not None:
for path in libraries_paths:
resources.add(toolchain.scan_resources(path))
# Build Directory
if clean:
if exists(build_path):
rmtree(build_path)
mkdir(build_path)
# Build Program
return toolchain.build_program(resources, build_path, name)
# Core mbed libraries
from workspace_tools.libraries import Library
def build_lib(lib_id, target, toolchain, verbose=False):
lib = Library(lib_id)
if lib.is_supported(target, toolchain):
build_library(lib.source_dir, lib.build_dir, target, toolchain, lib.dependencies, lib.name, verbose=verbose)
else:
print '\n\nLibrary "%s" is not yet supported on target %s with toolchain %s' % (lib_id, target.name, toolchain)
def build_mbed_libs(target, toolchain, verbose=False):
for lib_name in ["%s_cmsis" % target.vendor, "%s_mbed" % target.vendor]:
build_lib(lib_name, target, toolchain, verbose=verbose)