Skip to content

Commit 9d33fe8

Browse files
committed
Merge pull request #70 from screamerbg/build-static-libs
Support for compiling static libraries via build.py
2 parents f712259 + 34ec829 commit 9d33fe8

File tree

7 files changed

+100
-48
lines changed

7 files changed

+100
-48
lines changed

tools/build.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from tools.toolchains import TOOLCHAINS
3131
from tools.targets import TARGET_NAMES, TARGET_MAP
3232
from tools.options import get_default_options_parser
33-
from tools.build_api import build_mbed_libs, build_lib
33+
from tools.build_api import build_library, build_mbed_libs, build_lib
3434
from tools.build_api import mcu_toolchain_matrix
3535
from tools.build_api import static_analysis_scan, static_analysis_scan_lib, static_analysis_scan_library
3636
from tools.build_api import print_build_results
@@ -42,6 +42,15 @@
4242
# Parse Options
4343
parser = get_default_options_parser()
4444

45+
parser.add_option("--source", dest="source_dir",
46+
default=None, help="The source (input) directory", action="append")
47+
48+
parser.add_option("--build", dest="build_dir",
49+
default=None, help="The build (output) directory")
50+
51+
parser.add_option("--no-archive", dest="no_archive", action="store_true",
52+
default=False, help="Do not produce archive (.ar) file, but rather .o")
53+
4554
# Extra libraries
4655
parser.add_option("-r", "--rtos",
4756
action="store_true",
@@ -119,7 +128,7 @@
119128
help='For some commands you can use filter to filter out results')
120129

121130
parser.add_option("-j", "--jobs", type="int", dest="jobs",
122-
default=1, help="Number of concurrent jobs (default 1). Use 0 for auto based on host machine's number of CPUs")
131+
default=0, help="Number of concurrent jobs. Default: 0/auto (based on host machine's number of CPUs)")
123132

