Skip to content

Commit 5e2fe92

Browse files
feat(hdrs_map): graceful handling of duplicates
This changeset modifies the behavior of the logic responsible for materialization of header files mappings - previously, if the mappings resulted in any duplicated file entries, the logic will error out on the built-in Bazel ctx.actions.declare_file call. With this changes, situations in which a duplicate entry might appear are detected and avoided, while user is receving a warning message. First definiton to materialize, wins. At the moment this behavior is enabled by default and non-configurable.
1 parent aa15c3a commit 5e2fe92

1 file changed

Lines changed: 39 additions & 16 deletions

File tree

cc_hdrs_map/providers/hdrs_map.bzl

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,25 @@ def _glob_match(
229229
# if it isn't, it means it was not matched
230230
return p == None
231231

232-
def _materialize_hdr_mapping(ctx_actions, parent_dir_name, source_hdr_file, mappings):
232+
def _materialize_hdr_mapping(ctx_actions, parent_dir_name, source_hdr_file, mappings, existing_paths = None):
233+
existing_paths = existing_paths if existing_paths else set()
233234
mapped_files = []
235+
234236
for mapping in mappings:
235237
# Ensure {filename} is translated to header_file name
236238
target = mapping.replace("{filename}", source_hdr_file.basename)
237239

240+
# TODO: Made this behavior configurable
241+
# It might be the case, that aggregation of different header mapping, will result
242+
# in two or more files attempting to create given mapping.
243+
# For now - we are implementing "first-write-wins" strategy, where
244+
# every subsequent attempt results in warnings.
245+
if target in existing_paths:
246+
print("[WARN][rules_cc_hdrs_map] {} attempts to overwrite mapping of {}. Refusing and continuing.".format(source_hdr_file.path, target))
247+
continue
248+
249+
existing_paths.add(target)
250+
238251
# TODO: Hash the label name and add as prefix?
239252
mapping_path = "/".join([
240253
parent_dir_name,
@@ -250,7 +263,7 @@ def _materialize_hdr_mapping(ctx_actions, parent_dir_name, source_hdr_file, mapp
250263
)
251264
mapped_files.append(mapping_file)
252265

253-
return mapped_files
266+
return mapped_files, existing_paths
254267

255268
def materialize_hdrs_mapping(
256269
invoker_label,
@@ -276,33 +289,43 @@ def materialize_hdrs_mapping(
276289
materialized_include_path = None
277290
materialized_hdrs_files = []
278291

292+
# Retain paths (relative to HEADERS_MAP_DIR_NAME)
293+
# of all header files that were created during mapping phase.
294+
# This bookeeping is used for detection of scenario,
295+
# that would lead to attempt to create a duplicated file,
296+
# and would result in Bazel error.
297+
materialized_hdrs_paths_rel = set()
298+
299+
# TODO: Refactor this nested-loop logic
279300
for header_file in hdrs.to_list():
280301
if ".vhm" in header_file.path:
281302
# This is important! Improve the check
282303
continue
283304
if header_file.path in hdrs_map.non_glob:
284305
# This is happening before globbing to improve perf.
285-
materialized_hdrs_files.extend(
286-
_materialize_hdr_mapping(
287-
actions,
288-
HEADERS_MAP_DIR_NAME,
289-
header_file,
290-
hdrs_map.non_glob.get(header_file.path),
291-
),
306+
created_hdrs, created_hdrs_paths_rel = _materialize_hdr_mapping(
307+
actions,
308+
HEADERS_MAP_DIR_NAME,
309+
header_file,
310+
hdrs_map.non_glob.get(header_file.path),
311+
materialized_hdrs_paths_rel,
292312
)
313+
materialized_hdrs_files.extend(created_hdrs)
314+
materialized_hdrs_paths_rel.update(created_hdrs_paths_rel)
293315
continue
294316

295317
for pattern, mappings in hdrs_map.glob.items():
296318
if not _glob_match(pattern, header_file.path):
297319
continue
298-
materialized_hdrs_files.extend(
299-
_materialize_hdr_mapping(
300-
actions,
301-
HEADERS_MAP_DIR_NAME,
302-
header_file,
303-
mappings,
304-
),
320+
created_hdrs, created_hdrs_paths_rel = _materialize_hdr_mapping(
321+
actions,
322+
HEADERS_MAP_DIR_NAME,
323+
header_file,
324+
mappings,
325+
materialized_hdrs_paths_rel,
305326
)
327+
materialized_hdrs_files.extend(created_hdrs)
328+
materialized_hdrs_paths_rel.update(created_hdrs_paths_rel)
306329

307330
if materialized_hdrs_files:
308331
hdr = materialized_hdrs_files[0]

0 commit comments

Comments
 (0)