-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #214 from salesforce/plaird/deps_filter
Add the deps filter mechanism and update docs and examples.
- Loading branch information
Showing
4 changed files
with
202 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,9 @@ | ||
# | ||
# Copyright (c) 2019-2021, salesforce.com, inc. | ||
# Copyright (c) 2019-2024, salesforce.com, inc. | ||
# All rights reserved. | ||
# Licensed under the BSD 3-Clause license. | ||
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
# | ||
|
||
jakarta.annotation-api-1.3.5.jar | ||
javax.annotation-api-1.3.2.jar | ||
spring-jcl-5.2.1.RELEASE.jar | ||
commons-logging-1.2.jar | ||
liblib1.jar | ||
liblib2.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
def _depaggregator_rule_impl(merged, ctx): | ||
""" | ||
This method processes declared deps and their transitive closures | ||
to assemble a cohesive set of jars essential for the build process. During | ||
this process, it excludes deps specified in 'deps_exclude', which | ||
lists jar labels to be omitted from packaging due to issues that cannot | ||
be resolved upstream. By default, with 'exclude_transitives' set to true, any | ||
transitive deps that are only required by excluded deps | ||
are also omitted, ensuring that only necessary transitives are included | ||
in the final package. It uses 'deps_exclude_paths' to exclude deps | ||
based on partial filename matches, ensuring problematic files are also | ||
excluded from the build. This method ensures that only necessary | ||
deps are included for the build process. | ||
""" | ||
exclude_transitives = ctx.attr.exclude_transitives | ||
|
||
# list to store jars to be included and a dictionary to track excluded jars | ||
jars = [] | ||
excludes = {} | ||
|
||
if exclude_transitives: | ||
# Dictionary to track transitive dependency paths that should be excluded | ||
transitives_excludes = {} | ||
|
||
# List to store deps info for deps present in 'deps_exclude' | ||
direct_excludes = [] | ||
|
||
# Iterate through the deps specified in 'deps_exclude' to collect | ||
# jars that should be excluded from the final set. | ||
|
||
for exclusion_info in ctx.attr.deps_exclude: | ||
# For each excluded dependency, add its compile-time JARs to the exclusion list | ||
for compile_jar in exclusion_info[JavaInfo].full_compile_jars.to_list(): | ||
excludes[compile_jar.path] = True | ||
|
||
if exclude_transitives: | ||
# Mark all transitives of the current dependency as excluded | ||
# This list will be updated later based on transitives of non-excluded deps | ||
direct_excludes.append(str(exclusion_info)) | ||
for transitive_jar in exclusion_info[JavaInfo].transitive_runtime_jars.to_list(): | ||
transitives_excludes[transitive_jar.path] = True | ||
|
||
if exclude_transitives: | ||
# Iterate over all deps, for non-excluded deps, mark their transitives as included. | ||
for deps_info in ctx.attr.deps: | ||
# skip the current dependency if it is listed in 'deps_exclude'. | ||
if str(deps_info) in direct_excludes: | ||
continue | ||
|
||
# For non-excluded deps, mark them and their transitive deps as included (not to be excluded) | ||
# (transitive_runtime_jars includes both the primary JAR and its transitive deps) | ||
for transitive_jar in deps_info[JavaInfo].transitive_runtime_jars.to_list(): | ||
if transitive_jar.path in transitives_excludes: | ||
transitives_excludes[transitive_jar.path] = False | ||
|
||
# update the excludes list | ||
for dep_path in transitives_excludes: | ||
# print("Transitive:", str(dep_path), "is excluded", transitives_excludes[dep_path]) | ||
if transitives_excludes[dep_path]: | ||
excludes[dep_path] = True | ||
|
||
# compute the final set of jars | ||
for dep in merged.transitive_runtime_jars.to_list(): | ||
# If the current JAR is in the exclusion list, skip it (do not include it) | ||
if excludes.get(dep.path, None) != None: | ||
pass | ||
else: | ||
# Default to including the JAR unless a pattern match excludes it | ||
include = True | ||
for pattern in ctx.attr.deps_exclude_paths: | ||
if dep.path.find(pattern) > -1: | ||
include = False | ||
break | ||
if include: | ||
jars.append(dep) | ||
|
||
return jars | ||
|
||
def _deps_filter_transitive_impl(ctx): | ||
""" | ||
This rule filters out specified deps and JARs from the compile-time | ||
and runtime deps. It utilizes the 'deps_exclude' attribute to omit | ||
specific JAR labels and the 'deps_exclude_paths' attribute to exclude | ||
deps based on partial paths in their filenames. By default, with | ||
'exclude_transitives' set to true, any transitive deps solely required | ||
by the deps in 'deps_exclude' are also excluded. These exclusions ensure | ||
the final collection includes only the necessary elements for the build | ||
process, eliminating problematic deps. | ||
""" | ||
|
||
if len(ctx.attr.deps) == 0: | ||
fail("Error: 'deps' cannot be an empty list") | ||
|
||
# magical incantation for getting upstream transitive closure of java deps | ||
merged = java_common.merge([dep[java_common.provider] for dep in ctx.attr.deps]) | ||
runtime_dep_merged = java_common.merge([runtime_dep[java_common.provider] for runtime_dep in ctx.attr.runtime_deps]) | ||
|
||
compile_time_jars = _depaggregator_rule_impl(merged, ctx) | ||
runtime_jars = _depaggregator_rule_impl(runtime_dep_merged, ctx) | ||
|
||
if len(compile_time_jars) == 0: | ||
fail("Error: The rule must return at least one compile-time JAR. Excluding all compile-time dependencies is not allowed.") | ||
|
||
return [ | ||
DefaultInfo(files = depset(compile_time_jars,)), | ||
JavaInfo( | ||
compile_jar = None, | ||
output_jar = compile_time_jars[0], # output jar must be non-empty, adding a dummy value to it | ||
exports = [JavaInfo(source_jar = jar, compile_jar = jar, output_jar = jar) for jar in compile_time_jars], | ||
runtime_deps = [JavaInfo(source_jar = jar, compile_jar = jar, output_jar = jar) for jar in | ||
runtime_jars], | ||
deps = [JavaInfo(source_jar = jar, compile_jar = jar, output_jar = jar) for jar in compile_time_jars], | ||
), | ||
] | ||
|
||
|
||
deps_filter_transitive = rule( | ||
implementation = _deps_filter_transitive_impl, | ||
attrs = { | ||
"deps": attr.label_list(providers = [java_common.provider]), | ||
"runtime_deps": attr.label_list(providers = [java_common.provider], allow_empty = True), | ||
"deps_exclude": attr.label_list(providers = [java_common.provider], allow_empty = True), | ||
"deps_exclude_paths": attr.string_list(), | ||
"exclude_transitives": attr.bool(default = True), | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters