Skip to content

Commit 904ea44

Browse files
committed
Merge pull request #84 from screamerbg/compile-response-files
Response files for includes, de-duplicate includes and more
2 parents 27c6721 + 7e3b69e commit 904ea44

File tree

5 files changed

+124
-48
lines changed

5 files changed

+124
-48
lines changed

tools/toolchains/__init__.py

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from tools.utils import run_cmd, mkdir, rel_path, ToolException, NotSupportedException, split_path
3030
from tools.settings import BUILD_OPTIONS, MBED_ORG_USER
3131
import tools.hooks as hooks
32+
from hashlib import md5
3233

3334

3435
#Disables multiprocessing if set to higher number than the host machine CPUs
@@ -210,6 +211,7 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
210211
self.has_config = False
211212

212213
self.build_all = False
214+
self.build_dir = None
213215
self.timestamp = time()
214216
self.jobs = 1
215217

@@ -476,26 +478,43 @@ def relative_object_path(self, build_path, base_dir, source):
476478
mkdir(obj_dir)
477479
return join(obj_dir, name + '.o')
478480

481+
def get_inc_file(self, includes):
482+
include_file = join(self.build_dir, ".includes_%s.txt" % self.inc_md5)
483+
if not exists(include_file):
484+
with open(include_file, "wb") as f:
485+
cmd_list = []
486+
for c in includes:
487+
if c:
488+
cmd_list.append(('-I%s' % c).replace("\\", "/"))
489+
string = " ".join(cmd_list)
490+
f.write(string)
491+
return include_file
492+
479493
def compile_sources(self, resources, build_path, inc_dirs=None):
480494
# Web IDE progress bar for project build
481495
files_to_compile = resources.s_sources + resources.c_sources + resources.cpp_sources
482496
self.to_be_compiled = len(files_to_compile)
483497
self.compiled = 0
484498

485-
#for i in self.build_params:
486-
# self.debug(i)
487-
# self.debug("%s" % self.build_params[i])
488-
489499
inc_paths = resources.inc_dirs
490500
if inc_dirs is not None:
491501
inc_paths.extend(inc_dirs)
502+
# De-duplicate include paths
503+
inc_paths = set(inc_paths)
504+
# Sort include paths for consistency
505+
inc_paths = sorted(set(inc_paths))
506+
# Unique id of all include paths
507+
self.inc_md5 = md5(' '.join(inc_paths)).hexdigest()
508+
# Where to store response files
509+
self.build_dir = build_path
492510

493511
objects = []
494512
queue = []
495513
prev_dir = None
496514

497515
# The dependency checking for C/C++ is delegated to the compiler
498516
base_path = resources.base_path
517+
# Sort compile queue for consistency
499518
files_to_compile.sort()
500519
work_dir = getcwd()
501520

@@ -641,28 +660,6 @@ def compile_output(self, output=[]):
641660
else:
642661
raise ToolException(_stderr)
643662

644-
def compile(self, cc, source, object, includes):
645-
_, ext = splitext(source)
646-
ext = ext.lower()
647-
648-
command = cc + ['-D%s' % s for s in self.get_symbols()] + ["-I%s" % i for i in includes] + ["-o", object, source]
649-
650-
if hasattr(self, "get_dep_opt"):
651-
base, _ = splitext(object)
652-
dep_path = base + '.d'
653-
command.extend(self.get_dep_opt(dep_path))
654-
655-
if hasattr(self, "cc_extra"):
656-
command.extend(self.cc_extra(base))
657-
658-
return [command]
659-
660-
def compile_c(self, source, object, includes):
661-
return self.compile(self.cc, source, object, includes)
662-
663-
def compile_cpp(self, source, object, includes):
664-
return self.compile(self.cppc, source, object, includes)
665-
666663
def build_library(self, objects, dir, name):
667664
needed_update = False
668665
lib = self.STD_LIB_NAME % name
@@ -712,12 +709,12 @@ def link_program(self, r, tmp_path, name):
712709
return bin, needed_update
713710

714711
def default_cmd(self, command):
712+
self.debug("Command: %s"% ' '.join(command))
715713
_stdout, _stderr, _rc = run_cmd(command)
716714
# Print all warning / erros from stderr to console output
717715
for error_line in _stderr.splitlines():
718716
print error_line
719717

720-
self.debug("Command: %s"% ' '.join(command))
721718
self.debug("Return: %s"% _rc)
722719

