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 import re
00021 import shutil
00022 from os import remove, getcwd, chdir, mkdir
00023 from os.path import basename, exists
00024 from subprocess import Popen, PIPE
00025 
00026 from jinja2.exceptions import TemplateNotFound
00027 
00028 from tools.export.exporters import Exporter, apply_supported_whitelist
00029 from tools.targets import TARGET_MAP
00030 
00031 
00032 class CMake (Exporter ):
00033     """Generic CMake template that mimics the behavior of the python build
00034     system
00035     """
00036 
00037     TEMPLATE = 'CMakeLists.txt'
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 CMakefiles.txt
00058         """
00059         self.resources.win_to_unix()
00060 
00061         # get all source files including headers, adding headers allows IDEs to detect which files
00062         # belong to the project, otherwise headers may be greyed out and not work with inspection
00063         # (that is true for CLion and definitely for Visual Code)
00064         srcs = set(self.resources.c_sources +
00065                    self.resources.cpp_sources +
00066                    self.resources.s_sources +
00067                    self.resources.headers)
00068         srcs = [re.sub(r'^[.]/', '', f) for f in srcs]
00069 
00070         # additional libraries
00071         libraries = [self.prepare_lib(basename(lib)) for lib in self.resources.libraries]
00072         sys_libs = [self.prepare_sys_lib(lib) for lib in self.toolchain.sys_libs]
00073 
00074         # sort includes reverse, so the deepest dir comes first (ensures short includes)
00075         includes = sorted([re.sub(r'^[.]/', '', l) for l in self.resources.inc_dirs], reverse=True)
00076 
00077         ctx = {
00078             'name': self.project_name,
00079             'target': self.target,
00080             'sources': sorted(srcs),
00081             'libraries': libraries,
00082             'ld_sys_libs': sys_libs,
00083             'include_paths': includes,
00084             'library_paths': sorted([re.sub(r'^[.]/', '', l) for l in self.resources.lib_dirs]),
00085             'linker_script': self.resources.linker_script,
00086             'hex_files': self.resources.hex_files,
00087             'ar': basename(self.toolchain.ar),
00088             'cc': basename(self.toolchain.cc[0]),
00089             'cc_flags': " ".join(flag for flag in self.toolchain.cc[1:] if not flag == "-c"),
00090             'cxx': basename(self.toolchain.cppc[0]),
00091             'cxx_flags': " ".join(flag for flag in self.toolchain.cppc[1:] if not flag == "-c"),
00092             'asm': basename(self.toolchain.asm[0]),
00093             'asm_flags': " ".join(flag for flag in self.toolchain.asm[1:] if not flag == "-c"),
00094             'symbols': sorted(self.toolchain.get_symbols()),
00095             'ld': basename(self.toolchain.ld[0]),
00096             # fix the missing underscore '_' (see
00097             'ld_flags': re.sub("--wrap,_(?!_)", "--wrap,__", " ".join(self.toolchain.ld[1:])),
00098             'elf2bin': basename(self.toolchain.elf2bin),
00099             'link_script_ext': self.toolchain.LINKER_EXT,
00100             'link_script_option': self.LINK_SCRIPT_OPTION,
00101             'user_library_flag': self.USER_LIBRARY_FLAG,
00102             'needs_asm_preproc': self.PREPROCESS_ASM ,
00103         }
00104 
00105         if hasattr(self.toolchain, "preproc"):
00106             ctx['pp'] = basename(self.toolchain.preproc[0])
00107             ctx['pp_flags'] = " ".join(self.toolchain.preproc[1:] +
00108                                        self.toolchain.ld[1:])
00109         else:
00110             ctx['pp'] = None
00111             ctx['pp_flags'] = None
00112 
00113         try:
00114             self.gen_file('cmake/%s.tmpl' % self.TEMPLATE , ctx, 'CMakeLists.txt')
00115         except TemplateNotFound:
00116             pass
00117 
00118     @staticmethod
00119     def clean (_):
00120         remove("CMakeLists.txt")
00121         # legacy .build directory cleaned if exists
00122         if exists('.build'):
00123             shutil.rmtree('.build')
00124         if exists('BUILD'):
00125             shutil.rmtree('BUILD')
00126 
00127     @staticmethod
00128     def build (project_name, log_name="build_log.txt", cleanup=True):
00129         """ Build Make project """
00130 
00131         # change into our build directory
00132         current_dir = getcwd()
00133         if not exists("BUILD"):
00134             mkdir("BUILD")
00135         chdir("BUILD")
00136 
00137         # > run cmake initial command
00138         cmd = ["cmake", ".."]
00139 
00140         # Build the project
00141         p = Popen(cmd, stdout=PIPE, stderr=PIPE)
00142         out, err = p.communicate()
00143         ret_code = p.returncode
00144 
00145         if ret_code == 0:
00146             # we create the cmake files inside BUILD, change into and run cmake
00147 
00148             # > run make -j
00149             cmd = ["make", "-j"]
00150 
00151             p = Popen(cmd, stdout=PIPE, stderr=PIPE)
00152             out, err = p.communicate()
00153             ret_code = p.returncode
00154 
00155         # go back to the original directory
00156         chdir(current_dir)
00157 
00158         out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
00159         out_string += out
00160         out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
00161         out_string += err
00162 
00163         if ret_code == 0:
00164             out_string += "SUCCESS"
00165         else:
00166             out_string += "FAILURE"
00167 
00168         print(out_string)
00169 
00170         if log_name:
00171             # Write the output to the log file
00172             with open(log_name, 'w+') as f:
00173                 f.write(out_string)
00174 
00175         # Cleanup the exported and built files
00176         if cleanup:
00177             remove(log_name)
00178             CMake.clean(project_name)
00179 
00180         if ret_code != 0:
00181             # Seems like something went wrong.
00182             return -1
00183         else:
00184             return 0
00185 
00186 
00187 class GccArm (CMake ):
00188     """GCC ARM specific cmake target"""
00189     NAME = 'CMake-GCC-ARM'
00190     TOOLCHAIN = "GCC_ARM"
00191     LINK_SCRIPT_OPTION = "-T"
00192     USER_LIBRARY_FLAG = "-L"
00193 
00194     @staticmethod
00195     def prepare_lib(libname):
00196         if "lib" == libname[:3]:
00197             libname = libname[3:-2]
00198         return "-l" + libname
00199 
00200     @staticmethod
00201     def prepare_sys_lib(libname):
00202         return "-l" + libname
00203 
00204 # class Arm(CMake):
00205 #     """ARM Compiler generic cmake target"""
00206 #     LINK_SCRIPT_OPTION = "--scatter"
00207 #     USER_LIBRARY_FLAG = "--userlibpath "
00208 #
00209 #     @staticmethod
00210 #     def prepare_lib(libname):
00211 #         return libname
00212 #
00213 #     @staticmethod
00214 #     def prepare_sys_lib(libname):
00215 #         return libname
00216 #
00217 #     def generate(self):
00218 #         if self.resources.linker_script:
00219 #             new_script = self.toolchain.correct_scatter_shebang(
00220 #                 self.resources.linker_script)
00221 #             if new_script is not self.resources.linker_script:
00222 #                 self.resources.linker_script = new_script
00223 #                 self.generated_files.append(new_script)
00224 #         return super(Arm, self).generate()
00225 #
00226 #
00227 # class Armc5(Arm):
00228 #     """ARM Compiler 5 (armcc) specific makefile target"""
00229 #     NAME = 'CMake-ARMc5'
00230 #     TOOLCHAIN = "ARM"
00231 #     PREPROCESS_ASM = True
00232 #
00233 #
00234 # class Armc6(Arm):
00235 #     """ARM Compiler 6 (armclang) specific generic makefile target"""
00236 #     NAME = 'CMake-ARMc6'
00237 #     TOOLCHAIN = "ARMC6"
00238 #
00239 #
00240 # class IAR(CMake):
00241 #     """IAR specific cmake target"""
00242 #     NAME = 'CMake-IAR'
00243 #     TOOLCHAIN = "IAR"
00244 #     LINK_SCRIPT_OPTION = "--config"
00245 #     USER_LIBRARY_FLAG = "-L"
00246 #
00247 #     @staticmethod
00248 #     def prepare_lib(libname):
00249 #         if "lib" == libname[:3]:
00250 #             libname = libname[3:]
00251 #         return "-l" + splitext(libname)[0]
00252 #
00253 #     @staticmethod
00254 #     def prepare_sys_lib(libname):
00255 #         if "lib" == libname[:3]:
00256 #             libname = libname[3:]
00257 #         return "-l" + splitext(libname)[0]