Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental api crate_deps and all_crate_deps macro for gathering package dependencies #319

Merged
merged 35 commits into from
Dec 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cadbc0d
The crates.bzl can be used to locate crates
UebelAndre Nov 26, 2020
2f98c12
Updated smoketest
UebelAndre Nov 26, 2020
f2fa2d6
Updated examples
UebelAndre Dec 13, 2020
db7297a
It should not be an error that no dependencies are found.
UebelAndre Dec 19, 2020
650d699
Updated examples
UebelAndre Dec 22, 2020
db7fdaf
New API has been flagged experimental
UebelAndre Dec 22, 2020
a65d9fe
Updated examples
UebelAndre Dec 22, 2020
73f38ad
Updated more comments
UebelAndre Dec 22, 2020
bf2f9be
Updated examples
UebelAndre Dec 22, 2020
fd90d18
Updated documentation
UebelAndre Dec 22, 2020
ddc9fc6
Addressed PR feedback.
UebelAndre Dec 22, 2020
4771e2a
Updated examples
UebelAndre Dec 22, 2020
8a68a35
Addressed PR feedback
UebelAndre Dec 24, 2020
4ac8a63
Updated examples
UebelAndre Dec 24, 2020
a5e2d54
Addressed PR feedback
UebelAndre Dec 24, 2020
78f8f79
Updated examples
UebelAndre Dec 24, 2020
f63018a
Fixed typo
UebelAndre Dec 24, 2020
94856ba
Updated
UebelAndre Dec 24, 2020
c6f5418
Added experimental_api flag
UebelAndre Dec 24, 2020
8751679
Updated smoketest
UebelAndre Dec 24, 2020
b99c591
Updated examples
UebelAndre Dec 24, 2020
a52ca0d
Fixed buildifier defects
UebelAndre Dec 24, 2020
734e87d
Updated examples
UebelAndre Dec 24, 2020
2720cf4
Addressed PR feedback
UebelAndre Dec 24, 2020
4a3dae9
Updated examples
UebelAndre Dec 24, 2020
a991325
Addressed PR feedback
UebelAndre Dec 24, 2020
0c56c10
Updated examples
UebelAndre Dec 24, 2020
5ad98fe
Addressed PR feedback
UebelAndre Dec 24, 2020
311ecc6
Updated examples
UebelAndre Dec 24, 2020
cd3df77
updated smoketest
UebelAndre Dec 24, 2020
b83d71d
Updated examples
UebelAndre Dec 24, 2020
ec0ad06
Cleanup
UebelAndre Dec 24, 2020
e8f65fc
Updated examples
UebelAndre Dec 24, 2020
730e8e7
Updated macros `crates` -> `crate_deps` and `all_crates` -> `all_crat…
UebelAndre Dec 29, 2020
ee83597
Updated examples
UebelAndre Dec 29, 2020
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
5 changes: 2 additions & 3 deletions examples/remote/binary_dependencies/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary")
load("//remote/binary_dependencies/cargo:crates.bzl", "all_crate_deps")

package(default_visibility = ["//visibility:public"])

Expand All @@ -8,7 +9,5 @@ rust_binary(
data = [
"//remote/binary_dependencies/cargo:cargo_bin_texture_synthesis",
],
deps = [
"//remote/binary_dependencies/cargo:ferris_says",
],
deps = all_crate_deps(),
)
1 change: 1 addition & 0 deletions examples/remote/binary_dependencies/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ gen_workspace_prefix = "remote_binary_dependencies"
genmode = "Remote"
default_gen_buildrs = true
package_aliases_dir = "cargo"
experimental_api = true

[package.metadata.raze.binary_deps]
texture-synthesis-cli = "0.8.0"
Expand Down
158 changes: 158 additions & 0 deletions examples/remote/binary_dependencies/cargo/crates.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,164 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository") # bui
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # buildifier: disable=load
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") # buildifier: disable=load

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of normal dependencies for the Rust targets of that package.
_DEPENDENCIES = {
"remote/binary_dependencies": {
"ferris-says": "@remote_binary_dependencies__ferris_says__0_2_0//:ferris_says",
},
}

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of proc_macro dependencies for the Rust targets of that package.
_PROC_MACRO_DEPENDENCIES = {
"remote/binary_dependencies": {
},
}

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of normal dev dependencies for the Rust targets of that package.
_DEV_DEPENDENCIES = {
"remote/binary_dependencies": {
},
}

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of proc_macro dev dependencies for the Rust targets of that package.
_DEV_PROC_MACRO_DEPENDENCIES = {
"remote/binary_dependencies": {
},
}

def crate_deps(deps, package_name = None):
"""EXPERIMENTAL -- MAY CHANGE AT ANY TIME: Finds the fully qualified label of the requested crates for the package where this macro is called.

WARNING: This macro is part of an expeirmental API and is subject to change.

Args:
deps (list): The desired list of crate targets.
package_name (str, optional): The package name of the set of dependencies to look up.
Defaults to `native.package_name()`.
Returns:
list: A list of labels to cargo-raze generated targets (str)
"""

if not package_name:
package_name = native.package_name()

# Join both sets of dependencies
dependencies = _flatten_dependency_maps([
_DEPENDENCIES,
_PROC_MACRO_DEPENDENCIES,
_DEV_DEPENDENCIES,
_DEV_PROC_MACRO_DEPENDENCIES,
])

if not deps:
return []

missing_crates = []
crate_targets = []
for crate_target in deps:
if crate_target not in dependencies[package_name]:
missing_crates.append(crate_target)
else:
crate_targets.append(dependencies[package_name][crate_target])

if missing_crates:
fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format(
missing_crates,
package_name,
dependencies[package_name],
))

return crate_targets

def all_crate_deps(normal = False, normal_dev = False, proc_macro = False, proc_macro_dev = False, package_name = None):
"""EXPERIMENTAL -- MAY CHANGE AT ANY TIME: Finds the fully qualified label of all requested direct crate dependencies \
for the package where this macro is called.

If no parameters are set, all normal dependencies are returned. Setting any one flag will
otherwise impact the contents of the returned list.

Args:
normal (bool, optional): If True, normal dependencies are included in the
output list. Defaults to False.
normal_dev (bool, optional): If True, normla dev dependencies will be
included in the output list. Defaults to False.
proc_macro (bool, optional): If True, proc_macro dependencies are included
in the output list. Defaults to False.
proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are
included in the output list. Defaults to False.
package_name (str, optional): The package name of the set of dependencies to look up.
Defaults to `native.package_name()`.

Returns:
list: A list of labels to cargo-raze generated targets (str)
"""

if not package_name:
package_name = native.package_name()

# Determine the relevant maps to use
all_dependency_maps = []
if normal:
all_dependency_maps.append(_DEPENDENCIES)
if normal_dev:
all_dependency_maps.append(_DEV_DEPENDENCIES)
if proc_macro:
all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES)
if proc_macro_dev:
all_dependency_maps.append(_DEV_PROC_MACRO_DEPENDENCIES)

# Default to always using normal dependencies
if not all_dependency_maps:
all_dependency_maps.append(_DEPENDENCIES)

dependencies = _flatten_dependency_maps(all_dependency_maps)

if not dependencies:
return []

return dependencies[package_name].values()

def _flatten_dependency_maps(all_dependency_maps):
"""Flatten a list of dependency maps into one dictionary.

Dependency maps have the following structure:

```python
DEPENDENCIES_MAP = {
# The first key in the map is a Bazel package
# name of the workspace this file is defined in.
"package_name": {

# An alias to a crate target. # The label of the crate target the
# Aliases are only crate names. # alias refers to.
"alias": "@full//:label",
}
}
```

Args:
all_dependency_maps (list): A list of dicts as described above

Returns:
dict: A dictionary as described above
"""
dependencies = {}

for dep_map in all_dependency_maps:
for pkg_name in dep_map:
if pkg_name not in dependencies:
# Add a non-frozen dict to the collection of dependencies
dependencies.setdefault(pkg_name, dict(dep_map[pkg_name].items()))
continue

duplicate_crate_aliases = [key for key in dependencies[pkg_name] if key in dep_map[pkg_name]]
if duplicate_crate_aliases:
fail("There should be no duplicate crate aliases: {}".format(duplicate_crate_aliases))

dependencies[pkg_name].update(dep_map[pkg_name])

return dependencies

def remote_binary_dependencies_fetch_remote_crates():
"""This function defines a collection of repos and should be called in a WORKSPACE file"""
maybe(
Expand Down
1 change: 1 addition & 0 deletions examples/remote/cargo_workspace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ gen_workspace_prefix = "remote_cargo_workspace"
genmode = "Remote"
default_gen_buildrs = true
package_aliases_dir = "cargo"
experimental_api = true
176 changes: 176 additions & 0 deletions examples/remote/cargo_workspace/cargo/crates.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,182 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository") # bui
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # buildifier: disable=load
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") # buildifier: disable=load

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of normal dependencies for the Rust targets of that package.
_DEPENDENCIES = {
"remote/cargo_workspace/num_printer": {
"clap": "@remote_cargo_workspace__clap__2_33_3//:clap",
},
"remote/cargo_workspace/printer": {
"ferris-says": "@remote_cargo_workspace__ferris_says__0_2_0//:ferris_says",
},
"remote/cargo_workspace/rng": {
"rand": "@remote_cargo_workspace__rand__0_7_3//:rand",
},
}

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of proc_macro dependencies for the Rust targets of that package.
_PROC_MACRO_DEPENDENCIES = {
"remote/cargo_workspace/num_printer": {
},
"remote/cargo_workspace/printer": {
},
"remote/cargo_workspace/rng": {
},
}

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of normal dev dependencies for the Rust targets of that package.
_DEV_DEPENDENCIES = {
"remote/cargo_workspace/num_printer": {
},
"remote/cargo_workspace/printer": {
},
"remote/cargo_workspace/rng": {
},
}

# EXPERIMENTAL -- MAY CHANGE AT ANY TIME: A mapping of package names to a set of proc_macro dev dependencies for the Rust targets of that package.
_DEV_PROC_MACRO_DEPENDENCIES = {
"remote/cargo_workspace/num_printer": {
},
"remote/cargo_workspace/printer": {
},
"remote/cargo_workspace/rng": {
},
}
acmcarther marked this conversation as resolved.
Show resolved Hide resolved

def crate_deps(deps, package_name = None):
"""EXPERIMENTAL -- MAY CHANGE AT ANY TIME: Finds the fully qualified label of the requested crates for the package where this macro is called.

WARNING: This macro is part of an expeirmental API and is subject to change.

Args:
deps (list): The desired list of crate targets.
package_name (str, optional): The package name of the set of dependencies to look up.
Defaults to `native.package_name()`.
Returns:
list: A list of labels to cargo-raze generated targets (str)
"""

if not package_name:
package_name = native.package_name()

# Join both sets of dependencies
dependencies = _flatten_dependency_maps([
_DEPENDENCIES,
_PROC_MACRO_DEPENDENCIES,
_DEV_DEPENDENCIES,
_DEV_PROC_MACRO_DEPENDENCIES,
])

if not deps:
return []

missing_crates = []
crate_targets = []
for crate_target in deps:
if crate_target not in dependencies[package_name]:
missing_crates.append(crate_target)
else:
crate_targets.append(dependencies[package_name][crate_target])

if missing_crates:
fail("Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`".format(
missing_crates,
package_name,
dependencies[package_name],
))

