Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions crate_universe/private/generate_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,19 @@ def get_generator(repository_ctx, host_triple):

def render_config(
build_file_template = "//:BUILD.{name}-{version}.bazel",
crate_label_template = "@{repository}__{name}-{version}//:{target}",
crate_alias_template = "//:{name}-{version}",
crate_label_template = "@{repository}__{name}-{version}//:{target}",
crate_package_default_visibility = None,
crate_repository_template = "{repository}__{name}-{version}",
crates_module_template = "//:{file}",
default_alias_rule = "alias",
default_package_name = None,
generate_cargo_toml_env_vars = True,
generate_rules_license_metadata = False,
generate_target_compatible_with = True,
platforms_template = "@rules_rust//rust/platform:{triple}",
regen_command = None,
vendor_mode = None,
generate_rules_license_metadata = False):
vendor_mode = None):
"""Various settings used to configure rendered outputs

The template parameters each support a select number of format keys. A description of each key
Expand All @@ -126,6 +127,9 @@ def render_config(
available format keys are [`{repository}`, `{name}`, `{version}`].
crate_alias_template (str, optional): The template to use when referring to generated aliases within the external
repository. The available format keys are [`{repository}`, `{name}`, `{version}`].
crate_package_default_visibility (list, optional): The default_visibility for individual crate BUILD packages.
If None, defaults to `["//visibility:public"]`. Set to restrict direct references to crate targets so
that consumers must use the top-level aliases.
crates_module_template (str, optional): The pattern to use for the `defs.bzl` and `BUILD.bazel`
file names used for the crates module. The available format keys are [`{file}`].
default_alias_rule (str, option): Alias rule to use when generating aliases for all crates. Acceptable values
Expand Down Expand Up @@ -153,6 +157,7 @@ def render_config(
build_file_template = build_file_template,
crate_alias_template = crate_alias_template,
crate_label_template = crate_label_template,
crate_package_default_visibility = crate_package_default_visibility,
crate_repository_template = crate_repository_template,
crates_module_template = crates_module_template,
default_alias_rule = parse_alias_rule(default_alias_rule),
Expand Down
7 changes: 7 additions & 0 deletions crate_universe/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ pub(crate) struct RenderConfig {
/// Whether to generate cargo_toml_env_vars targets.
/// This is expected to always be true except for bootstrapping.
pub(crate) generate_cargo_toml_env_vars: bool,

/// The default_visibility for individual crate BUILD packages. If None,
/// defaults to ["//visibility:public"]. Set to restrict direct references
/// to crate targets so that consumers must use the top-level aliases.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(crate) crate_package_default_visibility: Option<Vec<String>>,
}

// Default is manually implemented so that the default values match the default
Expand All @@ -129,6 +135,7 @@ impl Default for RenderConfig {
regen_command: String::default(),
vendor_mode: Option::default(),
generate_rules_license_metadata: default_generate_rules_license_metadata(),
crate_package_default_visibility: None,
}
}
}
Expand Down
113 changes: 111 additions & 2 deletions crate_universe/src/rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ impl Renderer {
});
}

let package = Package::default_visibility_public(package_metadata);
let package = self.crate_package(package_metadata);
starlark.push(Starlark::Package(package));

starlark.push(Starlark::PackageInfo(starlark::PackageInfo {
Expand All @@ -461,7 +461,7 @@ impl Renderer {
}
} else {
// Package visibility.
let package = Package::default_visibility_public(BTreeSet::new());
let package = self.crate_package(BTreeSet::new());
starlark.push(Starlark::Package(package));
}

Expand Down Expand Up @@ -890,6 +890,22 @@ impl Renderer {
)
}

/// Constructs a `Package` for an individual crate BUILD file, using
/// `crate_package_default_visibility` from the render config if set,
/// otherwise falling back to `//visibility:public`.
fn crate_package(&self, default_package_metadata: BTreeSet<Label>) -> Package {
match &self.config.crate_package_default_visibility {
Some(visibility) => {
let default_visibility = visibility.iter().cloned().collect();
Package {
default_package_metadata,
default_visibility,
}
}
None => Package::default_visibility_public(default_package_metadata),
}
}

fn render_vendor_support_files(
&self,
engine: &TemplateEngine,
Expand Down Expand Up @@ -2350,4 +2366,97 @@ mod test {
"proc-macro lib must appear in proc_macro_deps:\n{binary_section}"
);
}

#[test]
fn render_crate_package_default_visibility() {
let mut context = Context::default();
let crate_id = CrateId::new("mock_crate".to_owned(), VERSION_ZERO_ONE_ZERO);
context.crates.insert(
crate_id.clone(),
CrateContext {
name: crate_id.name,
version: crate_id.version,
package_url: None,
repository: None,
targets: BTreeSet::from([Rule::Library(mock_target_attributes())]),
library_target_name: None,
common_attrs: CommonAttributes::default(),
build_script_attrs: None,
license: None,
license_ids: BTreeSet::default(),
license_file: None,
additive_build_file_content: None,
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

let config = Arc::new(RenderConfig {
repository_name: "test_rendering".to_owned(),
regen_command: "cargo_bazel_regen_command".to_owned(),
crate_package_default_visibility: Some(vec![
"//third_party/rust:__subpackages__".to_owned()
]),
..RenderConfig::default()
});
let renderer = Renderer::new(config, mock_supported_platform_triples());
let output = renderer.render(&context, None).unwrap();

let build_file_content = output
.get(&PathBuf::from("BUILD.mock_crate-0.1.0.bazel"))
.unwrap();

assert!(
build_file_content.contains("//third_party/rust:__subpackages__"),
"Expected custom visibility in BUILD file:\n{}",
build_file_content
);
assert!(
!build_file_content.contains("//visibility:public"),
"Expected no public visibility in BUILD file:\n{}",
build_file_content
);
}

#[test]
fn render_default_visibility_when_not_configured() {
let mut context = Context::default();
let crate_id = CrateId::new("mock_crate".to_owned(), VERSION_ZERO_ONE_ZERO);
context.crates.insert(
crate_id.clone(),
CrateContext {
name: crate_id.name,
version: crate_id.version,
package_url: None,
repository: None,
targets: BTreeSet::from([Rule::Library(mock_target_attributes())]),
library_target_name: None,
common_attrs: CommonAttributes::default(),
build_script_attrs: None,
license: None,
license_ids: BTreeSet::default(),
license_file: None,
additive_build_file_content: None,
disable_pipelining: false,
extra_aliased_targets: BTreeMap::default(),
alias_rule: None,
override_targets: BTreeMap::default(),
},
);

let renderer = Renderer::new(mock_render_config(None), mock_supported_platform_triples());
let output = renderer.render(&context, None).unwrap();

let build_file_content = output
.get(&PathBuf::from("BUILD.mock_crate-0.1.0.bazel"))
.unwrap();

assert!(
build_file_content.contains("//visibility:public"),
"Expected public visibility in BUILD file:\n{}",
build_file_content
);
}
}
Loading