init

Dependencies:   mbed

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