Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers __init__.py Source File

__init__.py

00001 """
00002 mbed SDK
00003 Copyright (c) 2011-2016 ARM Limited
00004 
00005 Licensed under the Apache License, Version 2.0 (the "License");
00006 you may not use this file except in compliance with the License.
00007 You may obtain a copy of the License at
00008 
00009     http://www.apache.org/licenses/LICENSE-2.0
00010 
00011 Unless required by applicable law or agreed to in writing, software
00012 distributed under the License is distributed on an "AS IS" BASIS,
00013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014 See the License for the specific language governing permissions and
00015 limitations under the License.
00016 """
00017 from __future__ import print_function, absolute_import
00018 from builtins import str
00019 
00020 from os.path import splitext, basename, relpath, join, abspath, dirname,\
00021     exists
00022 from os import remove
00023 import sys
00024 from subprocess import check_output, CalledProcessError, Popen, PIPE
00025 import shutil
00026 from jinja2.exceptions import TemplateNotFound
00027 from tools.export.exporters import Exporter, apply_supported_whitelist
00028 from tools.utils import NotSupportedException
00029 from tools.targets import TARGET_MAP
00030 
00031 
00032 class Makefile (Exporter ):
00033     """Generic Makefile template that mimics the behavior of the python build
00034     system
00035     """
00036 
00037     DOT_IN_RELATIVE_PATH = True
00038 
00039     MBED_CONFIG_HEADER_SUPPORTED = True
00040 
00041     PREPROCESS_ASM = False
00042 
00043     POST_BINARY_WHITELIST = set([
00044         "MCU_NRF51Code.binary_hook",
00045         "TEENSY3_1Code.binary_hook",
00046         "LPCTargetCode.lpc_patch",
00047         "LPC4088Code.binary_hook"
00048     ])
00049 
00050     @classmethod
00051     def is_target_supported (cls, target_name):
00052         target = TARGET_MAP[target_name]
00053         return apply_supported_whitelist(
00054             cls.TOOLCHAIN, cls.POST_BINARY_WHITELIST, target)
00055 
00056     def generate (self):
00057         """Generate the makefile
00058 
00059         Note: subclasses should not need to override this method
00060         """
00061         if not self.resources.linker_script:
00062             raise NotSupportedException("No linker script found.")
00063 
00064         self.resources.win_to_unix()
00065 
00066         to_be_compiled = [splitext(src)[0] + ".o" for src in
00067                           self.resources.s_sources +
00068                           self.resources.c_sources +
00069                           self.resources.cpp_sources]
00070 
00071         libraries = [self.prepare_lib(basename(lib)) for lib
00072                      in self.resources.libraries]
00073         sys_libs = [self.prepare_sys_lib(lib) for lib
00074                     in self.toolchain.sys_libs]
00075 
00076         ctx = {
00077             'name': self.project_name,
00078             'to_be_compiled': to_be_compiled,
00079             'object_files': self.resources.objects,
00080             'include_paths': list(set(self.resources.inc_dirs)),
00081             'library_paths': self.resources.lib_dirs,
00082             'linker_script': self.resources.linker_script,
00083             'libraries': libraries,
00084             'ld_sys_libs': sys_libs,
00085             'hex_files': self.resources.hex_files,
00086             'vpath': (["../../.."]
00087                       if (basename(dirname(dirname(self.export_dir)))
00088                           == "projectfiles")
00089                       else [".."]),
00090             'cc_cmd': " ".join(["\'" + part + "\'" for part
00091                                 in ([basename(self.toolchain.cc[0])] +
00092                                     self.toolchain.cc[1:])]),
00093             'cppc_cmd': " ".join(["\'" + part + "\'" for part
00094                                   in ([basename(self.toolchain.cppc[0])] +
00095                                       self.toolchain.cppc[1:])]),
00096             'asm_cmd': " ".join(["\'" + part + "\'" for part
00097                                 in ([basename(self.toolchain.asm[0])] +
00098                                     self.toolchain.asm[1:])]),
00099             'ld_cmd': "\'" + basename(self.toolchain.ld[0]) + "\'",
00100             'elf2bin_cmd': "\'" + basename(self.toolchain.elf2bin) + "\'",
00101             'link_script_ext': self.toolchain.LINKER_EXT,
00102             'link_script_option': self.LINK_SCRIPT_OPTION,
00103             'user_library_flag': self.USER_LIBRARY_FLAG,
00104             'needs_asm_preproc': self.PREPROCESS_ASM ,
00105         }
00106 
00107         if hasattr(self.toolchain, "preproc"):
00108             ctx['pp_cmd'] = " ".join(["\'" + part + "\'" for part
00109                                       in ([basename(self.toolchain.preproc[0])] +
00110                                           self.toolchain.preproc[1:] + 
00111                                           self.toolchain.ld[1:])])
00112         else:
00113             ctx['pp_cmd'] = None
00114 
00115         for key in ['include_paths', 'library_paths', 'linker_script',
00116                     'hex_files']:
00117             if isinstance(ctx[key], list):
00118                 ctx[key] = [ctx['vpath'][0] + "/" + t for t in ctx[key]]
00119             else:
00120                 ctx[key] = ctx['vpath'][0] + "/" + ctx[key]
00121         if "../." not in ctx["include_paths"]:
00122             ctx["include_paths"] += ['../.']
00123         for key in ['include_paths', 'library_paths', 'hex_files',
00124                     'to_be_compiled']:
00125             ctx[key] = sorted(ctx[key])
00126         ctx.update(self.format_flags ())
00127 
00128         # Add the virtual path the the include option in the ASM flags
00129         ctx['asm_flags'] = map(lambda item: "-I" + ctx['vpath'][0] + "/" + item[2:]
00130                                if item.startswith('-I') else item, ctx['asm_flags'])
00131 
00132         for templatefile in \
00133             ['makefile/%s_%s.tmpl' % (self.TEMPLATE,
00134                                       self.target.lower())] + \
00135             ['makefile/%s_%s.tmpl' % (self.TEMPLATE,
00136                                       label.lower()) for label
00137              in self.toolchain.target.extra_labels] +\
00138             ['makefile/%s.tmpl' % self.TEMPLATE]:
00139             try:
00140                 self.gen_file(templatefile, ctx, 'Makefile')
00141                 break
00142             except TemplateNotFound:
00143                 pass
00144         else:
00145             raise NotSupportedException("This make tool is in development")
00146 
00147     def format_flags (self):
00148         """Format toolchain flags for Makefile"""
00149         flags = {}
00150         for k, v in self.flags.items():
00151             if k in ['asm_flags', 'c_flags', 'cxx_flags']:
00152                 flags[k] = map(lambda x: x.replace('"', '\\"'), v)
00153             else:
00154                 flags[k] = v
00155 
00156         return flags
00157 
00158     @staticmethod
00159     def clean (_):
00160         remove("Makefile")
00161         # legacy .build directory cleaned if exists
00162         if exists('.build'):
00163             shutil.rmtree('.build')
00164         if exists('BUILD'):
00165             shutil.rmtree('BUILD')
00166 
00167     @staticmethod
00168     def build (project_name, log_name="build_log.txt", cleanup=True):
00169         """ Build Make project """
00170         # > Make -j
00171         cmd = ["make", "-j"]
00172 
00173         # Build the project
00174         p = Popen(cmd, stdout=PIPE, stderr=PIPE)
00175         out, err = p.communicate()
00176         ret_code = p.returncode
00177 
00178         out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
00179         out_string += out
00180         out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
00181         out_string += err
00182 
00183         if ret_code == 0:
00184             out_string += "SUCCESS"
00185         else:
00186             out_string += "FAILURE"
00187 
00188         print(out_string)
00189 
00190         if log_name:
00191             # Write the output to the log file
00192             with open(log_name, 'w+') as f:
00193                 f.write(out_string)
00194 
00195         # Cleanup the exported and built files
00196         if cleanup:
00197             remove(log_name)
00198             Makefile.clean(project_name)
00199 
00200         if ret_code != 0:
00201             # Seems like something went wrong.
00202             return -1
00203         else:
00204             return 0
00205 
00206 
00207 class GccArm (Makefile ):
00208     """GCC ARM specific makefile target"""
00209     NAME = 'Make-GCC-ARM'
00210     TEMPLATE = 'make-gcc-arm'
00211     TOOLCHAIN = "GCC_ARM"
00212     LINK_SCRIPT_OPTION = "-T"
00213     USER_LIBRARY_FLAG = "-L"
00214 
00215     @staticmethod
00216     def prepare_lib(libname):
00217         if "lib" == libname[:3]:
00218             libname = libname[3:-2]
00219         return "-l" + libname
00220 
00221     @staticmethod
00222     def prepare_sys_lib(libname):
00223         return "-l" + libname
00224 
00225 
00226 class Arm (Makefile ):
00227     """ARM Compiler generic makefile target"""
00228     LINK_SCRIPT_OPTION = "--scatter"
00229     USER_LIBRARY_FLAG = "--userlibpath "
00230     TEMPLATE = 'make-arm'
00231 
00232     @staticmethod
00233     def prepare_lib(libname):
00234         return libname
00235 
00236     @staticmethod
00237     def prepare_sys_lib(libname):
00238         return libname
00239 
00240     def generate (self):
00241         if self.resources.linker_script:
00242             sct_file = self.resources.linker_script
00243             new_script = self.toolchain.correct_scatter_shebang(
00244                 sct_file, join(self.resources.file_basepath[sct_file], "BUILD"))
00245             if new_script is not sct_file:
00246                 self.resources.linker_script = new_script
00247                 self.generated_files.append(new_script)
00248         return super(Arm, self).generate()
00249 
00250 class Armc5 (Arm ):
00251     """ARM Compiler 5 (armcc) specific makefile target"""
00252     NAME = 'Make-ARMc5'
00253     TOOLCHAIN = "ARM"
00254     PREPROCESS_ASM = True
00255 
00256 class Armc6 (Arm ):
00257     """ARM Compiler 6 (armclang) specific generic makefile target"""
00258     NAME = 'Make-ARMc6'
00259     TOOLCHAIN = "ARMC6"
00260 
00261 
00262 class IAR (Makefile ):
00263     """IAR specific makefile target"""
00264     NAME = 'Make-IAR'
00265     TEMPLATE = 'make-iar'
00266     TOOLCHAIN = "IAR"
00267     LINK_SCRIPT_OPTION = "--config"
00268     USER_LIBRARY_FLAG = "-L"
00269 
00270     @staticmethod
00271     def prepare_lib(libname):
00272         if "lib" == libname[:3]:
00273             libname = libname[3:]
00274         return "-l" + splitext(libname)[0]
00275 
00276     @staticmethod
00277     def prepare_sys_lib(libname):
00278         if "lib" == libname[:3]:
00279             libname = libname[3:]
00280         return "-l" + splitext(libname)[0]