Skip to content

Commit 432162f

Browse files
authored
Merge pull request #3997 from theotherjimmy/remove-project-api
Move contents of project_api to export/__init__.py
2 parents 8784913 + 70ac607 commit 432162f

File tree

3 files changed

+234
-263
lines changed

3 files changed

+234
-263
lines changed

tools/export/__init__.py

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
# See the License for the specific language governing permissions and
1616
# limitations under the License.
1717

18+
import sys
19+
from os.path import join, abspath, dirname, exists
20+
from os.path import basename, relpath, normpath, splitext
21+
from os import makedirs, walk
22+
import copy
23+
from shutil import rmtree
24+
import zipfile
25+
ROOT = abspath(join(dirname(__file__), ".."))
26+
sys.path.insert(0, ROOT)
27+
28+
from tools.build_api import prepare_toolchain
29+
from tools.build_api import scan_resources
30+
from tools.toolchains import Resources
1831
from tools.export import lpcxpresso, ds5_5, iar, makefile
1932
from tools.export import embitz, coide, kds, simplicity, atmelstudio
2033
from tools.export import sw4stm32, e2studio, zip, cmsis, uvision, cdt
@@ -105,3 +118,223 @@ def mcu_ide_matrix(verbose_html=False):
105118
if verbose_html:
106119
result = result.replace("&", "&")
107120
return result
121+
122+
123+
def get_exporter_toolchain(ide):
124+
""" Return the exporter class and the toolchain string as a tuple
125+
126+
Positional arguments:
127+
ide - the ide name of an exporter
128+
"""
129+
return EXPORTERS[ide], EXPORTERS[ide].TOOLCHAIN
130+
131+
132+
def rewrite_basepath(file_name, resources, export_path, loc):
133+
""" Replace the basepath of filename with export_path
134+
135+
Positional arguments:
136+
file_name - the absolute path to a file
137+
resources - the resources object that the file came from
138+
export_path - the final destination of the file after export
139+
"""
140+
new_f = join(loc, relpath(file_name, resources.file_basepath[file_name]))
141+
resources.file_basepath[join(export_path, new_f)] = export_path
142+
return new_f
143+
144+
145+
def subtract_basepath(resources, export_path, loc=""):
146+
""" Rewrite all of the basepaths with the export_path
147+
148+
Positional arguments:
149+
resources - the resource object to rewrite the basepaths of
150+
export_path - the final destination of the resources with respect to the
151+
generated project files
152+
"""
153+
keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
154+
'objects', 'libraries', 'inc_dirs', 'headers', 'linker_script',
155+
'lib_dirs']
156+
for key in keys:
157+
vals = getattr(resources, key)
158+
if isinstance(vals, set):
159+
vals = list(vals)
160+
if isinstance(vals, list):
161+
new_vals = []
162+
for val in vals:
163+
new_vals.append(rewrite_basepath(val, resources, export_path,
164+
loc))
165+
if isinstance(getattr(resources, key), set):
166+
setattr(resources, key, set(new_vals))
167+
else:
168+
setattr(resources, key, new_vals)
169+
elif vals:
170+
setattr(resources, key, rewrite_basepath(vals, resources,
171+
export_path, loc))
172+
173+
174+
def generate_project_files(resources, export_path, target, name, toolchain, ide,
175+
macros=None):
176+
"""Generate the project files for a project
177+
178+
Positional arguments:
179+
resources - a Resources object containing all of the files needed to build
180+
this project
181+
export_path - location to place project files
182+
name - name of the project
183+
toolchain - a toolchain class that corresponds to the toolchain used by the
184+
IDE or makefile
185+
ide - IDE name to export to
186+
187+
Optional arguments:
188+
macros - additional macros that should be defined within the exported
189+
project
190+
"""
191+
exporter_cls, _ = get_exporter_toolchain(ide)
192+
exporter = exporter_cls(target, export_path, name, toolchain,
193+
extra_symbols=macros, resources=resources)
194+
exporter.generate()
195+
files = exporter.generated_files
196+
return files, exporter
197+
198+
199+
def zip_export(file_name, prefix, resources, project_files, inc_repos):
200+
"""Create a zip file from an exported project.
201+
202+
Positional Parameters:
203+
file_name - the file name of the resulting zip file
204+
prefix - a directory name that will prefix the entire zip file's contents
205+
resources - a resources object with files that must be included in the zip
206+
project_files - a list of extra files to be added to the root of the prefix
207+
directory
208+
"""
209+
with zipfile.ZipFile(file_name, "w") as zip_file:
210+
for prj_file in project_files:
211+
zip_file.write(prj_file, join(prefix, basename(prj_file)))
212+
for loc, res in resources.iteritems():
213+
to_zip = (
214+
res.headers + res.s_sources + res.c_sources +\
215+
res.cpp_sources + res.libraries + res.hex_files + \
216+
[res.linker_script] + res.bin_files + res.objects + \
217+
res.json_files + res.lib_refs + res.lib_builds)
218+
if inc_repos:
219+
for directory in res.repo_dirs:
220+
for root, _, files in walk(directory):
221+
for repo_file in files:
222+
source = join(root, repo_file)
223+
to_zip.append(source)
224+
res.file_basepath[source] = res.base_path
225+
to_zip += res.repo_files
226+
for source in to_zip:
227+
if source:
228+
zip_file.write(
229+
source,
230+
join(prefix, loc,
231+
relpath(source, res.file_basepath[source])))
232+
for source in res.lib_builds:
233+
target_dir, _ = splitext(source)
234+
dest = join(prefix, loc,
235+
relpath(target_dir, res.file_basepath[source]),
236+
".bld", "bldrc")
237+
zip_file.write(source, dest)
238+
239+
240+
241+
def export_project(src_paths, export_path, target, ide, libraries_paths=None,
242+
linker_script=None, notify=None, verbose=False, name=None,
243+
inc_dirs=None, jobs=1, silent=False, extra_verbose=False,
244+
config=None, macros=None, zip_proj=None, inc_repos=False,
245+
build_profile=None):
246+
"""Generates a project file and creates a zip archive if specified
247+
248+
Positional Arguments:
249+
src_paths - a list of paths from which to find source files
250+
export_path - a path specifying the location of generated project files
251+
target - the mbed board/mcu for which to generate the executable
252+
ide - the ide for which to generate the project fields
253+
254+
Keyword Arguments:
255+
libraries_paths - paths to additional libraries
256+
linker_script - path to the linker script for the specified target
257+
notify - function is passed all events, and expected to handle notification
258+
of the user, emit the events to a log, etc.
259+
verbose - assigns the notify function to toolchains print_notify_verbose
260+
name - project name
261+
inc_dirs - additional include directories
262+
jobs - number of threads
263+
silent - silent build - no output
264+
extra_verbose - assigns the notify function to toolchains
265+
print_notify_verbose
266+
config - toolchain's config object
267+
macros - User-defined macros
268+
zip_proj - string name of the zip archive you wish to creat (exclude arg
269+
if you do not wish to create an archive
270+
"""
271+
272+
# Convert src_path to a list if needed
273+
if isinstance(src_paths, dict):
274+
paths = sum(src_paths.values(), [])
275+
elif isinstance(src_paths, list):
276+
paths = src_paths[:]
277+
else:
278+
paths = [src_paths]
279+
280+
# Extend src_paths wit libraries_paths
281+
if libraries_paths is not None:
282+
paths.extend(libraries_paths)
283+
284+
if not isinstance(src_paths, dict):
285+
src_paths = {"": paths}
286+
287+
# Export Directory
288+
if not exists(export_path):
289+
makedirs(export_path)
290+
291+
_, toolchain_name = get_exporter_toolchain(ide)
292+
293+
# Pass all params to the unified prepare_resources()
294+
toolchain = prepare_toolchain(
295+
paths, "", target, toolchain_name, macros=macros, jobs=jobs,
296+
notify=notify, silent=silent, verbose=verbose,
297+
extra_verbose=extra_verbose, config=config, build_profile=build_profile)
298+
# The first path will give the name to the library
299+
if name is None:
300+
name = basename(normpath(abspath(src_paths[0])))
301+
302+
# Call unified scan_resources
303+
resource_dict = {loc: scan_resources(path, toolchain, inc_dirs=inc_dirs)
304+
for loc, path in src_paths.iteritems()}
305+
resources = Resources()
306+
toolchain.build_dir = export_path
307+
config_header = toolchain.get_config_header()
308+
resources.headers.append(config_header)
309+
resources.file_basepath[config_header] = dirname(config_header)
310+
311+
if zip_proj:
312+
subtract_basepath(resources, export_path)
313+
for loc, res in resource_dict.iteritems():
314+
temp = copy.deepcopy(res)
315+
subtract_basepath(temp, export_path, loc)
316+
resources.add(temp)
317+
else:
318+
for _, res in resource_dict.iteritems():
319+
resources.add(res)
320+
321+
# Change linker script if specified
322+
if linker_script is not None:
323+
resources.linker_script = linker_script
324+
325+
files, exporter = generate_project_files(resources, export_path,
326+
target, name, toolchain, ide,
327+
macros=macros)
328+
files.append(config_header)
329+
if zip_proj:
330+
for resource in resource_dict.values():
331+
for label, res in resource.features.iteritems():
332+
if label not in toolchain.target.features:
333+
resource.add(res)
334+
if isinstance(zip_proj, basestring):
335+
zip_export(join(export_path, zip_proj), name, resource_dict, files,
336+
inc_repos)
337+
else:
338+
zip_export(zip_proj, name, resource_dict, files, inc_repos)
339+
340+
return exporter

tools/project.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212

1313
from tools.paths import EXPORT_DIR, MBED_HAL, MBED_LIBRARIES, MBED_TARGETS_PATH
1414
from tools.settings import BUILD_DIR
15-
from tools.export import EXPORTERS, mcu_ide_matrix
15+
from tools.export import EXPORTERS, mcu_ide_matrix, export_project, get_exporter_toolchain
1616
from tools.tests import TESTS, TEST_MAP
1717
from tools.tests import test_known, test_name_known, Test
1818
from tools.targets import TARGET_NAMES
1919
from tools.utils import argparse_filestring_type, argparse_profile_filestring_type, argparse_many, args_error
2020
from tools.utils import argparse_force_lowercase_type
2121
from tools.utils import argparse_force_uppercase_type
2222
from tools.utils import print_large_string
23-
from tools.project_api import export_project, get_exporter_toolchain
2423
from tools.options import extract_profile, list_profiles
2524

2625
def setup_project(ide, target, program=None, source_dir=None, build=None, export_path=None):

0 commit comments

Comments
 (0)