Clone of official tools
export/cces/__init__.py@47:21ae3e5a7128, 2021-02-04 (annotated)
- Committer:
- Anders Blomdell
- Date:
- Thu Feb 04 17:17:13 2021 +0100
- Revision:
- 47:21ae3e5a7128
- Parent:
- 43:2a7da56ebd24
Add a few normpath calls
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
theotherjimmy |
43:2a7da56ebd24 | 1 | """ |
theotherjimmy |
43:2a7da56ebd24 | 2 | mbed SDK |
theotherjimmy |
43:2a7da56ebd24 | 3 | Copyright (c) 2011-2017 ARM Limited |
theotherjimmy |
43:2a7da56ebd24 | 4 | Portions Copyright (c) 2017-2018 Analog Devices, Inc. |
theotherjimmy |
43:2a7da56ebd24 | 5 | |
theotherjimmy |
43:2a7da56ebd24 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); |
theotherjimmy |
43:2a7da56ebd24 | 7 | you may not use this file except in compliance with the License. |
theotherjimmy |
43:2a7da56ebd24 | 8 | You may obtain a copy of the License at |
theotherjimmy |
43:2a7da56ebd24 | 9 | |
theotherjimmy |
43:2a7da56ebd24 | 10 | http://www.apache.org/licenses/LICENSE-2.0 |
theotherjimmy |
43:2a7da56ebd24 | 11 | |
theotherjimmy |
43:2a7da56ebd24 | 12 | Unless required by applicable law or agreed to in writing, software |
theotherjimmy |
43:2a7da56ebd24 | 13 | distributed under the License is distributed on an "AS IS" BASIS, |
theotherjimmy |
43:2a7da56ebd24 | 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
theotherjimmy |
43:2a7da56ebd24 | 15 | See the License for the specific language governing permissions and |
theotherjimmy |
43:2a7da56ebd24 | 16 | limitations under the License. |
theotherjimmy |
43:2a7da56ebd24 | 17 | """ |
theotherjimmy |
43:2a7da56ebd24 | 18 | |
theotherjimmy |
43:2a7da56ebd24 | 19 | import copy |
theotherjimmy |
43:2a7da56ebd24 | 20 | import os |
theotherjimmy |
43:2a7da56ebd24 | 21 | import sys |
theotherjimmy |
43:2a7da56ebd24 | 22 | import shutil |
theotherjimmy |
43:2a7da56ebd24 | 23 | import tempfile |
theotherjimmy |
43:2a7da56ebd24 | 24 | |
theotherjimmy |
43:2a7da56ebd24 | 25 | from subprocess import Popen, PIPE |
theotherjimmy |
43:2a7da56ebd24 | 26 | |
theotherjimmy |
43:2a7da56ebd24 | 27 | from tools.targets import TARGET_MAP |
theotherjimmy |
43:2a7da56ebd24 | 28 | from tools.export.exporters import Exporter |
theotherjimmy |
43:2a7da56ebd24 | 29 | |
theotherjimmy |
43:2a7da56ebd24 | 30 | from collections import namedtuple |
theotherjimmy |
43:2a7da56ebd24 | 31 | |
theotherjimmy |
43:2a7da56ebd24 | 32 | |
theotherjimmy |
43:2a7da56ebd24 | 33 | # Container for CCES option type and value |
theotherjimmy |
43:2a7da56ebd24 | 34 | Option = namedtuple('Option', ['type', 'value']) |
theotherjimmy |
43:2a7da56ebd24 | 35 | |
theotherjimmy |
43:2a7da56ebd24 | 36 | """ |
theotherjimmy |
43:2a7da56ebd24 | 37 | Tuple of supported device names |
theotherjimmy |
43:2a7da56ebd24 | 38 | """ |
theotherjimmy |
43:2a7da56ebd24 | 39 | SUPPORTED_DEVICES = ("ADuCM3027", "ADuCM3029", "ADuCM360", "ADuCM4050") |
theotherjimmy |
43:2a7da56ebd24 | 40 | |
theotherjimmy |
43:2a7da56ebd24 | 41 | class CCES(Exporter): |
theotherjimmy |
43:2a7da56ebd24 | 42 | """ |
theotherjimmy |
43:2a7da56ebd24 | 43 | mbed exporter for Analog Devices' CrossCore Embedded Studio(TM) |
theotherjimmy |
43:2a7da56ebd24 | 44 | """ |
theotherjimmy |
43:2a7da56ebd24 | 45 | NAME = 'CrossCore Embedded Studio' |
theotherjimmy |
43:2a7da56ebd24 | 46 | TOOLCHAIN = 'GCC_ARM' |
theotherjimmy |
43:2a7da56ebd24 | 47 | |
theotherjimmy |
43:2a7da56ebd24 | 48 | @classmethod |
theotherjimmy |
43:2a7da56ebd24 | 49 | def is_target_supported(cls, target_name): |
theotherjimmy |
43:2a7da56ebd24 | 50 | """Query support for a particular target |
theotherjimmy |
43:2a7da56ebd24 | 51 | |
theotherjimmy |
43:2a7da56ebd24 | 52 | Positional Arguments: |
theotherjimmy |
43:2a7da56ebd24 | 53 | target_name - the name of the target. |
theotherjimmy |
43:2a7da56ebd24 | 54 | """ |
theotherjimmy |
43:2a7da56ebd24 | 55 | target = TARGET_MAP[target_name] |
theotherjimmy |
43:2a7da56ebd24 | 56 | return (cls.TOOLCHAIN in target.supported_toolchains) \ |
theotherjimmy |
43:2a7da56ebd24 | 57 | and hasattr(target, "device_name") \ |
theotherjimmy |
43:2a7da56ebd24 | 58 | and (target.device_name in SUPPORTED_DEVICES) |
theotherjimmy |
43:2a7da56ebd24 | 59 | |
theotherjimmy |
43:2a7da56ebd24 | 60 | @property |
theotherjimmy |
43:2a7da56ebd24 | 61 | def flags(self): |
theotherjimmy |
43:2a7da56ebd24 | 62 | """Returns a dictionary of toolchain flags. |
theotherjimmy |
43:2a7da56ebd24 | 63 | Keys of the dictionary are: |
theotherjimmy |
43:2a7da56ebd24 | 64 | cxx_flags - c++ flags |
theotherjimmy |
43:2a7da56ebd24 | 65 | c_flags - c flags |
theotherjimmy |
43:2a7da56ebd24 | 66 | ld_flags - linker flags |
theotherjimmy |
43:2a7da56ebd24 | 67 | asm_flags - assembler flags |
theotherjimmy |
43:2a7da56ebd24 | 68 | common_flags - common options |
theotherjimmy |
43:2a7da56ebd24 | 69 | |
theotherjimmy |
43:2a7da56ebd24 | 70 | Skip macros because headless tools handles them separately |
theotherjimmy |
43:2a7da56ebd24 | 71 | """ |
theotherjimmy |
43:2a7da56ebd24 | 72 | flags = {key + "_flags": copy.deepcopy(value) for key, value \ |
theotherjimmy |
43:2a7da56ebd24 | 73 | in self.toolchain.flags.iteritems()} |
theotherjimmy |
43:2a7da56ebd24 | 74 | config_header = self.config_header_ref |
theotherjimmy |
43:2a7da56ebd24 | 75 | if config_header: |
theotherjimmy |
43:2a7da56ebd24 | 76 | config_header = "\\\"" + self.format_inc_path(config_header.name) \ |
theotherjimmy |
43:2a7da56ebd24 | 77 | + "\\\"" |
theotherjimmy |
43:2a7da56ebd24 | 78 | header_options = self.toolchain.get_config_option(config_header) |
theotherjimmy |
43:2a7da56ebd24 | 79 | flags['c_flags'] += header_options |
theotherjimmy |
43:2a7da56ebd24 | 80 | flags['cxx_flags'] += header_options |
theotherjimmy |
43:2a7da56ebd24 | 81 | return flags |
theotherjimmy |
43:2a7da56ebd24 | 82 | |
theotherjimmy |
43:2a7da56ebd24 | 83 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 84 | def format_path(path, prefix): |
theotherjimmy |
43:2a7da56ebd24 | 85 | """ |
theotherjimmy |
43:2a7da56ebd24 | 86 | Formats the given source path relative to the project directory |
theotherjimmy |
43:2a7da56ebd24 | 87 | using the prefix |
theotherjimmy |
43:2a7da56ebd24 | 88 | """ |
theotherjimmy |
43:2a7da56ebd24 | 89 | new_path = path |
theotherjimmy |
43:2a7da56ebd24 | 90 | if new_path.startswith("./"): |
theotherjimmy |
43:2a7da56ebd24 | 91 | new_path = new_path[2:] |
theotherjimmy |
43:2a7da56ebd24 | 92 | return prefix + new_path.replace("\\", "\\\\") |
theotherjimmy |
43:2a7da56ebd24 | 93 | |
theotherjimmy |
43:2a7da56ebd24 | 94 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 95 | def format_inc_path(path): |
theotherjimmy |
43:2a7da56ebd24 | 96 | """ |
theotherjimmy |
43:2a7da56ebd24 | 97 | Formats the given include path relative to the project directory |
theotherjimmy |
43:2a7da56ebd24 | 98 | """ |
theotherjimmy |
43:2a7da56ebd24 | 99 | return CCES.format_path(path, "${ProjDirPath}/../") |
theotherjimmy |
43:2a7da56ebd24 | 100 | |
theotherjimmy |
43:2a7da56ebd24 | 101 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 102 | def format_src_path(path): |
theotherjimmy |
43:2a7da56ebd24 | 103 | """ |
theotherjimmy |
43:2a7da56ebd24 | 104 | Formats the given source path relative to the project directory |
theotherjimmy |
43:2a7da56ebd24 | 105 | """ |
theotherjimmy |
43:2a7da56ebd24 | 106 | return CCES.format_path(path, "PARENT-1-PROJECT_LOC/") |
theotherjimmy |
43:2a7da56ebd24 | 107 | |
theotherjimmy |
43:2a7da56ebd24 | 108 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 109 | def clean_flags(container, flags_to_remove): |
theotherjimmy |
43:2a7da56ebd24 | 110 | """ |
theotherjimmy |
43:2a7da56ebd24 | 111 | Some flags are handled by CCES already, so there's no need |
theotherjimmy |
43:2a7da56ebd24 | 112 | to include them twice. |
theotherjimmy |
43:2a7da56ebd24 | 113 | """ |
theotherjimmy |
43:2a7da56ebd24 | 114 | for flag in flags_to_remove: |
theotherjimmy |
43:2a7da56ebd24 | 115 | if flag in container: |
theotherjimmy |
43:2a7da56ebd24 | 116 | container.remove(flag) |
theotherjimmy |
43:2a7da56ebd24 | 117 | |
theotherjimmy |
43:2a7da56ebd24 | 118 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 119 | def parse_flags(flags, options, booleans): |
theotherjimmy |
43:2a7da56ebd24 | 120 | """ |
theotherjimmy |
43:2a7da56ebd24 | 121 | Parse the values in `booleans`, insert them into the |
theotherjimmy |
43:2a7da56ebd24 | 122 | `options` dictionary and remove them from `flags` |
theotherjimmy |
43:2a7da56ebd24 | 123 | """ |
theotherjimmy |
43:2a7da56ebd24 | 124 | for flag, flag_id in booleans.items(): |
theotherjimmy |
43:2a7da56ebd24 | 125 | value = "false" |
theotherjimmy |
43:2a7da56ebd24 | 126 | if flag in flags: |
theotherjimmy |
43:2a7da56ebd24 | 127 | value = "true" |
theotherjimmy |
43:2a7da56ebd24 | 128 | flags.remove(flag) |
theotherjimmy |
43:2a7da56ebd24 | 129 | options[flag_id] = Option("baseId", value) |
theotherjimmy |
43:2a7da56ebd24 | 130 | |
theotherjimmy |
43:2a7da56ebd24 | 131 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 132 | def convert_common_options(prefix, options, flags): |
theotherjimmy |
43:2a7da56ebd24 | 133 | """ |
theotherjimmy |
43:2a7da56ebd24 | 134 | Converts the common flags into CCES options and removes them |
theotherjimmy |
43:2a7da56ebd24 | 135 | from the flags list |
theotherjimmy |
43:2a7da56ebd24 | 136 | """ |
theotherjimmy |
43:2a7da56ebd24 | 137 | # remove these flags without converting to option |
theotherjimmy |
43:2a7da56ebd24 | 138 | # since they are added by CCES |
theotherjimmy |
43:2a7da56ebd24 | 139 | remove = ["-c"] |
theotherjimmy |
43:2a7da56ebd24 | 140 | CCES.clean_flags(flags, remove) |
theotherjimmy |
43:2a7da56ebd24 | 141 | |
theotherjimmy |
43:2a7da56ebd24 | 142 | value = prefix + "option.dwarfversion.enumerated.v2" |
theotherjimmy |
43:2a7da56ebd24 | 143 | for flag in flags: |
theotherjimmy |
43:2a7da56ebd24 | 144 | if flag.startswith("-gdwarf"): |
theotherjimmy |
43:2a7da56ebd24 | 145 | value = prefix + "option.dwarfversion.enumerated.v" + flag[-1] |
theotherjimmy |
43:2a7da56ebd24 | 146 | flags.remove(flag) |
theotherjimmy |
43:2a7da56ebd24 | 147 | break |
theotherjimmy |
43:2a7da56ebd24 | 148 | option = Option("baseId", value) |
theotherjimmy |
43:2a7da56ebd24 | 149 | options[prefix + "option.dwarfversion"] = option |
theotherjimmy |
43:2a7da56ebd24 | 150 | |
theotherjimmy |
43:2a7da56ebd24 | 151 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 152 | def convert_assembler_options(flags): |
theotherjimmy |
43:2a7da56ebd24 | 153 | """ |
theotherjimmy |
43:2a7da56ebd24 | 154 | Converts the assembler flags into CCES options and removes them |
theotherjimmy |
43:2a7da56ebd24 | 155 | from the flags list |
theotherjimmy |
43:2a7da56ebd24 | 156 | """ |
theotherjimmy |
43:2a7da56ebd24 | 157 | options = {} |
theotherjimmy |
43:2a7da56ebd24 | 158 | |
theotherjimmy |
43:2a7da56ebd24 | 159 | # remove these flags without converting to option |
theotherjimmy |
43:2a7da56ebd24 | 160 | # since they are added by CCES |
theotherjimmy |
43:2a7da56ebd24 | 161 | remove = ["-x", "assembler-with-cpp"] |
theotherjimmy |
43:2a7da56ebd24 | 162 | CCES.clean_flags(flags, remove) |
theotherjimmy |
43:2a7da56ebd24 | 163 | |
theotherjimmy |
43:2a7da56ebd24 | 164 | booleans = {"-v": "arm.assembler.option.verbose", |
theotherjimmy |
43:2a7da56ebd24 | 165 | "-g": "arm.assembler.option.debuginfo"} |
theotherjimmy |
43:2a7da56ebd24 | 166 | |
theotherjimmy |
43:2a7da56ebd24 | 167 | CCES.parse_flags(flags, options, booleans) |
theotherjimmy |
43:2a7da56ebd24 | 168 | |
theotherjimmy |
43:2a7da56ebd24 | 169 | CCES.convert_common_options("arm.assembler.", options, flags) |
theotherjimmy |
43:2a7da56ebd24 | 170 | |
theotherjimmy |
43:2a7da56ebd24 | 171 | return options |
theotherjimmy |
43:2a7da56ebd24 | 172 | |
theotherjimmy |
43:2a7da56ebd24 | 173 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 174 | def convert_compiler_options(flags): |
theotherjimmy |
43:2a7da56ebd24 | 175 | """ |
theotherjimmy |
43:2a7da56ebd24 | 176 | Converts the compiler flags into CCES options and removes them |
theotherjimmy |
43:2a7da56ebd24 | 177 | from the flags list |
theotherjimmy |
43:2a7da56ebd24 | 178 | """ |
theotherjimmy |
43:2a7da56ebd24 | 179 | options = {} |
theotherjimmy |
43:2a7da56ebd24 | 180 | |
theotherjimmy |
43:2a7da56ebd24 | 181 | enable_optimization = "true" |
theotherjimmy |
43:2a7da56ebd24 | 182 | value = "arm.base.compiler.option.optimization.og" |
theotherjimmy |
43:2a7da56ebd24 | 183 | for flag in flags: |
theotherjimmy |
43:2a7da56ebd24 | 184 | if flag.startswith("-O"): |
theotherjimmy |
43:2a7da56ebd24 | 185 | value = "arm.base.compiler.option.optimization.o" + flag[2:] |
theotherjimmy |
43:2a7da56ebd24 | 186 | if flag[2:] == "0": |
theotherjimmy |
43:2a7da56ebd24 | 187 | enable_optimization = "false" |
theotherjimmy |
43:2a7da56ebd24 | 188 | flags.remove(flag) |
theotherjimmy |
43:2a7da56ebd24 | 189 | break |
theotherjimmy |
43:2a7da56ebd24 | 190 | option = Option("baseId", value) |
theotherjimmy |
43:2a7da56ebd24 | 191 | options["arm.base.compiler.option.optimization"] = option |
theotherjimmy |
43:2a7da56ebd24 | 192 | |
theotherjimmy |
43:2a7da56ebd24 | 193 | option = Option("baseId", enable_optimization) |
theotherjimmy |
43:2a7da56ebd24 | 194 | options["arm.base.compiler.option.optimization.enable"] = option |
theotherjimmy |
43:2a7da56ebd24 | 195 | |
theotherjimmy |
43:2a7da56ebd24 | 196 | booleans = {"-g": "arm.base.compiler.option.debug", |
theotherjimmy |
43:2a7da56ebd24 | 197 | "-save-temps": \ |
theotherjimmy |
43:2a7da56ebd24 | 198 | "arm.base.compiler.option.savetemps", |
theotherjimmy |
43:2a7da56ebd24 | 199 | "-ffunction-sections": \ |
theotherjimmy |
43:2a7da56ebd24 | 200 | "arm.c.compiler.option.elimination.code", |
theotherjimmy |
43:2a7da56ebd24 | 201 | "-fdata-sections": \ |
theotherjimmy |
43:2a7da56ebd24 | 202 | "arm.c.compiler.option.elimination.data", |
theotherjimmy |
43:2a7da56ebd24 | 203 | "-pedantic": "arm.base.compiler.option.pedantic", |
theotherjimmy |
43:2a7da56ebd24 | 204 | "-pedantic-errors": \ |
theotherjimmy |
43:2a7da56ebd24 | 205 | "arm.base.compiler.option.pedanticerrors", |
theotherjimmy |
43:2a7da56ebd24 | 206 | "-w": "arm.base.compiler.option.inhibitallwarnings", |
theotherjimmy |
43:2a7da56ebd24 | 207 | "-Wall": "arm.base.compiler.option.allwarnings", |
theotherjimmy |
43:2a7da56ebd24 | 208 | "-Wextra": "arm.base.compiler.option.extrawarnings", |
theotherjimmy |
43:2a7da56ebd24 | 209 | "-Werror": "arm.base.compiler.option.warningaserror", |
theotherjimmy |
43:2a7da56ebd24 | 210 | "-Wconversion": \ |
theotherjimmy |
43:2a7da56ebd24 | 211 | "arm.base.compiler.option.conversionwarning"} |
theotherjimmy |
43:2a7da56ebd24 | 212 | |
theotherjimmy |
43:2a7da56ebd24 | 213 | CCES.parse_flags(flags, options, booleans) |
theotherjimmy |
43:2a7da56ebd24 | 214 | |
theotherjimmy |
43:2a7da56ebd24 | 215 | CCES.convert_common_options("arm.base.compiler.", options, flags) |
theotherjimmy |
43:2a7da56ebd24 | 216 | |
theotherjimmy |
43:2a7da56ebd24 | 217 | return options |
theotherjimmy |
43:2a7da56ebd24 | 218 | |
theotherjimmy |
43:2a7da56ebd24 | 219 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 220 | def convert_linker_options(flags): |
theotherjimmy |
43:2a7da56ebd24 | 221 | """ |
theotherjimmy |
43:2a7da56ebd24 | 222 | Converts the linker flags into CCES options and removes them |
theotherjimmy |
43:2a7da56ebd24 | 223 | from the flags list |
theotherjimmy |
43:2a7da56ebd24 | 224 | """ |
theotherjimmy |
43:2a7da56ebd24 | 225 | options = {} |
theotherjimmy |
43:2a7da56ebd24 | 226 | |
theotherjimmy |
43:2a7da56ebd24 | 227 | booleans = {"-nostartfiles": "arm.linker.option.nostart", |
theotherjimmy |
43:2a7da56ebd24 | 228 | "-nodefaultlibs": "arm.linker.option.nodeflibs", |
theotherjimmy |
43:2a7da56ebd24 | 229 | "-nostdlib": "arm.linker.option.nostdlibs", |
theotherjimmy |
43:2a7da56ebd24 | 230 | "-s": "arm.linker.option.strip", |
theotherjimmy |
43:2a7da56ebd24 | 231 | "-Wl,--gc-sections": "arm.linker.option.elimination"} |
theotherjimmy |
43:2a7da56ebd24 | 232 | |
theotherjimmy |
43:2a7da56ebd24 | 233 | CCES.parse_flags(flags, options, booleans) |
theotherjimmy |
43:2a7da56ebd24 | 234 | |
theotherjimmy |
43:2a7da56ebd24 | 235 | return options |
theotherjimmy |
43:2a7da56ebd24 | 236 | |
theotherjimmy |
43:2a7da56ebd24 | 237 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 238 | def get_cces_path(root): |
theotherjimmy |
43:2a7da56ebd24 | 239 | """ |
theotherjimmy |
43:2a7da56ebd24 | 240 | Returns the path to the CCES executable |
theotherjimmy |
43:2a7da56ebd24 | 241 | """ |
theotherjimmy |
43:2a7da56ebd24 | 242 | cces_path = None |
theotherjimmy |
43:2a7da56ebd24 | 243 | |
theotherjimmy |
43:2a7da56ebd24 | 244 | if sys.platform == 'win32' or sys.platform == 'cygwin': |
theotherjimmy |
43:2a7da56ebd24 | 245 | cces_path = os.path.join(root, "Eclipse", "ccesc.exe") |
theotherjimmy |
43:2a7da56ebd24 | 246 | elif sys.platform.startswith('linux'): |
theotherjimmy |
43:2a7da56ebd24 | 247 | cces_path = os.path.join(root, "Eclipse", "cces") |
theotherjimmy |
43:2a7da56ebd24 | 248 | elif sys.platform == 'darwin': |
theotherjimmy |
43:2a7da56ebd24 | 249 | cces_path = os.path.join(root, "MacOS", "cces") |
theotherjimmy |
43:2a7da56ebd24 | 250 | else: |
theotherjimmy |
43:2a7da56ebd24 | 251 | print("Unsupported operating system '%s'" % sys.platform) |
theotherjimmy |
43:2a7da56ebd24 | 252 | return None |
theotherjimmy |
43:2a7da56ebd24 | 253 | |
theotherjimmy |
43:2a7da56ebd24 | 254 | return cces_path |
theotherjimmy |
43:2a7da56ebd24 | 255 | |
theotherjimmy |
43:2a7da56ebd24 | 256 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 257 | def get_project_create_command(cces_path, workspace, project_name): |
theotherjimmy |
43:2a7da56ebd24 | 258 | """ |
theotherjimmy |
43:2a7da56ebd24 | 259 | Generate the headless tools projectcreate command string |
theotherjimmy |
43:2a7da56ebd24 | 260 | with the given parameters |
theotherjimmy |
43:2a7da56ebd24 | 261 | """ |
theotherjimmy |
43:2a7da56ebd24 | 262 | cmd = [ |
theotherjimmy |
43:2a7da56ebd24 | 263 | "\"%s\"" % cces_path, |
theotherjimmy |
43:2a7da56ebd24 | 264 | "-nosplash", |
theotherjimmy |
43:2a7da56ebd24 | 265 | "-consoleLog", |
theotherjimmy |
43:2a7da56ebd24 | 266 | "-application com.analog.crosscore.headlesstools", |
theotherjimmy |
43:2a7da56ebd24 | 267 | "-data", workspace, |
theotherjimmy |
43:2a7da56ebd24 | 268 | "-project", project_name, |
theotherjimmy |
43:2a7da56ebd24 | 269 | "-command projectcreate", |
theotherjimmy |
43:2a7da56ebd24 | 270 | "-input-file", "cces.json" |
theotherjimmy |
43:2a7da56ebd24 | 271 | ] |
theotherjimmy |
43:2a7da56ebd24 | 272 | return ' '.join(cmd) |
theotherjimmy |
43:2a7da56ebd24 | 273 | |
theotherjimmy |
43:2a7da56ebd24 | 274 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 275 | def get_project_build_command(cces_path, workspace, project_name): |
theotherjimmy |
43:2a7da56ebd24 | 276 | """ |
theotherjimmy |
43:2a7da56ebd24 | 277 | Generate the headless tools build command string |
theotherjimmy |
43:2a7da56ebd24 | 278 | with the given parameters |
theotherjimmy |
43:2a7da56ebd24 | 279 | """ |
theotherjimmy |
43:2a7da56ebd24 | 280 | cmd = [ |
theotherjimmy |
43:2a7da56ebd24 | 281 | "\"%s\"" % cces_path, |
theotherjimmy |
43:2a7da56ebd24 | 282 | "-nosplash", |
theotherjimmy |
43:2a7da56ebd24 | 283 | "-consoleLog", |
theotherjimmy |
43:2a7da56ebd24 | 284 | "-application com.analog.crosscore.headlesstools", |
theotherjimmy |
43:2a7da56ebd24 | 285 | "-data", workspace, |
theotherjimmy |
43:2a7da56ebd24 | 286 | "-project", project_name, |
theotherjimmy |
43:2a7da56ebd24 | 287 | "-cleanBuild all" |
theotherjimmy |
43:2a7da56ebd24 | 288 | ] |
theotherjimmy |
43:2a7da56ebd24 | 289 | return ' '.join(cmd) |
theotherjimmy |
43:2a7da56ebd24 | 290 | |
theotherjimmy |
43:2a7da56ebd24 | 291 | # override |
theotherjimmy |
43:2a7da56ebd24 | 292 | def generate(self): |
theotherjimmy |
43:2a7da56ebd24 | 293 | """ |
theotherjimmy |
43:2a7da56ebd24 | 294 | Generate the CCES project files using headless builder. |
theotherjimmy |
43:2a7da56ebd24 | 295 | """ |
theotherjimmy |
43:2a7da56ebd24 | 296 | |
theotherjimmy |
43:2a7da56ebd24 | 297 | self.resources.win_to_unix() |
theotherjimmy |
43:2a7da56ebd24 | 298 | |
theotherjimmy |
43:2a7da56ebd24 | 299 | asm_defines = self.toolchain.get_symbols(True) |
theotherjimmy |
43:2a7da56ebd24 | 300 | c_defines = self.toolchain.get_symbols() |
theotherjimmy |
43:2a7da56ebd24 | 301 | |
theotherjimmy |
43:2a7da56ebd24 | 302 | include_dirs = [self.format_inc_path(d) for d \ |
theotherjimmy |
43:2a7da56ebd24 | 303 | in self.resources.inc_dirs if d] |
theotherjimmy |
43:2a7da56ebd24 | 304 | |
theotherjimmy |
43:2a7da56ebd24 | 305 | srcs = self.resources.s_sources + \ |
theotherjimmy |
43:2a7da56ebd24 | 306 | self.resources.c_sources + \ |
theotherjimmy |
43:2a7da56ebd24 | 307 | self.resources.cpp_sources + \ |
theotherjimmy |
43:2a7da56ebd24 | 308 | self.resources.headers |
theotherjimmy |
43:2a7da56ebd24 | 309 | |
theotherjimmy |
43:2a7da56ebd24 | 310 | srcs_dict = {} |
theotherjimmy |
43:2a7da56ebd24 | 311 | for src in srcs: |
theotherjimmy |
43:2a7da56ebd24 | 312 | srcs_dict[src] = self.format_src_path(src) |
theotherjimmy |
43:2a7da56ebd24 | 313 | |
theotherjimmy |
43:2a7da56ebd24 | 314 | ld_script = self.format_inc_path(self.resources.linker_script) |
theotherjimmy |
43:2a7da56ebd24 | 315 | |
theotherjimmy |
43:2a7da56ebd24 | 316 | asm_flags = self.flags['asm_flags'] |
theotherjimmy |
43:2a7da56ebd24 | 317 | c_flags = self.flags['c_flags'] + self.flags['common_flags'] |
theotherjimmy |
43:2a7da56ebd24 | 318 | cxx_flags = self.flags['cxx_flags'] + self.flags['common_flags'] |
theotherjimmy |
43:2a7da56ebd24 | 319 | |
theotherjimmy |
43:2a7da56ebd24 | 320 | libs = [] |
theotherjimmy |
43:2a7da56ebd24 | 321 | for libpath in self.libraries: |
theotherjimmy |
43:2a7da56ebd24 | 322 | lib = os.path.splitext(os.path.basename(libpath))[0] |
theotherjimmy |
43:2a7da56ebd24 | 323 | libs.append(lib[3:]) # skip 'lib' prefix |
theotherjimmy |
43:2a7da56ebd24 | 324 | |
theotherjimmy |
43:2a7da56ebd24 | 325 | ld_flags = self.flags['ld_flags'] + ["-l" + lib for lib \ |
theotherjimmy |
43:2a7da56ebd24 | 326 | in self.toolchain.sys_libs] |
theotherjimmy |
43:2a7da56ebd24 | 327 | |
theotherjimmy |
43:2a7da56ebd24 | 328 | proc = self.toolchain.target.device_name |
theotherjimmy |
43:2a7da56ebd24 | 329 | cpu = self.toolchain.target.core.lower() |
theotherjimmy |
43:2a7da56ebd24 | 330 | fpu = None |
theotherjimmy |
43:2a7da56ebd24 | 331 | float_abi = None |
theotherjimmy |
43:2a7da56ebd24 | 332 | |
theotherjimmy |
43:2a7da56ebd24 | 333 | # parse toolchain CPU flags |
theotherjimmy |
43:2a7da56ebd24 | 334 | for flag in self.toolchain.cpu: |
theotherjimmy |
43:2a7da56ebd24 | 335 | if flag.startswith("-mcpu="): |
theotherjimmy |
43:2a7da56ebd24 | 336 | cpu = flag[len("-mcpu="):] |
theotherjimmy |
43:2a7da56ebd24 | 337 | elif flag.startswith("-mfpu="): |
theotherjimmy |
43:2a7da56ebd24 | 338 | fpu = flag[len("-mfpu="):] |
theotherjimmy |
43:2a7da56ebd24 | 339 | elif flag.startswith("-mfloat-abi="): |
theotherjimmy |
43:2a7da56ebd24 | 340 | float_abi = flag[len("-mfloat-abi="):] |
theotherjimmy |
43:2a7da56ebd24 | 341 | |
theotherjimmy |
43:2a7da56ebd24 | 342 | # remove toolchain CPU flags. We'll handle them separately |
theotherjimmy |
43:2a7da56ebd24 | 343 | # in the generated .json file |
theotherjimmy |
43:2a7da56ebd24 | 344 | self.clean_flags(c_flags, self.toolchain.cpu) |
theotherjimmy |
43:2a7da56ebd24 | 345 | self.clean_flags(cxx_flags, self.toolchain.cpu) |
theotherjimmy |
43:2a7da56ebd24 | 346 | self.clean_flags(ld_flags, self.toolchain.cpu) |
theotherjimmy |
43:2a7da56ebd24 | 347 | |
theotherjimmy |
43:2a7da56ebd24 | 348 | ld_opts = self.convert_linker_options(ld_flags) |
theotherjimmy |
43:2a7da56ebd24 | 349 | asm_opts = self.convert_assembler_options(asm_flags) |
theotherjimmy |
43:2a7da56ebd24 | 350 | c_opts = self.convert_compiler_options(c_flags) |
theotherjimmy |
43:2a7da56ebd24 | 351 | cxx_opts = self.convert_compiler_options(cxx_flags) |
theotherjimmy |
43:2a7da56ebd24 | 352 | |
theotherjimmy |
43:2a7da56ebd24 | 353 | project = "cces" |
theotherjimmy |
43:2a7da56ebd24 | 354 | json = "cces.json" |
theotherjimmy |
43:2a7da56ebd24 | 355 | local_location = project |
theotherjimmy |
43:2a7da56ebd24 | 356 | |
theotherjimmy |
43:2a7da56ebd24 | 357 | jinja_ctx = { |
theotherjimmy |
43:2a7da56ebd24 | 358 | 'project' : self.project_name, |
theotherjimmy |
43:2a7da56ebd24 | 359 | 'cpu' : cpu, |
theotherjimmy |
43:2a7da56ebd24 | 360 | 'proc' : proc, |
theotherjimmy |
43:2a7da56ebd24 | 361 | 'family' : "ARM", |
theotherjimmy |
43:2a7da56ebd24 | 362 | 'asm_defines' : asm_defines, |
theotherjimmy |
43:2a7da56ebd24 | 363 | 'c_defines' : c_defines, |
theotherjimmy |
43:2a7da56ebd24 | 364 | 'fpu' : fpu, |
theotherjimmy |
43:2a7da56ebd24 | 365 | 'float_abi' : float_abi, |
theotherjimmy |
43:2a7da56ebd24 | 366 | 'ld_script' : ld_script, |
theotherjimmy |
43:2a7da56ebd24 | 367 | 'local_location' : local_location, |
theotherjimmy |
43:2a7da56ebd24 | 368 | 'srcs': srcs_dict, |
theotherjimmy |
43:2a7da56ebd24 | 369 | 'include_dirs' : include_dirs, |
theotherjimmy |
43:2a7da56ebd24 | 370 | 'ld_opts' : ld_opts, |
theotherjimmy |
43:2a7da56ebd24 | 371 | 'ld_flags' : ld_flags, |
theotherjimmy |
43:2a7da56ebd24 | 372 | 'asm_opts' : asm_opts, |
theotherjimmy |
43:2a7da56ebd24 | 373 | 'asm_flags' : asm_flags, |
theotherjimmy |
43:2a7da56ebd24 | 374 | 'c_opts' : c_opts, |
theotherjimmy |
43:2a7da56ebd24 | 375 | 'c_flags' : c_flags, |
theotherjimmy |
43:2a7da56ebd24 | 376 | 'cxx_opts' : cxx_opts, |
theotherjimmy |
43:2a7da56ebd24 | 377 | 'cxx_flags' : cxx_flags, |
theotherjimmy |
43:2a7da56ebd24 | 378 | } |
theotherjimmy |
43:2a7da56ebd24 | 379 | |
theotherjimmy |
43:2a7da56ebd24 | 380 | self.gen_file('cces/cces.json.tmpl', jinja_ctx, |
theotherjimmy |
43:2a7da56ebd24 | 381 | json, trim_blocks=True, lstrip_blocks=True) |
theotherjimmy |
43:2a7da56ebd24 | 382 | |
theotherjimmy |
43:2a7da56ebd24 | 383 | # generate a readme on how to create the CCES project |
theotherjimmy |
43:2a7da56ebd24 | 384 | # using the generated .json file |
theotherjimmy |
43:2a7da56ebd24 | 385 | |
theotherjimmy |
43:2a7da56ebd24 | 386 | cces_paths = { |
theotherjimmy |
43:2a7da56ebd24 | 387 | "Windows" : "%CCES_HOME%\\Eclipse\\ccesc.exe", |
theotherjimmy |
43:2a7da56ebd24 | 388 | "Linux" : "${CCES_HOME}/Eclipse/cces", |
theotherjimmy |
43:2a7da56ebd24 | 389 | "MacOS" : "${CCES_HOME}/MacOS/cces" |
theotherjimmy |
43:2a7da56ebd24 | 390 | } |
theotherjimmy |
43:2a7da56ebd24 | 391 | |
theotherjimmy |
43:2a7da56ebd24 | 392 | commands = {"create":{}, "build":{}} |
theotherjimmy |
43:2a7da56ebd24 | 393 | for operating_system, path in cces_paths.items(): |
theotherjimmy |
43:2a7da56ebd24 | 394 | commands["create"][operating_system] = \ |
theotherjimmy |
43:2a7da56ebd24 | 395 | CCES.get_project_create_command(path, \ |
theotherjimmy |
43:2a7da56ebd24 | 396 | "WORKSPACE", project) |
theotherjimmy |
43:2a7da56ebd24 | 397 | commands["build"][operating_system] = \ |
theotherjimmy |
43:2a7da56ebd24 | 398 | CCES.get_project_build_command(path, \ |
theotherjimmy |
43:2a7da56ebd24 | 399 | "WORKSPACE", project) |
theotherjimmy |
43:2a7da56ebd24 | 400 | |
theotherjimmy |
43:2a7da56ebd24 | 401 | jinja_ctx = { |
theotherjimmy |
43:2a7da56ebd24 | 402 | 'commands' : commands |
theotherjimmy |
43:2a7da56ebd24 | 403 | } |
theotherjimmy |
43:2a7da56ebd24 | 404 | |
theotherjimmy |
43:2a7da56ebd24 | 405 | self.gen_file('cces/README.md.tmpl', jinja_ctx, "README.md") |
theotherjimmy |
43:2a7da56ebd24 | 406 | |
theotherjimmy |
43:2a7da56ebd24 | 407 | print("CCES files generated.") |
theotherjimmy |
43:2a7da56ebd24 | 408 | |
theotherjimmy |
43:2a7da56ebd24 | 409 | |
theotherjimmy |
43:2a7da56ebd24 | 410 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 411 | def clean(_): |
theotherjimmy |
43:2a7da56ebd24 | 412 | os.remove('cces.json') |
theotherjimmy |
43:2a7da56ebd24 | 413 | os.remove('README.md') |
theotherjimmy |
43:2a7da56ebd24 | 414 | |
theotherjimmy |
43:2a7da56ebd24 | 415 | @staticmethod |
theotherjimmy |
43:2a7da56ebd24 | 416 | def build(project_name, log_name='build_log.txt', cleanup=True): |
theotherjimmy |
43:2a7da56ebd24 | 417 | """ |
theotherjimmy |
43:2a7da56ebd24 | 418 | Build the generated CCES project using headless builder. |
theotherjimmy |
43:2a7da56ebd24 | 419 | """ |
theotherjimmy |
43:2a7da56ebd24 | 420 | # create the project by importing .json file using CCES headless builder |
theotherjimmy |
43:2a7da56ebd24 | 421 | cces_home = os.getenv("CCES_HOME") |
theotherjimmy |
43:2a7da56ebd24 | 422 | if cces_home is None: |
theotherjimmy |
43:2a7da56ebd24 | 423 | print("Failed to build project: " + \ |
theotherjimmy |
43:2a7da56ebd24 | 424 | "'CCES_HOME' environment variable not defined.") |
theotherjimmy |
43:2a7da56ebd24 | 425 | return -1 |
theotherjimmy |
43:2a7da56ebd24 | 426 | |
theotherjimmy |
43:2a7da56ebd24 | 427 | cces_path = CCES.get_cces_path(cces_home) |
theotherjimmy |
43:2a7da56ebd24 | 428 | if cces_path is None: |
theotherjimmy |
43:2a7da56ebd24 | 429 | return -1 |
theotherjimmy |
43:2a7da56ebd24 | 430 | |
theotherjimmy |
43:2a7da56ebd24 | 431 | workspace = tempfile.mkdtemp() |
theotherjimmy |
43:2a7da56ebd24 | 432 | |
theotherjimmy |
43:2a7da56ebd24 | 433 | cmd = CCES.get_project_create_command(cces_path, workspace, \ |
theotherjimmy |
43:2a7da56ebd24 | 434 | project_name) |
theotherjimmy |
43:2a7da56ebd24 | 435 | print(cmd) |
theotherjimmy |
43:2a7da56ebd24 | 436 | process = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) |
theotherjimmy |
43:2a7da56ebd24 | 437 | out, err = process.communicate() |
theotherjimmy |
43:2a7da56ebd24 | 438 | ret_code = process.returncode |
theotherjimmy |
43:2a7da56ebd24 | 439 | |
theotherjimmy |
43:2a7da56ebd24 | 440 | # cleanup workspace |
theotherjimmy |
43:2a7da56ebd24 | 441 | if os.path.exists(workspace): |
theotherjimmy |
43:2a7da56ebd24 | 442 | shutil.rmtree(workspace, True) |
theotherjimmy |
43:2a7da56ebd24 | 443 | CCES.clean(project_name) |
theotherjimmy |
43:2a7da56ebd24 | 444 | |
theotherjimmy |
43:2a7da56ebd24 | 445 | # check return code for failure |
theotherjimmy |
43:2a7da56ebd24 | 446 | if ret_code != 0: |
theotherjimmy |
43:2a7da56ebd24 | 447 | for line in out.split("\n"): |
theotherjimmy |
43:2a7da56ebd24 | 448 | print(line) |
theotherjimmy |
43:2a7da56ebd24 | 449 | for line in err.split("\n"): |
theotherjimmy |
43:2a7da56ebd24 | 450 | print(line) |
theotherjimmy |
43:2a7da56ebd24 | 451 | |
theotherjimmy |
43:2a7da56ebd24 | 452 | print("Failed to create project. Return code: %d" % ret_code) |
theotherjimmy |
43:2a7da56ebd24 | 453 | return -1 |
theotherjimmy |
43:2a7da56ebd24 | 454 | |
theotherjimmy |
43:2a7da56ebd24 | 455 | # build the project |
theotherjimmy |
43:2a7da56ebd24 | 456 | workspace = tempfile.mkdtemp() |
theotherjimmy |
43:2a7da56ebd24 | 457 | |
theotherjimmy |
43:2a7da56ebd24 | 458 | cmd = CCES.get_project_build_command(cces_path, workspace, project_name) |
theotherjimmy |
43:2a7da56ebd24 | 459 | print(cmd) |
theotherjimmy |
43:2a7da56ebd24 | 460 | process = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) |
theotherjimmy |
43:2a7da56ebd24 | 461 | out, err = process.communicate() |
theotherjimmy |
43:2a7da56ebd24 | 462 | ret_code = process.returncode |
theotherjimmy |
43:2a7da56ebd24 | 463 | |
theotherjimmy |
43:2a7da56ebd24 | 464 | if log_name: |
theotherjimmy |
43:2a7da56ebd24 | 465 | with open(log_name, 'w+') as log_file: |
theotherjimmy |
43:2a7da56ebd24 | 466 | log_file.write(out) |
theotherjimmy |
43:2a7da56ebd24 | 467 | log_file.write(err) |
theotherjimmy |
43:2a7da56ebd24 | 468 | if ret_code != 0: |
theotherjimmy |
43:2a7da56ebd24 | 469 | log_file.write("Failed to build project. Return code: %d"\ |
theotherjimmy |
43:2a7da56ebd24 | 470 | % ret_code) |
theotherjimmy |
43:2a7da56ebd24 | 471 | |
theotherjimmy |
43:2a7da56ebd24 | 472 | # cleanup workspace |
theotherjimmy |
43:2a7da56ebd24 | 473 | if os.path.exists(workspace): |
theotherjimmy |
43:2a7da56ebd24 | 474 | shutil.rmtree(workspace) |
theotherjimmy |
43:2a7da56ebd24 | 475 | |
theotherjimmy |
43:2a7da56ebd24 | 476 | # check return code for failure |
theotherjimmy |
43:2a7da56ebd24 | 477 | if ret_code == 0: |
theotherjimmy |
43:2a7da56ebd24 | 478 | return 0 |
theotherjimmy |
43:2a7da56ebd24 | 479 | |
theotherjimmy |
43:2a7da56ebd24 | 480 | for line in out.split("\n"): |
theotherjimmy |
43:2a7da56ebd24 | 481 | print(line) |
theotherjimmy |
43:2a7da56ebd24 | 482 | for line in err.split("\n"): |
theotherjimmy |
43:2a7da56ebd24 | 483 | print(line) |
theotherjimmy |
43:2a7da56ebd24 | 484 | |
theotherjimmy |
43:2a7da56ebd24 | 485 | print("Failed to build project. Return code: %d" % ret_code) |
theotherjimmy |
43:2a7da56ebd24 | 486 | return -1 |