Giter Club home page Giter Club logo

bazel-skylib's Introduction

Skylib

Build status

Skylib is a library of Starlark functions for manipulating collections, file paths, and various other data types in the domain of Bazel build rules.

Each of the .bzl files in the lib directory defines a "module"โ€”a struct that contains a set of related functions and/or other symbols that can be loaded as a single unit, for convenience.

Skylib also provides build rules under the rules directory.

Getting Started

WORKSPACE file

See the WORKSPACE setup section for the current release.

If you want to use lib/unittest.bzl from Skylib versions released in or after December 2018, then you also should add to the WORKSPACE file:

load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")

bazel_skylib_workspace()

BUILD and *.bzl files

Then, in the BUILD and/or *.bzl files in your own workspace, you can load the modules (listed below) and access the symbols by dotting into those structs:

load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//lib:shell.bzl", "shell")

p = paths.basename("foo.bar")
s = shell.quote(p)

List of modules (in lib/)

List of rules (in rules/)

Writing a new module

The criteria for adding a new function or module to this repository are:

  1. Is it widely needed? The new code must solve a problem that occurs often during the development of Bazel build rules. It is not sufficient that the new code is merely useful. Candidate code should generally have been proven to be necessary across several projects, either because it provides indispensable common functionality, or because it requires a single standardized implementation.

  2. Is its interface simpler than its implementation? A good abstraction provides a simple interface to a complex implementation, relieving the user from the burden of understanding. By contrast, a shallow abstraction provides little that the user could not easily have written out for themselves. If a function's doc comment is longer than its body, it's a good sign that the abstraction is too shallow.

  3. Is its interface unimpeachable? Given the problem it tries to solve, does it have sufficient parameters or generality to address all reasonable cases, or does it make arbitrary policy choices that limit its usefulness? If the function is not general, it likely does not belong here. Conversely, if it is general thanks only to a bewildering number of parameters, it also does not belong here.

  4. Is it efficient? Does it solve the problem using the asymptotically optimal algorithm, without using excessive looping, allocation, or other high constant factors? Starlark is an interpreted language with relatively expensive basic operations, and an approach that might make sense in C++ may not in Starlark.

If your new module meets all these criteria, then you should consider sending us a pull request. It is always better to discuss your plans before executing them.

Many of the declarations already in this repository do not meet this bar.

Steps to add a module to Skylib:

  1. Create a new .bzl file in the lib directory.

  2. Write the functions or other symbols (such as constants) in that file, defining them privately (prefixed by an underscore).

  3. Create the exported module struct, mapping the public names of the symbols to their implementations. For example, if your module was named things and had a function named manipulate, your things.bzl file would look like this:

    def _manipulate():
      ...
    
    things = struct(
        manipulate=_manipulate,
    )
  4. Add unit tests for your module in the tests directory.

bzl_library

The bzl_library.bzl rule can be used to aggregate a set of Starlark files and its dependencies for use in test targets and documentation generation.

Troubleshooting

If you try to use unittest and you get the following error:

ERROR: While resolving toolchains for target //foo:bar: no matching toolchains found for types @bazel_skylib//toolchains:toolchain_type
ERROR: Analysis of target '//foo:bar' failed; build aborted: no matching toolchains found for types @bazel_skylib//toolchains:toolchain_type

then you probably forgot to load and call bazel_skylib_workspace() in your WORKSPACE file.

Maintainer's guide

See the maintaner's guide for instructions for cutting a new release.

Gazelle Plugin

bazel_skylib ships with a gazelle plugin to generate bzl_library entries in build files. To use this, in your WORKSPACE:

load("@bazel_skylib_gazelle_plugin//:workspace.bzl", "bazel_skylib_gazelle_plugin_workspace")

bazel_skylib_gazelle_plugin_workspace()

load("@bazel_skylib_gazelle_plugin//:setup.bzl", "bazel_skylib_gazelle_plugin_setup")