723720
for output_line in _stdout.splitlines():

tools/toolchains/arm.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
limitations under the License.
1616
"""
1717
import re
18-
from os.path import join, dirname, basename
18+
from os.path import join, dirname, splitext, basename, exists
1919

2020
from tools.toolchains import mbedToolchain
2121
from tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB, GOANNA_PATH
@@ -78,11 +78,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
7878
self.ar = join(ARM_BIN, "armar")
7979
self.elf2bin = join(ARM_BIN, "fromelf")
8080

81-
def remove_option(self, option):
82-
for tool in [self.asm, self.cc, self.cppc]:
83-
if option in tool:
84-
tool.remove(option)
85-
8681
def parse_dependencies(self, dep_path):
8782
dependencies = []
8883
for line in open(dep_path).readlines():
@@ -112,9 +107,14 @@ def parse_output(self, output):
112107
match.group('message')
113108
)
114109

115-
def get_dep_opt(self, dep_path):
110+
def get_dep_option(self, object):
111+
base, _ = splitext(object)
112+
dep_path = base + '.d'
116113
return ["--depend", dep_path]
117114

115+
def get_compile_options(self, defines, includes):
116+
return ['-D%s' % d for d in defines] + ['--via', self.get_inc_file(includes)]
117+
118118
@hook_tool
119119
def assemble(self, source, object, includes):
120120
# Preprocess first, then assemble
@@ -123,8 +123,8 @@ def assemble(self, source, object, includes):
123123
tempfile = join(dir, basename(object) + '.E.s')
124124

125125
# Build preprocess assemble command
126-
cmd_pre = self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-E", "-o", tempfile, source]
127-
126+
cmd_pre = self.asm + self.get_compile_options(self.get_symbols(), includes) + ["-E", "-o", tempfile, source]
127+
128128
# Build main assemble command
129129
cmd = self.asm + ["-o", object, tempfile]
130130

@@ -135,6 +135,25 @@ def assemble(self, source, object, includes):
135135
# Return command array, don't execute
136136
return [cmd_pre, cmd]
137137

138+
@hook_tool
139+
def compile(self, cc, source, object, includes):
140+
# Build compile command
141+
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
142+
143+
cmd.extend(self.get_dep_option(object))
144+
145+
cmd.extend(["-o", object, source])
146+
147+
# Call cmdline hook
148+
cmd = self.hook.get_cmdline_compiler(cmd)
149+
150+
return [cmd]
151+
152+
def compile_c(self, source, object, includes):
153+
return self.compile(self.cc, source, object, includes)
154+
155+
def compile_cpp(self, source, object, includes):
156+
return self.compile(self.cppc, source, object, includes)
138157

139158
@hook_tool
140159
def link(self, output, objects, libraries, lib_dirs, mem_map):

tools/toolchains/gcc.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
limitations under the License.
1616
"""
1717
import re
18-
from os.path import join, basename, splitext, dirname
18+
from os.path import join, basename, splitext, dirname, exists
1919

2020
from tools.toolchains import mbedToolchain
2121
from tools.settings import GCC_ARM_PATH, GCC_CR_PATH
@@ -68,7 +68,7 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
6868
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
6969
"-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
7070
"-ffunction-sections", "-fdata-sections",
71-
"-MMD", "-fno-delete-null-pointer-checks", "-fomit-frame-pointer"
71+
"-fno-delete-null-pointer-checks", "-fomit-frame-pointer"
7272
] + self.cpu
7373

7474
if "save-asm" in self.options:
@@ -161,17 +161,45 @@ def parse_output(self, output):
161161
message + match.group('message')
162162
)
163163

164+
def get_dep_option(self, object):
165+
base, _ = splitext(object)
166+
dep_path = base + '.d'
167+
return ["-MD", "-MF", dep_path]
168+
169+
def get_compile_options(self, defines, includes):
170+
return ['-D%s' % d for d in defines] + ['@%s' % self.get_inc_file(includes)]
171+
164172
@hook_tool
165173
def assemble(self, source, object, includes):
166174
# Build assemble command
167-
cmd = self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source]
175+
cmd = self.asm + self.get_compile_options(self.get_symbols(), includes) + ["-o", object, source]
168176

169177
# Call cmdline hook
170178
cmd = self.hook.get_cmdline_assembler(cmd)
171179

172180
# Return command array, don't execute
173181
return [cmd]
174182

