2013-08-06 13:38:00 +00:00
|
|
|
"""
|
|
|
|
mbed SDK
|
2016-07-26 20:30:59 +00:00
|
|
|
Copyright (c) 2011-2016 ARM Limited
|
2013-08-06 13:38:00 +00:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
"""
|
2016-08-17 19:39:31 +00:00
|
|
|
from os.path import splitext, basename, relpath, join, abspath, dirname,\
|
|
|
|
exists
|
2016-10-31 21:00:15 +00:00
|
|
|
from os import remove
|
|
|
|
import sys
|
|
|
|
from subprocess import check_output, CalledProcessError, Popen, PIPE
|
|
|
|
import shutil
|
2016-08-22 22:30:38 +00:00
|
|
|
from jinja2.exceptions import TemplateNotFound
|
2016-08-22 14:27:40 +00:00
|
|
|
from tools.export.exporters import Exporter
|
2016-08-22 20:58:30 +00:00
|
|
|
from tools.utils import NotSupportedException
|
2016-08-22 21:24:01 +00:00
|
|
|
from tools.targets import TARGET_MAP
|
2013-02-18 15:32:11 +00:00
|
|
|
|
|
|
|
|
2016-08-22 20:58:30 +00:00
|
|
|
class Makefile(Exporter):
|
2016-08-22 22:30:38 +00:00
|
|
|
"""Generic Makefile template that mimics the behavior of the python build
|
|
|
|
system
|
|
|
|
"""
|
2014-05-29 13:42:03 +00:00
|
|
|
|
2013-02-18 15:32:11 +00:00
|
|
|
DOT_IN_RELATIVE_PATH = True
|
2014-05-29 13:42:03 +00:00
|
|
|
|
2016-06-27 15:40:32 +00:00
|
|
|
MBED_CONFIG_HEADER_SUPPORTED = True
|
2016-06-20 19:28:55 +00:00
|
|
|
|
2013-02-18 15:32:11 +00:00
|
|
|
def generate(self):
|
2016-08-22 22:30:38 +00:00
|
|
|
"""Generate the makefile
|
|
|
|
|
|
|
|
Note: subclasses should not need to override this method
|
|
|
|
"""
|
2016-12-20 20:11:58 +00:00
|
|
|
if not self.resources.linker_script:
|
|
|
|
raise NotSupportedException("No linker script found.")
|
|
|
|
|
2016-07-06 18:54:33 +00:00
|
|
|
self.resources.win_to_unix()
|
2014-05-29 13:42:03 +00:00
|
|
|
|
2016-08-22 22:30:38 +00:00
|
|
|
to_be_compiled = [splitext(src)[0] + ".o" for src in
|
2016-08-23 23:50:55 +00:00
|
|
|
self.resources.s_sources +
|
|
|
|
self.resources.c_sources +
|
|
|
|
self.resources.cpp_sources]
|
2014-05-29 13:42:03 +00:00
|
|
|
|
2016-10-19 18:57:40 +00:00
|
|
|
libraries = [self.prepare_lib(basename(lib)) for lib
|
2016-10-18 15:30:46 +00:00
|
|
|
in self.resources.libraries]
|
2017-01-17 17:52:41 +00:00
|
|
|
sys_libs = [self.prepare_sys_lib(lib) for lib
|
|
|
|
in self.toolchain.sys_libs]
|
2014-05-29 13:42:03 +00:00
|
|
|
|
2013-02-18 15:32:11 +00:00
|
|
|
ctx = {
|
2016-07-20 19:43:09 +00:00
|
|
|
'name': self.project_name,
|
2013-02-18 15:32:11 +00:00
|
|
|
'to_be_compiled': to_be_compiled,
|
|
|
|
'object_files': self.resources.objects,
|
2016-08-22 22:30:38 +00:00
|
|
|
'include_paths': list(set(self.resources.inc_dirs)),
|
2013-02-18 15:32:11 +00:00
|
|
|
'library_paths': self.resources.lib_dirs,
|
|
|
|
'linker_script': self.resources.linker_script,
|
|
|
|
'libraries': libraries,
|
2017-01-17 17:52:41 +00:00
|
|
|
'ld_sys_libs': sys_libs,
|
2016-07-20 19:43:09 +00:00
|
|
|
'hex_files': self.resources.hex_files,
|
2016-08-22 14:27:40 +00:00
|
|
|
'vpath': (["../../.."]
|
2016-08-22 22:30:38 +00:00
|
|
|
if (basename(dirname(dirname(self.export_dir)))
|
|
|
|
== "projectfiles")
|
2016-08-22 20:58:30 +00:00
|
|
|
else [".."]),
|
2016-09-21 16:30:05 +00:00
|
|
|
'cc_cmd': " ".join(["\'" + part + "\'" for part
|
2016-11-02 22:16:35 +00:00
|
|
|
in ([basename(self.toolchain.cc[0])] +
|
|
|
|
self.toolchain.cc[1:])]),
|
2016-09-21 16:30:05 +00:00
|
|
|
'cppc_cmd': " ".join(["\'" + part + "\'" for part
|
2016-11-02 22:16:35 +00:00
|
|
|
in ([basename(self.toolchain.cppc[0])] +
|
|
|
|
self.toolchain.cppc[1:])]),
|
2016-09-21 16:30:05 +00:00
|
|
|
'asm_cmd': " ".join(["\'" + part + "\'" for part
|
2016-11-02 22:16:35 +00:00
|
|
|
in ([basename(self.toolchain.asm[0])] +
|
|
|
|
self.toolchain.asm[1:])]),
|
2016-09-21 16:30:05 +00:00
|
|
|
'ld_cmd': " ".join(["\'" + part + "\'" for part
|
2016-11-02 22:16:35 +00:00
|
|
|
in ([basename(self.toolchain.ld[0])] +
|
|
|
|
self.toolchain.ld[1:])]),
|
|
|
|
'elf2bin_cmd': "\'" + basename(self.toolchain.elf2bin) + "\'",
|
2016-08-22 20:58:30 +00:00
|
|
|
'link_script_ext': self.toolchain.LINKER_EXT,
|
|
|
|
'link_script_option': self.LINK_SCRIPT_OPTION,
|
2016-10-19 18:57:40 +00:00
|
|
|
'user_library_flag': self.USER_LIBRARY_FLAG,
|
2013-02-18 15:32:11 +00:00
|
|
|
}
|
2016-07-05 16:51:27 +00:00
|
|
|
|
2016-08-22 22:30:38 +00:00
|
|
|
for key in ['include_paths', 'library_paths', 'linker_script',
|
|
|
|
'hex_files']:
|
2016-07-05 16:51:27 +00:00
|
|
|
if isinstance(ctx[key], list):
|
|
|
|
ctx[key] = [ctx['vpath'][0] + "/" + t for t in ctx[key]]
|
|
|
|
else:
|
|
|
|
ctx[key] = ctx['vpath'][0] + "/" + ctx[key]
|
|
|
|
if "../." not in ctx["include_paths"]:
|
|
|
|
ctx["include_paths"] += ['../.']
|
2016-08-22 22:30:38 +00:00
|
|
|
for key in ['include_paths', 'library_paths', 'hex_files',
|
2016-08-23 23:50:55 +00:00
|
|
|
'to_be_compiled']:
|
2016-08-22 20:58:30 +00:00
|
|
|
ctx[key] = sorted(ctx[key])
|
2016-07-20 19:43:09 +00:00
|
|
|
ctx.update(self.flags)
|
2016-08-22 20:58:30 +00:00
|
|
|
|
|
|
|
for templatefile in \
|
2016-11-02 20:42:30 +00:00
|
|
|
['makefile/%s_%s.tmpl' % (self.TEMPLATE,
|
2016-08-22 20:58:30 +00:00
|
|
|
self.target.lower())] + \
|
2016-11-02 20:42:30 +00:00
|
|
|
['makefile/%s_%s.tmpl' % (self.TEMPLATE,
|
2016-08-22 20:58:30 +00:00
|
|
|
label.lower()) for label
|
|
|
|
in self.toolchain.target.extra_labels] +\
|
2016-11-02 20:42:30 +00:00
|
|
|
['makefile/%s.tmpl' % self.TEMPLATE]:
|
2016-08-22 20:58:30 +00:00
|
|
|
try:
|
|
|
|
self.gen_file(templatefile, ctx, 'Makefile')
|
|
|
|
break
|
|
|
|
except TemplateNotFound:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
raise NotSupportedException("This make tool is in development")
|
|
|
|
|
2016-10-31 21:00:15 +00:00
|
|
|
@staticmethod
|
2016-10-31 21:47:27 +00:00
|
|
|
def build(project_name, log_name="build_log.txt", cleanup=True):
|
2016-10-31 21:00:15 +00:00
|
|
|
""" Build Make project """
|
2016-11-01 16:18:40 +00:00
|
|
|
# > Make -j
|
2016-10-31 21:00:15 +00:00
|
|
|
cmd = ["make", "-j"]
|
2016-11-03 18:13:50 +00:00
|
|
|
|
|
|
|
# Build the project
|
2016-10-31 21:00:15 +00:00
|
|
|
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
2016-11-03 18:13:50 +00:00
|
|
|
out, err = p.communicate()
|
2016-10-31 21:00:15 +00:00
|
|
|
ret_code = p.returncode
|
|
|
|
|
2016-11-03 18:13:50 +00:00
|
|
|
out_string = "=" * 10 + "STDOUT" + "=" * 10 + "\n"
|
|
|
|
out_string += out
|
|
|
|
out_string += "=" * 10 + "STDERR" + "=" * 10 + "\n"
|
|
|
|
out_string += err
|
|
|
|
|
|
|
|
if ret_code == 0:
|
|
|
|
out_string += "SUCCESS"
|
|
|
|
else:
|
|
|
|
out_string += "FAILURE"
|
|
|
|
|
|
|
|
print out_string
|
|
|
|
|
|
|
|
if log_name:
|
|
|
|
# Write the output to the log file
|
|
|
|
with open(log_name, 'w+') as f:
|
|
|
|
f.write(out_string)
|
|
|
|
|
|
|
|
# Cleanup the exported and built files
|
2016-10-31 21:47:27 +00:00
|
|
|
if cleanup:
|
2016-10-31 21:00:15 +00:00
|
|
|
remove("Makefile")
|
2016-10-31 21:47:27 +00:00
|
|
|
remove(log_name)
|
2016-11-18 05:49:49 +00:00
|
|
|
# legacy .build directory cleaned if exists
|
2016-10-31 21:00:15 +00:00
|
|
|
if exists('.build'):
|
|
|
|
shutil.rmtree('.build')
|
2016-11-18 05:49:49 +00:00
|
|
|
if exists('BUILD'):
|
|
|
|
shutil.rmtree('BUILD')
|
2016-11-03 18:13:50 +00:00
|
|
|
|
2016-10-31 21:00:15 +00:00
|
|
|
if ret_code != 0:
|
|
|
|
# Seems like something went wrong.
|
|
|
|
return -1
|
2016-11-03 18:13:50 +00:00
|
|
|
else:
|
|
|
|
return 0
|
2016-10-31 21:00:15 +00:00
|
|
|
|
2016-08-22 20:58:30 +00:00
|
|
|
|
2016-08-22 22:30:38 +00:00
|
|
|
class GccArm(Makefile):
|
|
|
|
"""GCC ARM specific makefile target"""
|
2016-08-22 21:24:01 +00:00
|
|
|
TARGETS = [target for target, obj in TARGET_MAP.iteritems()
|
|
|
|
if "GCC_ARM" in obj.supported_toolchains]
|
2016-08-22 20:58:30 +00:00
|
|
|
NAME = 'Make-GCC-ARM'
|
2016-11-02 20:42:30 +00:00
|
|
|
TEMPLATE = 'make-gcc-arm'
|
2016-08-22 20:58:30 +00:00
|
|
|
TOOLCHAIN = "GCC_ARM"
|
|
|
|
LINK_SCRIPT_OPTION = "-T"
|
2016-10-19 18:57:40 +00:00
|
|
|
USER_LIBRARY_FLAG = "-L"
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def prepare_lib(libname):
|
|
|
|
return "-l:" + libname
|
2016-08-22 20:58:30 +00:00
|
|
|
|
2017-01-17 17:52:41 +00:00
|
|
|
@staticmethod
|
|
|
|
def prepare_sys_lib(libname):
|
|
|
|
return "-l" + libname
|
|
|
|
|
2016-08-22 20:58:30 +00:00
|
|
|
|
2016-08-22 22:30:38 +00:00
|
|
|
class Armc5(Makefile):
|
|
|
|
"""ARM Compiler 5 specific makefile target"""
|
2016-08-22 21:24:01 +00:00
|
|
|
TARGETS = [target for target, obj in TARGET_MAP.iteritems()
|
|
|
|
if "ARM" in obj.supported_toolchains]
|
2016-08-22 20:58:30 +00:00
|
|
|
NAME = 'Make-ARMc5'
|
2016-11-02 20:42:30 +00:00
|
|
|
TEMPLATE = 'make-armc5'
|
2016-08-22 20:58:30 +00:00
|
|
|
TOOLCHAIN = "ARM"
|
|
|
|
LINK_SCRIPT_OPTION = "--scatter"
|
2016-10-19 18:57:40 +00:00
|
|
|
USER_LIBRARY_FLAG = "--userlibpath "
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def prepare_lib(libname):
|
|
|
|
return libname
|
2016-08-22 20:58:30 +00:00
|
|
|
|
2017-01-17 17:52:41 +00:00
|
|
|
@staticmethod
|
|
|
|
def prepare_sys_lib(libname):
|
|
|
|
return libname
|
|
|
|
|
2016-08-22 20:58:30 +00:00
|
|
|
|
2016-08-22 22:30:38 +00:00
|
|
|
class IAR(Makefile):
|
|
|
|
"""IAR specific makefile target"""
|
2016-08-22 21:24:01 +00:00
|
|
|
TARGETS = [target for target, obj in TARGET_MAP.iteritems()
|
|
|
|
if "IAR" in obj.supported_toolchains]
|
2016-08-22 20:58:30 +00:00
|
|
|
NAME = 'Make-IAR'
|
2016-11-02 20:42:30 +00:00
|
|
|
TEMPLATE = 'make-iar'
|
2016-08-22 20:58:30 +00:00
|
|
|
TOOLCHAIN = "IAR"
|
|
|
|
LINK_SCRIPT_OPTION = "--config"
|
2016-10-19 18:57:40 +00:00
|
|
|
USER_LIBRARY_FLAG = "-L"
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def prepare_lib(libname):
|
|
|
|
if "lib" == libname[:3]:
|
|
|
|
libname = libname[3:]
|
|
|
|
return "-l" + splitext(libname)[0]
|
2017-01-17 17:52:41 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def prepare_sys_lib(libname):
|
|
|
|
if "lib" == libname[:3]:
|
|
|
|
libname = libname[3:]
|
|
|
|
return "-l" + splitext(libname)[0]
|