bazel_skylib_gazelle_plugin_setup()

You may then include the plugin using code similar to this in your BUILD.bazel file:

load("@bazel_gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle", "gazelle_binary")

gazelle(
    name = "gazelle",
    gazelle = ":gazelle_bin",
)

gazelle_binary(
    name = "gazelle_bin",
    languages = DEFAULT_LANGUAGES + [
        "@bazel_skylib_gazelle_plugin//bzl",
    ],
)

bazel-skylib's People

Contributors

achew22 avatar aiuto avatar alexeagle avatar allevato avatar bttk avatar c-parsons avatar capstan avatar comius avatar cpsauer avatar daivinhtran avatar dmaclach avatar fmeum avatar gmngeoffrey avatar gregestren avatar juliexxia avatar kkress avatar kotlaja avatar laszlocsomor avatar laurentlb avatar meteorcloudy avatar nickgooding avatar phst avatar sfreilich avatar shs96c avatar techsy730 avatar tetromino avatar thomasvl avatar uebelandre avatar vertexwahn avatar wyverald avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bazel-skylib's Issues

1.0.2 instructions on the release page do not work

Following the instructions on https://github.com/bazelbuild/bazel-skylib/releases/tag/1.0.2:

http_archive(
    name = "bazel_skylib",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
    ],
    sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
$ bazel build //src/test:make_person_json 
ERROR: error loading package '': Unable to load file '@bazel_skylib//:workspace.bzl': file doesn't exist
ERROR: error loading package '': Unable to load file '@bazel_skylib//:workspace.bzl': file doesn't exist
INFO: Elapsed time: 0.115s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (0 packages loaded)

Attach source archives and sha256 sums to releases

Please attach source archives and sha256 sums to GitHub releases (both current and future releases) so they can be used safely with http_archive.

Source archives can be prepared like this:

$ git archive --output=bazel-skylib-0.2.0.tar.gz 0.2.0
$ sha256sum bazel-skylib-0.2.0.tar.gz 
61e358bd51312b5a31b8f81f9755b587bc240472b34054e2c2aff792b48eab10  bazel-skylib-0.2.0.tar.gz

GitHub has provides links to source archives on releases, but these are not safe for http_archive. They are generated on the fly and don't have stable sha256 sums. Earlier, GitHub broke Bazel, Homebrew, and other systems when they upgraded their internal software.

Source archives that are manually generated and attached to releases won't change and are safe.

support accepting files in analysis_test.targets

One may want to specify:

analysis_test(
    name = "my_test",
    targets = ["foo.o"],

But currently targets does not support files.
At first glance, this would seem easy to implement, using attr.label_list.allow_files, however, this approach poses a different problem: one can then specify a file that does not actually exist, and the analysis_test thus passes.
Thus, the above example test might fail if the rule generating foo.o fails, but the following would pass:

analysis_test(
    name = "my_test",
    targets = ["foo.o_oopsfatfinger"],

We'd need some way to ensure an input file actually exists to implement this feature.

Windows: implement run_binary rule

Implement @laurentlb 's idea (from bazelbuild/bazel#7503 (comment)):

We can provide a simple rule in skylib:

exec_cmd(
  name = "x",
  tool = "//pkg:binary_to_run",
  args = ["-a", "-o", "$(location output_file)"],
  outputs = ["output_file", "logs"],
  stdout = "file_that_will_contain_stdout",
  stderr = "file_that_will_contain_stderr",
]

It executes a command, we can specify arguments, and we can save stdout and/or stderr to an output file. This should be able to replace many basic uses of genrule, right? And we can support this on all platforms.

0.9.0 release

The last version of bazel skylib was relased on March 20th, almost 3 months ago. Since then a few new rules such as diff_test have been added, and it would be great to be able to consume those from a released version.

Are there any plans to do a new skylib release soon?

typo in 0.9.0 release notes

There's a missing , after name = "bazel_skylib" in the release notes for 0.9.0: https://github.com/bazelbuild/bazel-skylib/releases/tag/0.9.0

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")

maybe(
    http_archive,
-    name = "bazel_skylib"
+    name = "bazel_skylib",
    url = "https://github.com/bazelbuild/bazel-skylib/releases/download/0.9.0/bazel_skylib-0.9.0.tar.gz",
    sha256 = "1dde365491125a3db70731e25658dfdd3bc5dbdfd11b840b3e987ecf043c7ca0",
)

load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()

1.0.0 release

We would like to have a 1.0.0 release to include as the baseline in bazel-federation.
Right now we are in the sad position of having to point at a commit rather than a release.

@aiuto is prepared to do this by October 1, unless anyone else wants to step up.

CC: @fweikert

versions.check needs documentation/better error message explaining it can only be used in repository rules

For some reason, using versions.check("0.9.0") fails on macOS with a homebrew installed bazel.

Here's the error:

ERROR: /Users/jmhodges/founding/src/founding/BUILD:12:1: Traceback (most recent call last):
	File "/Users/jmhodges/founding/src/founding/BUILD", line 12
		versions.check("0.9.0")
	File "/private/var/tmp/_bazel_jmhodges/ee957dabdee1b1a9e1f2fe90369cf80f/external/bazel_skylib/lib/versions.bzl", line 96, in versions.check
		fail(("\nCurrent Bazel version is low...))

Current Bazel version is lower than 0.2.1, expected at least 0.9.0

but my bazel version reports

Build label: 0.9.0-homebrew
Build target: bazel-out/darwin-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Sun Jul 12 12:24:01 +49936 (1513677414241)
Build timestamp: 1513677414241
Build timestamp as int: 1513677414241

Should we add `types.is_depset`?

We're migrating rules_swift to use the types module instead of type(foo) == type(bar), but we can't update all of them since there's not a types.is_depset. I have to check the type because I'm writing action wrappers that need to augment the tools/inputs passed into them, which means knowing whether it's a depset or a list and performing the right operation.

Any reason we shouldn't do this?

analysis_test expect_failure does not work for rules with outputs

It looks as if an analysis test depending on a rule with an implicit rule output, such as the example:

custom_rule = rule(
    implementation = custom_rule_impl,
    outputs = {'my_output': '%{name}.txt'})

doesn't always behave nicely with expect_failures = True.

Specifically, if the custom_rule target fails before an action is registered to output my_output, a stack trace is thrown by Bazel.

at com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment.verifyGeneratedArtifactHaveActions(CachingAnalysisEnvironment.java:144)
	at com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment.disable(CachingAnalysisEnvironment.java:107)
	at com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.createConfiguredTarget(ConfiguredTargetFunction.java:856)
	at com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.compute(ConfiguredTargetFunction.java:358)
	at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:440)
	... 6 more

Bazel doesn't think the test executable is excutable.

On a vanilla project, bazel 0.21.0, MacOS, with the following:

WORKSPACE:

workspace(name = "bazel_maven_repository_rules")

# For testing.
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
    name = "bazel_skylib",
    remote = "https://github.com/bazelbuild/bazel-skylib.git",
    # tag = "0.x.0",
    commit = "9948d5538b8c400aec0dc23c545ec5094f8e079b",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()

BUILD:

load(":foo_test.bzl", "foo_test_suite")
foo_tes
load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")

def _foo_test_impl(ctx):
    env = unittest.begin(ctx)
    asserts.equals(env, "1", "1")
    unittest.end(env)

foo_test = unittest.make(_foo_test_impl)

def foo_test_suite():
    unittest.suite("foo_tests", foo_test)

I get the following result:

ERROR: /Users/gruber/Development/bazel_skylib_repro/foo/BUILD:2:1: in foo_test rule //foo:foo_tests_test_0: 


/Users/gruber/Development/bazel_skylib_repro/foo/foo_test.bzl:3:5: The rule 'foo_test' is executable. It needs to create an executable File and pass it as the 'executable' parameter to the DefaultInfo it returns.
ERROR: Analysis of target '//foo:foo_tests_test_0' failed; build aborted: Analysis of target '//foo:foo_tests_test_0' failed; build aborted

As far as I can tell, walking through skylib's unittest.bzl, the _make function does declare the file foo_tests_test_0, and writes to it, but the analysis phase doesn't seem to recognize that, and so it dumps before it even gets to generate that file.

This might be related to bazelbuild/bazel#6784 but I'm not sure. Repro example in code here: https://github.com/cgruber/bazel_skylib_repro/tree/unittest_fails_to_create_executable_file

Incompatible changes to maprule

Context: https://groups.google.com/d/msg/bazel-discuss/jp9RLsiVhD8/3M0wdWFoCgAJ

/cc @laurentlb

Plans:

  • add_env and outs_templates attributes: update requirements for dict keys. The rule would no longer prefix these with MAPRULE_. Instead the the name would have to start with MR_.

    Rationale: more obvious connection with their use in the cmd attribute, and MR_ is easier to type than MAPRULE_.

  • Envvars of the action: they would start with MR_ instead of MAPRULE_.

    Rationale: easier to type.

Questions:

  1. May I proceed with these incompatible changes?
  2. When is the next release due? I hope to merge my changes beforehand.

Build of maprule tests via "bazel build @bazel_skylib//tests/..." fails

WORKSPACE:

workspace(name = "foo")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

skylib_version = "0.8.0"
http_archive(
    name = "bazel_skylib",
    type = "tar.gz",
    url = "https://github.com/bazelbuild/bazel-skylib/releases/download/{}/bazel-skylib.{}.tar.gz".format (skylib_version, skylib_version),
    sha256 = "2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e",
)

load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")

bazel_skylib_workspace()

Command:

bazel build @bazel_skylib//tests/...

Output:

INFO: Analyzed 91 targets (0 packages loaded, 0 targets configured).
INFO: Found 91 targets...
ERROR: /usr/local/google/home/fwe/.cache/bazel/_bazel_fwe/ea0f404d46c6e8c3c74ad70e292ab53d/external/bazel_skylib/tests/maprule/BUILD:27:1: error executing shell command: '/bin/bash -c $MAPRULE_TOOL' failed (Exit 1) bash failed: error executing command /bin/bash -c '$MAPRULE_TOOL'

Use --sandbox_debug to see verbose messages from the sandbox
cat: ../bazel_skylib/tests/maprule/foo.txt: No such file or directory
INFO: Elapsed time: 0.440s, Critical Path: 0.12s
INFO: 3 processes: 3 linux-sandbox.
FAILED: Build did NOT complete successfully

bzl_library "builds" with missing deps

As seen in #49, you can update a .bzl file to add another load statement, but failing to add the dep for the skylark_library doesn't cause the build to break. If the skylark_library is then used to copy files for something like integration tests, those will fail as the file won't be found in the integration test's sandbox to be load()ed.

paths.relativize doesn't support a path not fully under start

The docs for paths.relativize compares itself to os.path.relpath, but the current implementation requires path be fully under start.

In theory it could also work for things that have a common prefix:

  • paths.relativize("foo/bar/baz", "foo/mumble") could return "../bar/baz"
  • paths.relativize("foo/bar", "foo/mumble/baz") could return "../../bar"
  • paths.relativize("foo/bar/baz", "mumble/grumble") could return "../../foo/bar/baz"

Right now these cases fail, so adding the support shouldn't break anyone. If callers want something fully nested, they could check the result to ensure it doesn't start with ...

Expand template rule

It's often useful to generate a file using a template. For example, to create a launcher script (usable from bazel run). Having to create a new rule for this can be annoying.

In the past, I've been using the following implementation and I think it could be useful to have it in Skylib. I'm pasting the code, hoping that someone will make a PR out of it. :)

"""Rule for simple expansion of template files. This performs a simple
search over the template file for the keys in substitutions,
and replaces them with the corresponding values.

Typical usage:
  load("//tools/build_rules:expand_template.bzl", "expand_template")
  expand_template(
      name = "ExpandMyTemplate",
      template = "my.template",
      out = "my.txt",
      substitutions = {
        "$VAR1": "foo",
        "$VAR2": "bar",
      }
  )

Args:
  name: The name of the rule.
  template: The template file to expand
  out: The destination of the expanded file
  substitutions: A dictionary mapping strings to their substitutions
  is_executable: A boolean indicating whether the output file should be executable
"""

def expand_template_impl(ctx):
    ctx.actions.expand_template(
        template = ctx.file.template,
        output = ctx.outputs.out,
        substitutions = {
            k: ctx.expand_location(v, ctx.attr.data)
            for k, v in ctx.attr.substitutions.items()
        },
        is_executable = ctx.attr.is_executable,
    )

expand_template = rule(
    implementation = expand_template_impl,
    attrs = {
        "template": attr.label(mandatory = True, allow_single_file = True),
        "substitutions": attr.string_dict(mandatory = True),
        "out": attr.output(mandatory = True),
        "is_executable": attr.bool(default = False, mandatory = False),
        "data": attr.label_list(allow_files = True),
    },
)

Add bzl_library support for @bazel_tools

(Maybe this belongs in Bazel's component.)

It was mentioned on the Slack that you can't define a bzl_library for your own .bzl files if they load files in @bazel_tools. At the same time, we can't just naively add bzl_library targets for each .bzl in @bazel_tools because it would make Bazel depend on skylib. The user also can't define their own bzl_library targets for the files in @bazel_tools due to visibility / exports_files issues.

As a somewhat clunky workaround, I suggest that we export all .bzl files underneath @bazel_tools with visibility granted to a specific subpackage, e.g. @bazel_tools//bzl_exports. That subpackage would load bzl_library from skylib and re-export these as bzl_library targets. This way, users who have skylib can depend on this subpackage, and users who don't have skylib will have no need to import it.

Hash mismatch

[ex@cube ~]$ curl -L https://github.com/bazelbuild/bazel-skylib/releases/download/0.8.0/bazel-skylib.0.8.0.tar.gz | shasum -a 256
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   616    0   616    0     0   1555      0 --:--:-- --:--:-- --:--:--  1551
100 72941  100 72941    0     0  59543      0  0:00:01  0:00:01 --:--:-- 59543
2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e  -
[ex@cube ~]$ curl https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/archive/0.8.0.tar.gz | shasum -a 256
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 73708  100 73708    0     0   278k      0 --:--:-- --:--:-- --:--:--  278k
2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a  -

1.0 release has different directions from rest of dep

https://github.com/bazelbuild/bazel-skylib/releases/tag/1.0.0

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "bazel-skylib",
    url = "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.0/bazel-skylib-1.0.0.tar.gz",
    sha256 = "e72747100a8b6002992cc0bf678f6279e71a3fd4a88cab3371ace6c73432be30",
)
load("@bazel-skylib//:deps.bzl", "bazel-skylib_dependencies")
bazel-skylib_dependencies()

But the WORKSPACE and all the docs say to call it bazel_skylib.

The last load also tries to load deps.bzl which does not exist, workspace.bzl does. bazel-skylib_dependencies isn't a valid Starlark symbol either.

paths.is_absolute on windows

There are probably more issues on windows, but the first one I hit is that c:/ should be recognized as an absolute path.

1.0 release doesn't appear to contain toolchains/unittest/BUILD

1.0 release doesn't appear to contain toolchains/unittest/BUILD

$ wget -O - https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.0/bazel-skylib-1.0.0.tar.gz 2>/dev/null | tar tzf -
./
./LICENSE
./BUILD
./CODEOWNERS
./CONTRIBUTORS
./lib/
./lib/BUILD
./lib/collections.bzl
./lib/dicts.bzl
./lib/new_sets.bzl
./lib/old_sets.bzl
./lib/partial.bzl
./lib/paths.bzl
./lib/selects.bzl
./lib/sets.bzl
./lib/shell.bzl
./lib/structs.bzl
./lib/types.bzl
./lib/unittest.bzl
./lib/versions.bzl
./rules/
./rules/BUILD
./rules/analysis_test.bzl
./rules/build_test.bzl
./rules/common_settings.bzl
./rules/copy_file.bzl
./rules/diff_test.bzl
./rules/empty_test.sh
./rules/native_binary.bzl
./rules/run_binary.bzl
./rules/write_file.bzl
./bzl_library.bzl
./internal_deps.bzl
./internal_setup.bzl
./lib.bzl
./skylark_library.bzl
./version.bzl
./workspace.bzl

Proposal for golden output testing rule

In #86 it appears the first rule is being added to skylib. Would there be any interest in adding a new rule that does golden comparison? To pick a name let's call it golden_test. I propose it is usable in 3 ways:

Literal:

golden_test(
    name = "content",
    src = ":myfile.txt", # Note that this could be the output of a genrule or other target
    content = "demonstration content for a test",
)

Regexp

golden_test(
    name = "content",
    src = ":myfile.txt", # Note that this could be the output of a genrule or other target
    regexp = "demonstration content for a .*",
)

Golden file

golden_test(
    name = "content",
    src = ":myfile.txt", # Note that this could be the output of a genrule or other target
    golden_file = ":myfile.golden.txt",
)

Would there be any interest in adding a rule like this? I believe that almost every rules_x has implemented something like this and consolidating on a single implementation seems like a not terrible idea.

CC: @c-parsons

rules/empty_test.sh isn't executable in tar.gz

rules/build_test.bzl uses empty_test.sh, but in the download it is no longer executable, so it builds trying to use it fail.

$ wget -O - https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.0/bazel-skylib-1.0.0.tar.gz 2>/dev/null | tar tvzf - | grep empty
-r--r--r-- 0/0             103 1999-12-31 19:00 ./rules/empty_test.sh

Test rule to verify aspect applied to another target

Some workflows apply a top level aspect to a build, such as:

bazel build //foo:bar --aspect=//baz:my_aspect.bzl%my_aspect

It would be nice to have a canonical test rule which would verify that builds such as these would work.

It should be as simple as creating a thin analysis test rule which applies the aspect along the edge. That is, a test rule with attribute defined:

deps' : attr.label_list(aspects = [my_aspect]),

And then, to satisfy the above example, the user could create a test target that has //foo:bar as one of its deps.

Shell tests: don't assume cwd is writable

The shell tests assume they are running in $TEST_TMPDIR or some other writable directory, but Bazel actually doesn't promise that.

Update tests to cd "$TEST_TMPDIR" before attempting to create any files or directories.

Windows: implement native_binary and native_test rules

Implement rules that allow wrapping a native binary (or native script) in a _binary and _test rule, so we can bazel run and bazel test it, or use as tools entry for other rules.

Desired semantics:

native_test(
  name = "my_bin",
  src = "my_bin.exe",
  args = ["--data=$(location some-data.txt)"],
  data = ["some-data.txt"],
)

Crucially these rules should use ctx.actions.run and NOT ctx.actions.run_shell, to avoid depending on Bash.

add a label resolving method

something like str(Label("//label")) so that rule developers have a nice method to resolve labels even if someone imports your repository in a different name.
Spotted with @damienmg during a hack session

Support minimum supported bazel version check from bazelisk's .bazelversion

Gerrit Code Review project is optionally supporting Bazelisk, by providing .bazelversion file. In the same time, we are checking the minimum supported Bazel version in WORKSPACE file by using bazel_skylib's versions.check() function (in case the build is invoked with Bazel and not with Bazelisk command), e.g.:

http_archive(
    name = "bazel_skylib",
    sha256 = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a",
    strip_prefix = "bazel-skylib-0.8.0",
    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.8.0.tar.gz"],
)

load("@bazel_skylib//lib:versions.bzl", "versions")

versions.check(minimum_bazel_version = "0.29.0")

However, this is disadvantageously, to maintain Bazel versions in two different places, and upgrade them in two places, when Bazel version is bumped, like it was done in this CL: [1]:

  1. .bazelversion
  2. WORKSPACE

What we need is a supported built-in way to check minimum supported Bazel version check from .bazelversion, e.g.:

bazel_version_check_from_bazelversion_file()

with the outcome, that the Build would break, if Bazel version is less than 0.29.

Bonus point, would be to not invoke anything, but just add a line in .bazelrc file, e.g.:

build --bazel_version_check_from_bazelversion_file

Even a bigger bonus point, when this check performed automatically, without saying anything (neither in WORKSPACE nor in .bazelrc files). So, if there is .bazelversion file with content 1.0.0, and I am invoking the build with bazel version 0.0.1, then the build should just fail.

[1] https://gerrit-review.googlesource.com/c/gerrit/+/232533

FR: strict deps for bzl_library

Suggest a model where srcs are parsed just enough to evaluate load() statements to ensure the label's .bzl file is a member of one of deps's SkylarkLibraryInfo's srcs, i.e., a direct dependency rather than a transitive dependency.

Feature request: a function that helps propagate implicitly added attributes

When a rule is wrapped in a macro or a rule instantiates another rule is it often needed to propagate implicitly added attributes like tags and visibility. Maybe there should be some helper function for this in skylib?

See bazelbuild/rules_k8s#137, the issue it fixes bazelbuild/rules_k8s#123 and a similar issue in rules_docker bazelbuild/rules_docker#269.
I guess many rules suffer from the same issue - implicit attributes are not propagated. Documenting what is the right thing to do in the "how to write rules" document (https://docs.bazel.build/versions/master/skylark/rules.html) would be great.

Improve documentation

We should, for example, use Stardoc to generate documentation for the rules / modules contained in this repository.

Support the builtin test attributes in the unittest module

I am writing some unit tests for custom skylark macros using the unittest module and would like to specify that each is a "short" test rather than the default "moderate", but can't figure out how. Currently some of my tests emit a warning that the tests were specified as the wrong size for their actual execution time.

You can currently create a unit test with custom attrs which are passed to the underlying test rule to specify dependencies of your test. However, this does not support specifying the builtin attributes for the test rules such as "size" and "timeout".

Here is a fake example testing a macro that implements the map() procedure:

load("@bazel_skylib//:lib.bzl", "unittest", "asserts")

def map(func, inputs):
    return [func(ele) for ele in inputs]

def _increment(ele)
    return ele + 1

def _macro_implementing_the_test(ctx):
    env = unittest.begin(ctx)
    inputs = [1, 2, 3, 4, 5]
    expected_output = [2, 3, 4, 5, 6]
    for results in zip(map(_increment, inputs), expected_output):
        asserts.equals(env, results[0], results[1])
    unittest.end(env)

map_test = unittest.make(_macro_implementing_the_test)

Once inside a BUILD file and executed this test results in a warning about the test execution time being outside the range of its "moderate" default. I would like to be able to specify the builtin attrs as optional positional arguments to unittest.make(...) to fix this:

map_test = unittest.make(_macro_implementing_the_test, size="small")

Can these builtin attributes be supported by unittest or if I am just approaching this wrong could some guidance be provided?

Should we add `types.is_struct`?

Like in #104, we're migrating rules_apple, and we have some places where we use a string or skylib's partial, we currently deal with this mainly by checking if it is a struct, the one catch is we also support None for the string, so flipping it to types.is_string doesn't exactly match. So, does it make sense to add types.is_struct to round out types?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.