return crate_targets

def all_crate_deps(normal = False, normal_dev = False, proc_macro = False, proc_macro_dev = False, package_name = None):
"""EXPERIMENTAL -- MAY CHANGE AT ANY TIME: Finds the fully qualified label of all requested direct crate dependencies \
for the package where this macro is called.

If no parameters are set, all normal dependencies are returned. Setting any one flag will
otherwise impact the contents of the returned list.

Args:
normal (bool, optional): If True, normal dependencies are included in the
output list. Defaults to False.
normal_dev (bool, optional): If True, normla dev dependencies will be
included in the output list. Defaults to False.
proc_macro (bool, optional): If True, proc_macro dependencies are included
in the output list. Defaults to False.
proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are
included in the output list. Defaults to False.
package_name (str, optional): The package name of the set of dependencies to look up.
Defaults to `native.package_name()`.

Returns:
list: A list of labels to cargo-raze generated targets (str)
"""

if not package_name:
package_name = native.package_name()

# Determine the relevant maps to use
all_dependency_maps = []
if normal:
all_dependency_maps.append(_DEPENDENCIES)
if normal_dev:
all_dependency_maps.append(_DEV_DEPENDENCIES)
if proc_macro:
all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES)
if proc_macro_dev:
all_dependency_maps.append(_DEV_PROC_MACRO_DEPENDENCIES)

