Deduplication in compiler driver commands
This commit is contained in:
@@ -21,13 +21,14 @@ class _FlattenContext:
|
|||||||
_libs_list: list[Accessor] = field(init=False, default_factory=list)
|
_libs_list: list[Accessor] = field(init=False, default_factory=list)
|
||||||
_srcs_list: list[Accessor] = field(init=False, default_factory=list)
|
_srcs_list: list[Accessor] = field(init=False, default_factory=list)
|
||||||
|
|
||||||
_incs_set: set[Accessor] = field(init=False, default_factory=set)
|
# Keyed by value so the same entry at different access levels isn't repeated.
|
||||||
_dirs_set: set[Accessor] = field(init=False, default_factory=set)
|
_incs_set: set[str] = field(init=False, default_factory=set)
|
||||||
_opts_set: set[Accessor] = field(init=False, default_factory=set)
|
_dirs_set: set[str] = field(init=False, default_factory=set)
|
||||||
_defs_set: set[Accessor] = field(init=False, default_factory=set)
|
_opts_set: set[str] = field(init=False, default_factory=set)
|
||||||
_deps_set: set[Accessor] = field(init=False, default_factory=set)
|
_defs_set: set[str] = field(init=False, default_factory=set)
|
||||||
_libs_set: set[Accessor] = field(init=False, default_factory=set)
|
_deps_set: set[str] = field(init=False, default_factory=set)
|
||||||
_srcs_set: set[Accessor] = field(init=False, default_factory=set)
|
_libs_set: set[str] = field(init=False, default_factory=set)
|
||||||
|
_srcs_set: set[str] = field(init=False, default_factory=set)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def incs(self) -> list[Accessor]:
|
def incs(self) -> list[Accessor]:
|
||||||
@@ -68,45 +69,45 @@ class _FlattenContext:
|
|||||||
for src in target.srcs: self.append_src(src)
|
for src in target.srcs: self.append_src(src)
|
||||||
|
|
||||||
def append_inc(self, inc: Accessor) -> None:
|
def append_inc(self, inc: Accessor) -> None:
|
||||||
if inc.level == Access.PRIVATE or inc in self._incs_set:
|
if inc.level == Access.PRIVATE or str(inc.value) in self._incs_set:
|
||||||
return
|
return
|
||||||
self._incs_set.add(inc)
|
self._incs_set.add(str(inc.value))
|
||||||
self._incs_list.insert(0, inc)
|
self._incs_list.insert(0, inc)
|
||||||
|
|
||||||
def append_dir(self, lib: Accessor) -> None:
|
def append_dir(self, lib: Accessor) -> None:
|
||||||
if lib.level == Access.PRIVATE or lib in self._dirs_set:
|
if lib.level == Access.PRIVATE or str(lib.value) in self._dirs_set:
|
||||||
return
|
return
|
||||||
self._dirs_set.add(lib)
|
self._dirs_set.add(str(lib.value))
|
||||||
self._dirs_list.insert(0, lib)
|
self._dirs_list.insert(0, lib)
|
||||||
|
|
||||||
def append_opt(self, opt: Accessor) -> None:
|
def append_opt(self, opt: Accessor) -> None:
|
||||||
if opt.level == Access.PRIVATE or opt in self._opts_set:
|
if opt.level == Access.PRIVATE or str(opt.value) in self._opts_set:
|
||||||
return
|
return
|
||||||
self._opts_set.add(opt)
|
self._opts_set.add(str(opt.value))
|
||||||
self._opts_list.insert(0, opt)
|
self._opts_list.insert(0, opt)
|
||||||
|
|
||||||
def append_def(self, dfn: Accessor) -> None:
|
def append_def(self, dfn: Accessor) -> None:
|
||||||
if dfn.level == Access.PRIVATE or dfn in self._defs_set:
|
if dfn.level == Access.PRIVATE or str(dfn.value) in self._defs_set:
|
||||||
return
|
return
|
||||||
self._defs_set.add(dfn)
|
self._defs_set.add(str(dfn.value))
|
||||||
self._defs_list.insert(0, dfn)
|
self._defs_list.insert(0, dfn)
|
||||||
|
|
||||||
def append_dep(self, dep: Accessor) -> None:
|
def append_dep(self, dep: Accessor) -> None:
|
||||||
if dep.level == Access.PRIVATE or dep in self._deps_set:
|
if dep.level == Access.PRIVATE or str(dep.value) in self._deps_set:
|
||||||
return
|
return
|
||||||
self._deps_set.add(dep)
|
self._deps_set.add(str(dep.value))
|
||||||
self._deps_list.insert(0, dep)
|
self._deps_list.insert(0, dep)
|
||||||
|
|
||||||
def append_lib(self, lib: Accessor) -> None:
|
def append_lib(self, lib: Accessor) -> None:
|
||||||
if lib.level == Access.PRIVATE or lib in self._libs_set:
|
if lib.level == Access.PRIVATE or str(lib.value) in self._libs_set:
|
||||||
return
|
return
|
||||||
self._libs_set.add(lib)
|
self._libs_set.add(str(lib.value))
|
||||||
self._libs_list.insert(0, lib)
|
self._libs_list.insert(0, lib)
|
||||||
|
|
||||||
def append_src(self, src: Accessor) -> None:
|
def append_src(self, src: Accessor) -> None:
|
||||||
if src.level == Access.PRIVATE or src in self._srcs_set:
|
if src.level == Access.PRIVATE or str(src.value) in self._srcs_set:
|
||||||
return
|
return
|
||||||
self._srcs_set.add(src)
|
self._srcs_set.add(str(src.value))
|
||||||
self._srcs_list.insert(0, src)
|
self._srcs_list.insert(0, src)
|
||||||
|
|
||||||
|
|
||||||
@@ -114,18 +115,7 @@ def flatten_targets(project: Project) -> None:
|
|||||||
for target in project.targets:
|
for target in project.targets:
|
||||||
if target._flattend:
|
if target._flattend:
|
||||||
continue
|
continue
|
||||||
context = _FlattenContext()
|
_flatten_target(_target_context(project, target), target)
|
||||||
context.append_inc(Accessor(
|
|
||||||
level = Access.PUBLIC \
|
|
||||||
if target.name in project.exports \
|
|
||||||
else Access.PROTECTED,
|
|
||||||
value = project.origination.src("include")
|
|
||||||
))
|
|
||||||
context.append_dir(Accessor(
|
|
||||||
level = Access.PUBLIC,
|
|
||||||
value = project.destination.libpath
|
|
||||||
))
|
|
||||||
_flatten_target(context, target)
|
|
||||||
|
|
||||||
def flatten_tests(project: Project) -> None:
|
def flatten_tests(project: Project) -> None:
|
||||||
for target in project.tests:
|
for target in project.tests:
|
||||||
@@ -142,6 +132,20 @@ def flatten_tests(project: Project) -> None:
|
|||||||
))
|
))
|
||||||
_flatten_test(context, target)
|
_flatten_test(context, target)
|
||||||
|
|
||||||
|
def _target_context(project: Project, target: Target) -> _FlattenContext:
|
||||||
|
context = _FlattenContext()
|
||||||
|
context.append_inc(Accessor(
|
||||||
|
level = Access.PUBLIC \
|
||||||
|
if target.name in project.exports \
|
||||||
|
else Access.PROTECTED,
|
||||||
|
value = project.origination.src("include")
|
||||||
|
))
|
||||||
|
context.append_dir(Accessor(
|
||||||
|
level = Access.PUBLIC,
|
||||||
|
value = project.destination.libpath
|
||||||
|
))
|
||||||
|
return context
|
||||||
|
|
||||||
def _flatten_target(context: _FlattenContext, target: Target) -> None:
|
def _flatten_target(context: _FlattenContext, target: Target) -> None:
|
||||||
if target._flattend:
|
if target._flattend:
|
||||||
return
|
return
|
||||||
@@ -150,14 +154,7 @@ def _flatten_target(context: _FlattenContext, target: Target) -> None:
|
|||||||
if (parent:=targets_by_name_mapping.get(dependency.value)) == None:
|
if (parent:=targets_by_name_mapping.get(dependency.value)) == None:
|
||||||
raise ValueError(f"No such dependable target: {dependency.value}")
|
raise ValueError(f"No such dependable target: {dependency.value}")
|
||||||
_target_inherit_target(context, parent)
|
_target_inherit_target(context, parent)
|
||||||
target.incs.includes.extend(context.incs)
|
_extend_target(context, target)
|
||||||
target.incs.libraries.extend(context.dirs)
|
|
||||||
target.opts.extend(context.opts)
|
|
||||||
target.defs.extend(context.defs)
|
|
||||||
target.deps.extend(context.deps)
|
|
||||||
target.libs.extend(context.libs)
|
|
||||||
target.srcs.extend(context.srcs)
|
|
||||||
target._flattend = True
|
|
||||||
|
|
||||||
def _flatten_test(context: _FlattenContext, target: Target) -> None:
|
def _flatten_test(context: _FlattenContext, target: Target) -> None:
|
||||||
if target._flattend:
|
if target._flattend:
|
||||||
@@ -167,15 +164,25 @@ def _flatten_test(context: _FlattenContext, target: Target) -> None:
|
|||||||
if (parent:=targets_by_name_mapping.get(dependency.value)) == None:
|
if (parent:=targets_by_name_mapping.get(dependency.value)) == None:
|
||||||
raise ValueError(f"No such dependable target: {dependency.value}")
|
raise ValueError(f"No such dependable target: {dependency.value}")
|
||||||
_test_inherit_target(context, parent)
|
_test_inherit_target(context, parent)
|
||||||
target.incs.includes.extend(context.incs)
|
_extend_target(context, target)
|
||||||
target.incs.libraries.extend(context.dirs)
|
|
||||||
target.opts.extend(context.opts)
|
def _extend_target(context: _FlattenContext, target: Target) -> None:
|
||||||
target.defs.extend(context.defs)
|
_extend_unique(target.incs.includes, context.incs)
|
||||||
target.deps.extend(context.deps)
|
_extend_unique(target.incs.libraries, context.dirs)
|
||||||
target.libs.extend(context.libs)
|
_extend_unique(target.opts, context.opts)
|
||||||
target.srcs.extend(context.srcs)
|
_extend_unique(target.defs, context.defs)
|
||||||
|
_extend_unique(target.deps, context.deps)
|
||||||
|
_extend_unique(target.libs, context.libs)
|
||||||
|
_extend_unique(target.srcs, context.srcs)
|
||||||
target._flattend = True
|
target._flattend = True
|
||||||
|
|
||||||
|
def _extend_unique(dst: list[Accessor], src: list[Accessor]) -> None:
|
||||||
|
values = {str(v.value) for v in dst}
|
||||||
|
for accessor in src:
|
||||||
|
if str(accessor.value) not in values:
|
||||||
|
values.add(str(accessor.value))
|
||||||
|
dst.append(accessor)
|
||||||
|
|
||||||
def _target_inherit_target(context: _FlattenContext, parent: Target) -> None:
|
def _target_inherit_target(context: _FlattenContext, parent: Target) -> None:
|
||||||
if parent.name in tests_by_name_mapping:
|
if parent.name in tests_by_name_mapping:
|
||||||
raise ValueError("Cannot inherit tests")
|
raise ValueError("Cannot inherit tests")
|
||||||
@@ -188,7 +195,8 @@ def _inherit_raw(context: _FlattenContext, parent: Target) -> None:
|
|||||||
parent_project = project_by_targets_mapping.get(parent.name)
|
parent_project = project_by_targets_mapping.get(parent.name)
|
||||||
assert parent_project is not None, "Parent project not mapped!"
|
assert parent_project is not None, "Parent project not mapped!"
|
||||||
|
|
||||||
_flatten_target(context, parent)
|
# Parents flatten in their own context so the child's entries don't leak into them.
|
||||||
|
_flatten_target(_target_context(parent_project, parent), parent)
|
||||||
context.inherit_target(parent)
|
context.inherit_target(parent)
|
||||||
context.append_inc(Accessor(
|
context.append_inc(Accessor(
|
||||||
level = Access.PROTECTED,
|
level = Access.PROTECTED,
|
||||||
@@ -202,4 +210,3 @@ def _inherit_raw(context: _FlattenContext, parent: Target) -> None:
|
|||||||
level = Access.PROTECTED,
|
level = Access.PROTECTED,
|
||||||
value = parent.name
|
value = parent.name
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ def prepare(
|
|||||||
libprj = find_project_by_target(libtgt.name)
|
libprj = find_project_by_target(libtgt.name)
|
||||||
if libtgt.type == Output.LIB:
|
if libtgt.type == Output.LIB:
|
||||||
libfile = libprj.destination.lib(library.value)
|
libfile = libprj.destination.lib(library.value)
|
||||||
defopts.libdirs.append(libprj.destination.libpath)
|
if libprj.destination.libpath not in defopts.libdirs:
|
||||||
|
defopts.libdirs.append(libprj.destination.libpath)
|
||||||
defopts.archives.append(library.value)
|
defopts.archives.append(library.value)
|
||||||
elif libtgt.type == Output.DLL:
|
elif libtgt.type == Output.DLL:
|
||||||
libfile = libprj.destination.dll(library.value)
|
libfile = libprj.destination.dll(library.value)
|
||||||
|
|||||||
Reference in New Issue
Block a user