mbed-os/workspace_tools/build_api.py

144 lines
5.0 KiB
Python

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)