# Default to always using normal dependencies
if not all_dependency_maps:
all_dependency_maps.append(_DEPENDENCIES)

dependencies = _flatten_dependency_maps(all_dependency_maps)

if not dependencies:
return []

return dependencies[package_name].values()

def _flatten_dependency_maps(all_dependency_maps):
"""Flatten a list of dependency maps into one dictionary.

Dependency maps have the following structure:

```python
DEPENDENCIES_MAP = {
# The first key in the map is a Bazel package
# name of the workspace this file is defined in.
"package_name": {

# An alias to a crate target. # The label of the crate target the
# Aliases are only crate names. # alias refers to.
"alias": "@full//:label",
}
}
```

Args:
all_dependency_maps (list): A list of dicts as described above

Returns:
dict: A dictionary as described above
"""
dependencies = {}

for dep_map in all_dependency_maps:
for pkg_name in dep_map:
if pkg_name not in dependencies:
# Add a non-frozen dict to the collection of dependencies
dependencies.setdefault(pkg_name, dict(dep_map[pkg_name].items()))
continue

duplicate_crate_aliases = [key for key in dependencies[pkg_name] if key in dep_map[pkg_name]]
if duplicate_crate_aliases:
fail("There should be no duplicate crate aliases: {}".format(duplicate_crate_aliases))

dependencies[pkg_name].update(dep_map[pkg_name])

return dependencies

def remote_cargo_workspace_fetch_remote_crates():
"""This function defines a collection of repos and should be called in a WORKSPACE file"""
maybe(
Expand Down
4 changes: 2 additions & 2 deletions examples/remote/cargo_workspace/num_printer/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary")
load("//remote/cargo_workspace/cargo:crates.bzl", "all_crate_deps")

package(default_visibility = ["//visibility:public"])

Expand All @@ -7,7 +8,6 @@ rust_binary(
srcs = ["src/main.rs"],
edition = "2018",
deps = [
"//remote/cargo_workspace/num_printer/cargo:clap",
"//remote/cargo_workspace/printer",
],
] + all_crate_deps(),
)
Loading