|
| 1 | +""" |
| 2 | +mbed SDK |
| 3 | +Copyright (c) 2011-2016 ARM Limited |
| 4 | +
|
| 5 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | +you may not use this file except in compliance with the License. |
| 7 | +You may obtain a copy of the License at |
| 8 | +
|
| 9 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +
|
| 11 | +Unless required by applicable law or agreed to in writing, software |
| 12 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | +See the License for the specific language governing permissions and |
| 15 | +limitations under the License. |
| 16 | +""" |
| 17 | +import re |
| 18 | +import shutil |
| 19 | +from os import remove |
| 20 | +from os.path import splitext, basename, exists |
| 21 | +from subprocess import Popen, PIPE |
| 22 | + |
| 23 | +from jinja2.exceptions import TemplateNotFound |
| 24 | + |
| 25 | +from tools.export.exporters import Exporter |
| 26 | +from tools.utils import NotSupportedException |
| 27 | + |
| 28 | + |
| 29 | +class CMake(Exporter): |
| 30 | + """Generic CMake template that mimics the behavior of the python build |
| 31 | + system |
| 32 | + """ |
| 33 | + |
| 34 | + TEMPLATE = 'CMakeLists.txt' |
| 35 | + |
| 36 | + MBED_CONFIG_HEADER_SUPPORTED = True |
| 37 | + |
| 38 | + PREPROCESS_ASM = False |
| 39 | + |
| 40 | + @classmethod |
| 41 | + def is_target_supported(cls, target_name): |
| 42 | + return True |
| 43 | + |
| 44 | + def generate(self): |
| 45 | + """Generate the CMakefiles.txt |
| 46 | + """ |
| 47 | + self.resources.win_to_unix() |
| 48 | + |
| 49 | + sources = set(self.resources.c_sources + \ |
| 50 | + self.resources.cpp_sources + \ |
| 51 | + self.resources.s_sources + \ |
| 52 | + self.resources.headers) |
| 53 | + |
| 54 | + libnames = [l[:-4] for l in self.resources.lib_refs] |
| 55 | + libs = {re.sub(r'^[.]/', '', l): sorted([f for f in sources if f.startswith(l)]) for l in libnames} |
| 56 | + libs = {k: v for k, v in libs.items() if len(v) != 0} |
| 57 | + srcs = sorted([f for f in sources if f not in [item for sublist in libs.values() for item in sublist]]) |
| 58 | + |
| 59 | + libraries = [self.prepare_lib(basename(lib)) for lib |
| 60 | + in self.resources.libraries] |
| 61 | + sys_libs = [self.prepare_sys_lib(lib) for lib |
| 62 | + in self.toolchain.sys_libs] |
| 63 | + |
| 64 | + ctx = { |
| 65 | + 'name': self.project_name, |
| 66 | + 'target': self.target, |
| 67 | + 'sources': srcs, |
| 68 | + 'libs': libs, |
| 69 | + 'libraries': libraries, |
| 70 | + 'ld_sys_libs': sys_libs, |
| 71 | + 'include_paths': sorted(list(set(self.resources.inc_dirs))), |
| 72 | + 'library_paths': sorted(self.resources.lib_dirs), |
| 73 | + 'linker_script': self.resources.linker_script, |
| 74 | + 'hex_files': self.resources.hex_files, |
| 75 | + 'ar': basename(self.toolchain.ar), |
| 76 | + 'cc': basename(self.toolchain.cc[0]), |
| 77 | + 'cc_flags': " ".join(self.toolchain.cc[1:]), |
| 78 | + 'cxx': basename(self.toolchain.cppc[0]), |
| 79 | + 'cxx_flags': " ".join(self.toolchain.cppc[1:]), |
| 80 | + 'asm': basename(self.toolchain.asm[0]), |
| 81 | + 'asm_flags': " ".join(self.toolchain.asm[1:]), |
| 82 | + 'symbols': self.toolchain.get_symbols(), |
| 83 | + 'ld': basename(self.toolchain.ld[0]), |
| 84 | + 'ld_flags': " ".join(self.toolchain.ld[1:]), |
| 85 | + 'elf2bin': basename(self.toolchain.elf2bin), |
| 86 | + 'link_script_ext': self.toolchain.LINKER_EXT, |
| 87 | + 'link_script_option': self.LINK_SCRIPT_OPTION, |
| 88 | + 'user_library_flag': self.USER_LIBRARY_FLAG, |
| 89 | + 'needs_asm_preproc': self.PREPROCESS_ASM, |
| 90 | + } |
| 91 | + |
| 92 | + if hasattr(self.toolchain, "preproc"): |
| 93 | + ctx['pp'] = " ".join(["\'" + part + "\'" for part |
| 94 | + in ([basename(self.toolchain.preproc[0])] + |
| 95 | + self.toolchain.preproc[1:] + |
| 96 | + self.toolchain.ld[1:])]) |
| 97 | + else: |
| 98 | + ctx['pp'] = None |
| 99 | + |
| 100 | + for templatefile in ['cmake/%s.tmpl' % self.TEMPLATE]: |
| 101 | + try: |
| 102 | + self.gen_file(templatefile, ctx, 'CMakeLists.txt') |
| 103 | + break |
| 104 | + except TemplateNotFound: |
| 105 | + pass |
| 106 | + else: |
| 107 | + raise NotSupportedException("This make tool is in development") |
| 108 | + |
| 109 | + @staticmethod |
| 110 | + def build(project_name, log_name="build_log.txt", cleanup=True): |
| 111 | + """ Build Make project """ |
| 112 | + # > Make -j |
| 113 | + cmd = ["make", "-j"] |
| 114 | + |
| 115 | + # Build the project |
| 116 | + p = Popen(cmd, stdout=PIPE, stderr=PIPE) |
| 117 | + out, err = p.communicate() |
| 118 | + ret_code = p.returncode |
| 119 | + |
| 120 | + out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n" |
| 121 | + out_string += out |
| 122 | + out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n" |
| 123 | + out_string += err |
| 124 | + |
| 125 | + if ret_code == 0: |
| 126 | + out_string += "SUCCESS" |
| 127 | + else: |
| 128 | + out_string += "FAILURE" |
| 129 | + |
| 130 | + print out_string |
| 131 | + |
| 132 | + if log_name: |
| 133 | + # Write the output to the log file |
| 134 | + with open(log_name, 'w+') as f: |
| 135 | + f.write(out_string) |
| 136 | + |
| 137 | + # Cleanup the exported and built files |
| 138 | + if cleanup: |
| 139 | + remove("CMakeLists.txt") |
| 140 | + remove(log_name) |
| 141 | + # legacy .build directory cleaned if exists |
| 142 | + if exists('.build'): |
| 143 | + shutil.rmtree('.build') |
| 144 | + if exists('BUILD'): |
| 145 | + shutil.rmtree('BUILD') |
| 146 | + |
| 147 | + if ret_code != 0: |
| 148 | + # Seems like something went wrong. |
| 149 | + return -1 |
| 150 | + else: |
| 151 | + return 0 |
| 152 | + |
| 153 | + |
| 154 | +class GccArm(CMake): |
| 155 | + """GCC ARM specific cmake target""" |
| 156 | + NAME = 'CMake-GCC-ARM' |
| 157 | + TOOLCHAIN = "GCC_ARM" |
| 158 | + LINK_SCRIPT_OPTION = "-T" |
| 159 | + USER_LIBRARY_FLAG = "-L" |
| 160 | + |
| 161 | + @staticmethod |
| 162 | + def prepare_lib(libname): |
| 163 | + if "lib" == libname[:3]: |
| 164 | + libname = libname[3:-2] |
| 165 | + return "-l" + libname |
| 166 | + |
| 167 | + @staticmethod |
| 168 | + def prepare_sys_lib(libname): |
| 169 | + return "-l" + libname |
| 170 | + |
| 171 | + |
| 172 | +# class Arm(CMake): |
| 173 | +# """ARM Compiler generic cmake target""" |
| 174 | +# LINK_SCRIPT_OPTION = "--scatter" |
| 175 | +# USER_LIBRARY_FLAG = "--userlibpath " |
| 176 | +# |
| 177 | +# @staticmethod |
| 178 | +# def prepare_lib(libname): |
| 179 | +# return libname |
| 180 | +# |
| 181 | +# @staticmethod |
| 182 | +# def prepare_sys_lib(libname): |
| 183 | +# return libname |
| 184 | +# |
| 185 | +# def generate(self): |
| 186 | +# if self.resources.linker_script: |
| 187 | +# new_script = self.toolchain.correct_scatter_shebang( |
| 188 | +# self.resources.linker_script) |
| 189 | +# if new_script is not self.resources.linker_script: |
| 190 | +# self.resources.linker_script = new_script |
| 191 | +# self.generated_files.append(new_script) |
| 192 | +# return super(Arm, self).generate() |
| 193 | +# |
| 194 | +# |
| 195 | +# class Armc5(Arm): |
| 196 | +# """ARM Compiler 5 (armcc) specific makefile target""" |
| 197 | +# NAME = 'CMake-ARMc5' |
| 198 | +# TOOLCHAIN = "ARM" |
| 199 | +# PREPROCESS_ASM = True |
| 200 | +# |
| 201 | +# |
| 202 | +# class Armc6(Arm): |
| 203 | +# """ARM Compiler 6 (armclang) specific generic makefile target""" |
| 204 | +# NAME = 'CMake-ARMc6' |
| 205 | +# TOOLCHAIN = "ARMC6" |
| 206 | +# |
| 207 | +# |
| 208 | +# class IAR(CMake): |
| 209 | +# """IAR specific cmake target""" |
| 210 | +# NAME = 'CMake-IAR' |
| 211 | +# TOOLCHAIN = "IAR" |
| 212 | +# LINK_SCRIPT_OPTION = "--config" |
| 213 | +# USER_LIBRARY_FLAG = "-L" |
| 214 | +# |
| 215 | +# @staticmethod |
| 216 | +# def prepare_lib(libname): |
| 217 | +# if "lib" == libname[:3]: |
| 218 | +# libname = libname[3:] |
| 219 | +# return "-l" + splitext(libname)[0] |
| 220 | +# |
| 221 | +# @staticmethod |
| 222 | +# def prepare_sys_lib(libname): |
| 223 | +# if "lib" == libname[:3]: |
| 224 | +# libname = libname[3:] |
| 225 | +# return "-l" + splitext(libname)[0] |
0 commit comments