183+
@hook_tool
184+
def compile(self, cc, source, object, includes):
185+
# Build compile command
186+
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
187+
188+
cmd.extend(self.get_dep_option(object))
189+
190+
cmd.extend(["-o", object, source])
191+
192+
# Call cmdline hook
193+
cmd = self.hook.get_cmdline_compiler(cmd)
194+
195+
return [cmd]
196+
197+
def compile_c(self, source, object, includes):
198+
return self.compile(self.cc, source, object, includes)
199+
200+
def compile_cpp(self, source, object, includes):
201+
return self.compile(self.cppc, source, object, includes)
202+
175203
@hook_tool
176204
def link(self, output, objects, libraries, lib_dirs, mem_map):
177205
libs = []

tools/toolchains/iar.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"""
1717
import re
1818
from os import remove
19-
from os.path import join, exists, dirname
19+
from os.path import join, exists, dirname, splitext, exists
2020

2121
from tools.toolchains import mbedToolchain
2222
from tools.settings import IAR_PATH
@@ -72,6 +72,10 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
7272
self.ar = join(IAR_BIN, "iarchive")
7373
self.elf2bin = join(IAR_BIN, "ielftool")
7474

75+
def parse_dependencies(self, dep_path):
76+
return [path.strip() for path in open(dep_path).readlines()
77+
if (path and not path.isspace())]
78+
7579
def parse_output(self, output):
7680
for line in output.splitlines():
7781
match = IAR.DIAGNOSTIC_PATTERN.match(line)
@@ -93,27 +97,51 @@ def parse_output(self, output):
9397
match.group('message')
9498
)
9599

96-
def get_dep_opt(self, dep_path):
100+
def get_dep_option(self, object):
101+
base, _ = splitext(object)
102+
dep_path = base + '.d'
97103
return ["--dependencies", dep_path]
98104

99-
def cc_extra(self, base):
105+
def cc_extra(self, object):
106+
base, _ = splitext(object)
100107
return ["-l", base + '.s']
101108

102-
def parse_dependencies(self, dep_path):
103-
return [path.strip() for path in open(dep_path).readlines()
104-
if (path and not path.isspace())]
109+
def get_compile_options(self, defines, includes):
110+
return ['-D%s' % d for d in defines] + ['-f', self.get_inc_file(includes)]
105111

106112
@hook_tool
107113
def assemble(self, source, object, includes):
108114
# Build assemble command
109-
cmd = self.asm + ['-D%s' % s for s in self.get_symbols() + self.macros] + ["-I%s" % i for i in includes] + ["-o", object, source]
115+
cmd = self.asm + self.get_compile_options(self.get_symbols(), includes) + ["-o", object, source]
110116

111117
# Call cmdline hook
112118
cmd = self.hook.get_cmdline_assembler(cmd)
113119

114120
# Return command array, don't execute
115121
return [cmd]
116122

123+
@hook_tool
124+
def compile(self, cc, source, object, includes):
125+
# Build compile command
126+
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
127+
128+
cmd.extend(self.get_dep_option(object))
129+
130+
cmd.extend(self.cc_extra(object))
131+
132+
cmd.extend(["-o", object, source])
133+
134+
# Call cmdline hook
135+
cmd = self.hook.get_cmdline_compiler(cmd)
136+
137+
return [cmd]
138+
139+
def compile_c(self, source, object, includes):
140+
return self.compile(self.cc, source, object, includes)
141+
142+
def compile_cpp(self, source, object, includes):
143+
return self.compile(self.cppc, source, object, includes)
144+
117145
@hook_tool
118146
def link(self, output, objects, libraries, lib_dirs, mem_map):
119147
# Build linker command

tools/utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ def cmd(l, check=True, verbose=False, shell=False, cwd=None):
3434

3535
def run_cmd(command, wd=None, redirect=False):
3636
assert is_cmd_valid(command[0])
37-
p = Popen(command, stdout=PIPE, stderr=STDOUT if redirect else PIPE, cwd=wd)
38-
_stdout, _stderr = p.communicate()
37+
try:
38+
p = Popen(command, stdout=PIPE, stderr=STDOUT if redirect else PIPE, cwd=wd)
39+
_stdout, _stderr = p.communicate()
40+
except:
41+
print "[OS ERROR] Command: "+(' '.join(command))
42+
raise
3943
return _stdout, _stderr, p.returncode
4044

4145

0 commit comments

Comments
 (0)