124133
parser.add_option("-v", "--verbose",
125134
action="store_true",
@@ -224,13 +233,14 @@
224233
tt_id = "%s::%s" % (toolchain, target)
225234
try:
226235
mcu = TARGET_MAP[target]
227-
lib_build_res = build_mbed_libs(mcu, toolchain,
236+
lib_build_res = build_library(options.source_dir, options.build_dir, mcu, toolchain,
228237
options=options.options,
229238
extra_verbose=options.extra_verbose_notify,
230239
verbose=options.verbose,
231240
silent=options.silent,
232241
jobs=options.jobs,
233242
clean=options.clean,
243+
archive=(not options.no_archive),
234244
macros=options.macros)
235245
for lib_id in libraries:
236246
build_lib(lib_id, mcu, toolchain,

tools/build_api.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
from types import ListType
2424
from shutil import rmtree
25-
from os.path import join, exists, basename
25+
from os.path import join, exists, basename, abspath
2626
from os import getcwd
2727
from time import time
2828

@@ -188,7 +188,7 @@ def build_project(src_path, build_path, target, toolchain_name,
188188

189189

190190
def build_library(src_paths, build_path, target, toolchain_name,
191-
dependencies_paths=None, options=None, name=None, clean=False,
191+
dependencies_paths=None, options=None, name=None, clean=False, archive=True,
192192
notify=None, verbose=False, macros=None, inc_dirs=None, inc_dirs_ext=None,
193193
jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
194194
""" src_path: the path of the source directory
@@ -206,7 +206,10 @@ def build_library(src_paths, build_path, target, toolchain_name,
206206
src_paths = [src_paths]
207207

208208
# The first path will give the name to the library
209-
name = basename(src_paths[0])
209+
project_name = basename(src_paths[0] if src_paths[0] != "." and src_paths[0] != "./" else getcwd())
210+
if name is None:
211+
# We will use default project name based on project folder name
212+
name = project_name
210213

211214
if report != None:
212215
start = time()
@@ -238,7 +241,7 @@ def build_library(src_paths, build_path, target, toolchain_name,
238241
toolchain.jobs = jobs
239242
toolchain.build_all = clean
240243

241-
toolchain.info("Building library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
244+
toolchain.info("Building library %s (%s, %s)" % (name, target.name, toolchain_name))
242245

243246
# Scan Resources
244247
resources = []
@@ -262,23 +265,30 @@ def build_library(src_paths, build_path, target, toolchain_name,
262265
if inc_dirs:
263266
dependencies_include_dir.extend(inc_dirs)
264267

265-
# Create the desired build directory structure
266-
bin_path = join(build_path, toolchain.obj_path)
267-
mkdir(bin_path)
268-
tmp_path = join(build_path, '.temp', toolchain.obj_path)
269-
mkdir(tmp_path)
268+
if archive:
269+
# Use temp path when building archive
270+
tmp_path = join(build_path, '.temp')
271+
mkdir(tmp_path)
272+
else:
273+
tmp_path = build_path
270274

271-
# Copy Headers
275+
# Copy headers, objects and static libraries
272276
for resource in resources:
273277
toolchain.copy_files(resource.headers, build_path, rel_path=resource.base_path)
274-
dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
278+
toolchain.copy_files(resource.objects, build_path, rel_path=resource.base_path)
279+
toolchain.copy_files(resource.libraries, build_path, rel_path=resource.base_path)
280+
if resource.linker_script:
281+
toolchain.copy_files(resource.linker_script, build_path, rel_path=resource.base_path)
275282

276283
# Compile Sources
277284
objects = []
278285
for resource in resources:
279-
objects.extend(toolchain.compile_sources(resource, tmp_path, dependencies_include_dir))
286+
objects.extend(toolchain.compile_sources(resource, abspath(tmp_path), dependencies_include_dir))
280287

281-
needed_update = toolchain.build_library(objects, bin_path, name)
288+
if archive:
289+
needed_update = toolchain.build_library(objects, build_path, name)
290+
else:
291+
needed_update = True
282292

283293
if report != None and needed_update:
284294
end = time()

tools/make.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
type="int",
6464
dest="jobs",
6565
default=1,
66-
help="Number of concurrent jobs (default 1). Use 0 for auto based on host machine's number of CPUs")
66+
help="Number of concurrent jobs. Default: 0/auto (based on host machine's number of CPUs)")
6767

6868
parser.add_option("-v", "--verbose",
6969
action="store_true",

tools/toolchains/__init__.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -472,12 +472,7 @@ def copy_files(self, files_paths, trg_path, rel_path=None):
472472
def relative_object_path(self, build_path, base_dir, source):
473473
source_dir, name, _ = split_path(source)
474474

475-
if build_path.startswith(base_dir):
476-
# absolute path
477-
obj_dir = join(build_path, relpath(source_dir, base_dir))
478-
else:
479-
# relative path
480-
obj_dir = join(base_dir, build_path)
475+
obj_dir = join(build_path, relpath(source_dir, base_dir))
481476
mkdir(obj_dir)
482477
return join(obj_dir, name + '.o')
483478

tools/toolchains/arm.py

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

2020
from tools.toolchains import mbedToolchain
21-
from tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB
21+
from tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB, GOANNA_PATH
2222
from tools.hooks import hook_tool
23-
from tools.settings import GOANNA_PATH
23+
from tools.utils import mkdir
2424

2525
class ARM(mbedToolchain):
2626
LINKER_EXT = '.sct'
@@ -115,13 +115,12 @@ def parse_output(self, output):
115115
def get_dep_opt(self, dep_path):
116116
return ["--depend", dep_path]
117117

118-
def archive(self, objects, lib_path):
119-
self.default_cmd([self.ar, '-r', lib_path] + objects)
120-
121118
@hook_tool
122119
def assemble(self, source, object, includes):
123120
# Preprocess first, then assemble
124-
tempfile = object + '.E.s'
121+
dir = join(dirname(object), '.temp')
122+
mkdir(dir)
123+
tempfile = join(dir, basename(object) + '.E.s')
125124

126125
# Build preprocess assemble command
127126
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]
@@ -159,13 +158,27 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
159158
cmd_linker = cmd[0]
160159
cmd_list = []
161160
for c in cmd[1:]:
162-
cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
161+
if c:
162+
cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
163163
string = " ".join(cmd_list).replace("\\", "/")
164164
f.write(string)
165165

166166
# Exec command
167167
self.default_cmd([cmd_linker, '--via', link_files])
168168

169+
@hook_tool
170+
def archive(self, objects, lib_path):
171+
archive_files = join(dirname(lib_path), ".archive_files.txt")
172+
with open(archive_files, "wb") as f:
173+
o_list = []
174+
for o in objects:
175+
o_list.append('"%s"' % o)
176+
string = " ".join(o_list).replace("\\", "/")
177+
f.write(string)
178+
179+
# Exec command
180+
self.default_cmd([self.ar, '-r', lib_path, '--via', archive_files])
181+
169182
@hook_tool
170183
def binary(self, resources, elf, bin):
171184
# Build binary command

tools/toolchains/gcc.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,6 @@ def parse_output(self, output):
161161
message + match.group('message')
162162
)
163163

164-
def archive(self, objects, lib_path):
165-
# Build archive command
166-
cmd = [self.ar, "rcs", lib_path] + objects
167-
168-
# Exec cmd
169-
self.default_cmd(cmd)
170-
171164
@hook_tool
172165
def assemble(self, source, object, includes):
173166
# Build assemble command
@@ -195,7 +188,11 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
195188
libs.extend(libs)
196189

197190
# Build linker command
198-
cmd = self.ld + ["-T", mem_map, "-o", output] + objects
191+
cmd = self.ld + ["-o", output] + objects
192+
193+
if mem_map:
194+
cmd.extend(['-T', mem_map])
195+
199196
for L in lib_dirs:
200197
cmd.extend(['-L', L])
201198
cmd.extend(libs)
@@ -209,13 +206,27 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
209206
cmd_linker = cmd[0]
210207
cmd_list = []
211208
for c in cmd[1:]:
212-
cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
209+
if c:
210+
cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
213211
string = " ".join(cmd_list).replace("\\", "/")
214212
f.write(string)
215213

216214
# Exec command
217215
self.default_cmd([cmd_linker, "@%s" % link_files])
218216

217+
@hook_tool
218+
def archive(self, objects, lib_path):
219+
archive_files = join(dirname(lib_path), ".archive_files.txt")
220+
with open(archive_files, "wb") as f:
221+
o_list = []
222+
for o in objects:
223+
o_list.append('"%s"' % o)
224+
string = " ".join(o_list).replace("\\", "/")
225+
f.write(string)
226+
227+
# Exec command
228+
self.default_cmd([self.ar, 'rcs', lib_path, "@%s" % archive_files])
229+
219230
@hook_tool
220231
def binary(self, resources, elf, bin):
221232
# Build binary command

tools/toolchains/iar.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,13 @@ def assemble(self, source, object, includes):
114114
# Return command array, don't execute
115115
return [cmd]
116116

117-
@hook_tool
118-
def archive(self, objects, lib_path):
119-
if exists(lib_path):
120-
remove(lib_path)
121-
self.default_cmd([self.ar, lib_path] + objects)
122-
123117
@hook_tool
124118
def link(self, output, objects, libraries, lib_dirs, mem_map):
125119
# Build linker command
126-
cmd = [self.ld, "-o", output, "--config", mem_map, "--skip_dynamic_initialization"] + objects + libraries
120+
cmd = [self.ld, "-o", output, "--skip_dynamic_initialization"] + objects + libraries
121+
122+
if mem_map:
123+
args.extend(["--config", mem_map])
127124

128125
# Call cmdline hook
129126
cmd = self.hook.get_cmdline_linker(cmd)
@@ -134,13 +131,29 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
134131
cmd_linker = cmd[0]
135132
cmd_list = []
136133
for c in cmd[1:]:
137-
cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
134+
if c:
135+
cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
138136
string = " ".join(cmd_list).replace("\\", "/")
139137
f.write(string)
140138

141139
# Exec command
142140
self.default_cmd([cmd_linker, '-f', link_files])
143141

142+
@hook_tool
143+
def archive(self, objects, lib_path):
144+
archive_files = join(dirname(lib_path), ".archive_files.txt")
145+
with open(archive_files, "wb") as f:
146+
o_list = []
147+
for o in objects:
148+
o_list.append('"%s"' % o)
149+
string = " ".join(o_list).replace("\\", "/")
150+
f.write(string)
151+
152+
if exists(lib_path):
153+
remove(lib_path)
154+
155+
self.default_cmd([self.ar, lib_path, '-f', archive_files])
156+
144157
@hook_tool
145158
def binary(self, resources, elf, bin):
146159
# Build binary command

0 commit comments

Comments
 (0)