pax_global_header00006660000000000000000000000064151744503620014521gustar00rootroot0000000000000052 comment=72291d1e2a6d92b4a2e0cf112982d1f6722a3485 bazel-skylib-1.9.1/000077500000000000000000000000001517445036200141215ustar00rootroot00000000000000bazel-skylib-1.9.1/.bazelci/000077500000000000000000000000001517445036200156105ustar00rootroot00000000000000bazel-skylib-1.9.1/.bazelci/presubmit.yml000066400000000000000000000041631517445036200203510ustar00rootroot00000000000000--- matrix: platform: - ubuntu2004 - ubuntu2204 - macos_arm64 - windows .reusable_build_flags: &reusable_build_flags ? "--incompatible_config_setting_private_default_visibility" ? "--incompatible_disallow_empty_glob" .reusable_test_flags: &reusable_test_flags <<: *reusable_build_flags ? "--test_env=PATH" .workspace_targets: &workspace_targets ? "--" ? "//..." # No longer run all the tests with WORKSPACE ? "-//docs/..." ? "-//tests/..." ? "-//distribution/..." .bzlmod_targets: &bzlmod_targets ? "--" ? "//..." ? "@external_directory_tests//..." ? "@bazel_skylib_gazelle_plugin//..." tasks: run_presubmit_bazel_7_workspace: name: "Bazel 7 (WORKSPACE)" platform: ${{ platform }} bazel: 7.x build_flags: <<: *reusable_build_flags ? "--enable_workspace" ? "--noenable_bzlmod" test_flags: <<: *reusable_test_flags ? "--enable_workspace" ? "--noenable_bzlmod" build_targets: *workspace_targets skip_in_bazel_downstream_pipeline: "Only Bazel 9 is relevant for the Downstream pipeline" run_presubmit_bazel_7_bzlmod: name: "Bazel 7 (Bzlmod)" platform: ${{ platform }} bazel: 7.x build_flags: <<: *reusable_build_flags ? "--noenable_workspace" test_flags: <<: *reusable_test_flags ? "--noenable_workspace" build_targets: *bzlmod_targets test_targets: <<: *bzlmod_targets ? "-//docs/..." skip_in_bazel_downstream_pipeline: "Only Bazel 9 is relevant for the Downstream pipeline" run_presubmit_bazel_8: name: "Bazel 8 (Bzlmod)" platform: ${{ platform }} bazel: 8.x build_flags: *reusable_build_flags test_flags: *reusable_test_flags build_targets: *bzlmod_targets test_targets: *bzlmod_targets skip_in_bazel_downstream_pipeline: "Only Bazel 9 is relevant for the Downstream pipeline" run_presubmit_bazel_9: name: "Bazel 9 (Bzlmod)" platform: ${{ platform }} bazel: 9.x build_flags: *reusable_build_flags test_flags: *reusable_test_flags build_targets: *bzlmod_targets test_targets: *bzlmod_targets buildifier: latest bazel-skylib-1.9.1/.bazelignore000066400000000000000000000000111517445036200164130ustar00rootroot00000000000000gazelle/ bazel-skylib-1.9.1/.bazelversion000066400000000000000000000000031517445036200166160ustar00rootroot000000000000008.xbazel-skylib-1.9.1/.bcr/000077500000000000000000000000001517445036200147455ustar00rootroot00000000000000bazel-skylib-1.9.1/.bcr/config.yml000066400000000000000000000000441517445036200167330ustar00rootroot00000000000000moduleRoots: - "." - "gazelle" bazel-skylib-1.9.1/.bcr/gazelle/000077500000000000000000000000001517445036200163705ustar00rootroot00000000000000bazel-skylib-1.9.1/.bcr/gazelle/metadata.template.json000066400000000000000000000004521517445036200226560ustar00rootroot00000000000000{ "homepage": "https://github.com/bazelbuild/bazel-skylib", "maintainers": [ { "email": "ilist@google.com", "github": "comius", "name": "Ivo Ristovski List" } ], "versions": [], "yanked_versions": {}, "repository": [ "github:bazelbuild/bazel-skylib" ] } bazel-skylib-1.9.1/.bcr/gazelle/presubmit.yml000066400000000000000000000005111517445036200211220ustar00rootroot00000000000000matrix: platform: - rockylinux8 - debian10 - macos - macos_arm64 - ubuntu2204 - ubuntu2404 - windows bazel: - 8.x - 7.x - 6.x tasks: verify_build_targets: name: "Verify build targets" platform: ${{ platform }} bazel: ${{ bazel }} build_targets: - "@bazel_skylib_gazelle_plugin//..." bazel-skylib-1.9.1/.bcr/gazelle/source.template.json000066400000000000000000000002331517445036200223730ustar00rootroot00000000000000{ "integrity": "", "strip_prefix": "", "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/bazel-skylib-gazelle-plugin-{TAG}.tar.gz" } bazel-skylib-1.9.1/.bcr/metadata.template.json000066400000000000000000000004521517445036200212330ustar00rootroot00000000000000{ "homepage": "https://github.com/bazelbuild/bazel-skylib", "maintainers": [ { "email": "ilist@google.com", "github": "comius", "name": "Ivo Ristovski List" } ], "versions": [], "yanked_versions": {}, "repository": [ "github:bazelbuild/bazel-skylib" ] } bazel-skylib-1.9.1/.bcr/presubmit.yml000066400000000000000000000004721517445036200175050ustar00rootroot00000000000000matrix: platform: - rockylinux8 - debian10 - macos - macos_arm64 - ubuntu2204 - ubuntu2404 - windows bazel: - 8.x - 7.x - 6.x tasks: verify_build_targets: name: "Verify build targets" platform: ${{ platform }} bazel: ${{ bazel }} build_targets: - "@bazel_skylib//..." bazel-skylib-1.9.1/.bcr/source.template.json000066400000000000000000000002141517445036200207470ustar00rootroot00000000000000{ "integrity": "", "strip_prefix": "", "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/bazel-skylib-{TAG}.tar.gz" } bazel-skylib-1.9.1/.github/000077500000000000000000000000001517445036200154615ustar00rootroot00000000000000bazel-skylib-1.9.1/.github/workflows/000077500000000000000000000000001517445036200175165ustar00rootroot00000000000000bazel-skylib-1.9.1/.github/workflows/publish.yaml000066400000000000000000000021261517445036200220510ustar00rootroot00000000000000name: Publish to BCR on: # Run the publish workflow after a successful release # Will be triggered from the release.yaml workflow workflow_call: inputs: tag_name: required: true type: string secrets: publish_token: required: true # In case of problems, let release engineers retry by manually dispatching # the workflow from the GitHub UI workflow_dispatch: inputs: tag_name: description: git tag being released required: true type: string jobs: publish: uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@v0.2.2 with: tag_name: ${{ inputs.tag_name }} # GitHub repository which is a fork of the upstream where the Pull Request will be opened. registry_fork: bazel-io/bazel-central-registry draft: false permissions: attestations: write contents: write id-token: write secrets: # Necessary to push to the BCR fork, and to open a pull request against a registry publish_token: ${{ secrets.publish_token || secrets.BCR_PUBLISH_TOKEN }} bazel-skylib-1.9.1/.github/workflows/release.yaml000066400000000000000000000016021517445036200220210ustar00rootroot00000000000000name: Release on: # Can be triggered from the tag.yaml workflow workflow_call: inputs: tag_name: required: true type: string secrets: publish_token: required: true # Or, developers can manually push a tag from their clone push: tags: - "*.*.*" permissions: id-token: write attestations: write contents: write jobs: release: uses: bazel-contrib/.github/.github/workflows/release_ruleset.yaml@v7.2.2 with: # Matches both the main and Gazelle plugin archives release_files: bazel-skylib-*.tar.gz prerelease: false tag_name: ${{ inputs.tag_name || github.ref_name }} publish: needs: release uses: ./.github/workflows/publish.yaml with: tag_name: ${{ inputs.tag_name || github.ref_name }} secrets: publish_token: ${{ secrets.publish_token || secrets.BCR_PUBLISH_TOKEN }} bazel-skylib-1.9.1/.github/workflows/release_prep.sh000077500000000000000000000044071517445036200225300ustar00rootroot00000000000000#!/usr/bin/env bash set -o errexit -o nounset -o pipefail # Argument provided by reusable workflow caller, see # https://github.com/bazel-contrib/.github/blob/d197a6427c5435ac22e56e33340dff912bc9334e/.github/workflows/release_ruleset.yaml#L72 VERSION=$1 bazel build //distribution:bazel-skylib ARCHIVE="$(bazel cquery --output=files //distribution:bazel-skylib)" SHA256SUM=$(shasum -a 256 "$ARCHIVE" | awk '{print $1}') bazel build //distribution:bazel-skylib-gazelle-plugin ARCHIVE_GAZELLE_PLUGIN="$(bazel cquery --output=files //distribution:bazel-skylib-gazelle-plugin)" SHA256SUM_GAZELLE_PLUGIN=$(shasum -a 256 "$ARCHIVE_GAZELLE_PLUGIN" | awk '{print $1}') # Move the archives to the root so that they are discoverable for upload mv "$ARCHIVE" . mv "$ARCHIVE_GAZELLE_PLUGIN" . cat << EOF **MODULE.bazel setup** \`\`\`starlark bazel_dep(name = "bazel_skylib", version = "$VERSION") \`\`\` And for the Gazelle plugin: \`\`\`starlark bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "$VERSION", dev_dependency = True) \`\`\` **WORKSPACE setup** \`\`\`starlark load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "bazel_skylib", sha256 = "$SHA256SUM", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/$VERSION/bazel-skylib-$VERSION.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/$VERSION/bazel-skylib-$VERSION.tar.gz", ], ) load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() \`\`\` ***Additional WORKSPACE setup for the Gazelle plugin*** \`\`\`starlark http_archive( name = "bazel_skylib_gazelle_plugin", sha256 = "$SHA256SUM_GAZELLE_PLUGIN", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/$VERSION/bazel-skylib-gazelle-plugin-$VERSION.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/$VERSION/bazel-skylib-gazelle-plugin-$VERSION.tar.gz", ], ) 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() \`\`\` EOF bazel-skylib-1.9.1/.gitignore000066400000000000000000000000321517445036200161040ustar00rootroot00000000000000/bazel-* MODULE.bazel.lockbazel-skylib-1.9.1/AUTHORS000066400000000000000000000004641517445036200151750ustar00rootroot00000000000000# This is the official list of Bazel authors for copyright purposes. # This file is distinct from the CONTRIBUTORS files. # See the latter for an explanation. # Names should be added to this file as: # Name or Organization # The email address is not required for organizations. Google Inc. bazel-skylib-1.9.1/BUILD000066400000000000000000000041721517445036200147070ustar00rootroot00000000000000load("@rules_license//rules:license.bzl", "license") load("//:bzl_library.bzl", "bzl_library") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) license( name = "license", package_name = "bazelbuild/bazel_skylib", license_kinds = ["@rules_license//licenses/spdx:Apache-2.0"], ) licenses(["notice"]) # buildifier: disable=skylark-comment # gazelle:exclude skylark_library.bzl exports_files([ "LICENSE", "MODULE.bazel", "WORKSPACE", ]) filegroup( name = "test_deps", testonly = True, srcs = [ "BUILD", "//lib:test_deps", "//rules:test_deps", "//toolchains/unittest:test_deps", ] + glob(["*.bzl"]), ) bzl_library( name = "lib", srcs = ["lib.bzl"], deprecation = ( "lib.bzl will go away in the future, please directly depend on the" + " module(s) needed as it is more efficient." ), deps = [ "//lib:collections", "//lib:dicts", "//lib:new_sets", "//lib:partial", "//lib:paths", "//lib:selects", "//lib:sets", "//lib:shell", "//lib:structs", "//lib:types", "//lib:unittest", "//lib:versions", ], ) bzl_library( name = "bzl_library", srcs = ["bzl_library.bzl"], deps = [ "//rules/private:bzl_library", ], ) bzl_library( name = "version", srcs = ["version.bzl"], ) bzl_library( name = "workspace", srcs = ["workspace.bzl"], ) # The files needed for distribution. # TODO(aiuto): We should strip this from the release, but there is no # capability now to generate BUILD.foo from BUILD and have it appear in the # tarball as BUILD. filegroup( name = "distribution", srcs = [ "BUILD", "CODEOWNERS", "CONTRIBUTORS", "LICENSE", "WORKSPACE.bzlmod", "//lib:distribution", "//rules:distribution", "//rules/directory:distribution", "//rules/directory/private:distribution", "//rules/private:distribution", "//toolchains/unittest:distribution", ] + glob(["*.bzl"]), ) bazel-skylib-1.9.1/CHANGELOG.md000066400000000000000000000316201517445036200157340ustar00rootroot00000000000000# Release 1.9.1 **What's Changed** * Revert allow_symlink = True by default for non-executables * Change from stamp to some other boolean flag * Update Bazel versions in CI: drop Bazel 6, add Bazel 9 **Contributors**: @gzm0, @kotlaja, @susinmotion, @justinhorvitz # Release 1.9.0 **What's Changed** * Optimize `copy_file` and set `allow_symlink` by default to `True` if `is_executable` is `False` (#565) * Give `rules/private:is_windows` an empty `applicable_license` (#600) * Bump `rules_go` dependency for compatibility with Bazel 9 (#601) **Contributors**: @fdinoff, @fmeum, @fweikert, @susinmotion **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.8.2...1.9.0 # Release 1.8.2 **New Features** * Introduce repeatable_string_flag (#593) **Other Changes** * Migrate `copy_directory` away from deprecated host constraint (#588) **Contributors** * fmeum@ * susinmotion@ # Release 1.8.1 **What's Changed** * Make `is_windows` public (https://github.com/bazelbuild/bazel-skylib/pull/584) **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.8.0...1.8.1 # Release 1.8.0 ## What's Changed * fix: subpackages.all works for root packages by @kilian-funk in https://github.com/bazelbuild/bazel-skylib/pull/531 * Strip compatible_with from bzl_library rules by @aiuto in https://github.com/bazelbuild/bazel-skylib/pull/522 * Make only root test_deps externally visible by @tetromino in https://github.com/bazelbuild/bazel-skylib/pull/508 * Update README.md by @BoleynSu in https://github.com/bazelbuild/bazel-skylib/pull/380 * Add test_deps to rules/private by @aiuto in https://github.com/bazelbuild/bazel-skylib/pull/534 * Fix bazel_skylib with Bazel@HEAD by @meteorcloudy in https://github.com/bazelbuild/bazel-skylib/pull/538 * Explicitly enable workspace for some tasks by @meteorcloudy in https://github.com/bazelbuild/bazel-skylib/pull/540 * README.md: fix broken directory rule links by @lukasoyen in https://github.com/bazelbuild/bazel-skylib/pull/544 * Remove sh_binary usage for Bazel 8 friendliness by @tetromino in https://github.com/bazelbuild/bazel-skylib/pull/550 * adding scope attributes for starlark flags by @aranguyen in https://github.com/bazelbuild/bazel-skylib/pull/546 * Update common_settings.bzl by @aranguyen in https://github.com/bazelbuild/bazel-skylib/pull/552 * Simplify CI steup and make presubmit green again by @meteorcloudy in https://github.com/bazelbuild/bazel-skylib/pull/557 * fix(gazelle): remove deprecated function call by @tyler-french in https://github.com/bazelbuild/bazel-skylib/pull/556 * Remove obsolete bazel 4.x compat code by @lukasoyen in https://github.com/bazelbuild/bazel-skylib/pull/560 * Add new "env" variable to native_* rules by @gioachin in https://github.com/bazelbuild/bazel-skylib/pull/561 * Replace outdated `select() on --cpu` with another flag ref by @gregestren in https://github.com/bazelbuild/bazel-skylib/pull/570 * Migrate away from `@bazel_tools//src/conditions:host_windows` by @fmeum in https://github.com/bazelbuild/bazel-skylib/pull/574 * Use DefaultInfo directly by @keith in https://github.com/bazelbuild/bazel-skylib/pull/577 * Use `native.package_relative_label` in `selects.bzl` by @fmeum in https://github.com/bazelbuild/bazel-skylib/pull/576 * Add BCR publishing workflow by @fmeum in https://github.com/bazelbuild/bazel-skylib/pull/581 ## New Contributors * @kilian-funk made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/531 * @BoleynSu made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/380 * @lukasoyen made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/544 * @aranguyen made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/546 * @tyler-french made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/556 * @gioachin made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/561 **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.7.1...1.8.0 # Release 1.7.1 **What's Changed** * Fix distribution tarballs to include directory rules. (https://github.com/bazelbuild/bazel-skylib/pull/520) **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.7.0...1.7.1 # Release 1.7.0 **New features** * Implement `directory` rules by @matts1 in https://github.com/bazelbuild/bazel-skylib/pull/510 * Add `is_normalized` and `starts_with` to paths module by @comius in https://github.com/bazelbuild/bazel-skylib/pull/514 **New Contributors** * @matts1 made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/510 **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.6.1...1.7.0 # Release 1.6.1 **What's Changed** * Fix `modules` Bazel 6 compatibility by @phst in https://github.com/bazelbuild/bazel-skylib/pull/499 **New Contributors** * @phst made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/499 **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.6.0...1.6.1 # Release 1.6.0 **What's Changed** * Add helper functions for module extensions as `modules` by @fmeum in https://github.com/bazelbuild/bazel-skylib/pull/457 * Make `out` on `native_binary` optional by @tpudlik in https://github.com/bazelbuild/bazel-skylib/pull/474 * Remove outdated rules_cc dependency @cpsauer in https://github.com/bazelbuild/bazel-skylib/pull/476 * Add toolchains argument to unittests.make by @jylinv0 in https://github.com/bazelbuild/bazel-skylib/pull/483 * Allow `bzl_library` to depend on non-`bzl_library` targets by @Wyverald in https://github.com/bazelbuild/bazel-skylib/pull/495 **New Contributors** * @jylinv0 made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/483 * @tpudlik made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/474 **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.5.0...1.6.0 # Release 1.5.0 **What's Changed** * Expose int- and string-valued build settings as Make variables by @fmeum in https://github.com/bazelbuild/bazel-skylib/pull/440 * Modify actions in order not to need `toolchain` param by @kotlaja in https://github.com/bazelbuild/bazel-skylib/pull/455 * versions: Don't fail on Bazel dev builds by @fmeum in https://github.com/bazelbuild/bazel-skylib/pull/463 * Add error for empty `bzl_library` by @keith in https://github.com/bazelbuild/bazel-skylib/pull/457 * Add `doc` param to `unittest.make` by @UebelAndre in https://github.com/bazelbuild/bazel-skylib/pull/464 **New Contributors** * @kotlaja made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/455 * @keith made their first contribution in https://github.com/bazelbuild/bazel-skylib/pull/457 **Full Changelog**: https://github.com/bazelbuild/bazel-skylib/compare/1.4.2...1.5.0 # Release 1.4.2 Bugfix release: fixes `build_test` to respect `target_compatible_with` (#448) **New Features** - `bzl_library` allows `.scl` files (new Starlark dialect loadable by Bazel at HEAD with `--experimental_enable_scl_dialect`) **Contributors** Alexandre Rostovtsev, UebelAndre, Vertexwahn, Xavier Bonaventura # Release 1.4.1 Bugfix release: fixes gazelle plugin failure with `--incompatible_disallow_empty_glob` (#431) and (for released versions) with `--incompatible_disable_starlark_host_transitions` (#433). **Contributors** Alexandre Rostovtsev, Chuck Grindel # Release 1.4.0 **New Features** - The Gazelle plugin is marked stable for general use (#400, #424) **Other Notable Changes** - copy_file/copy_directory again allow sandboxing (#392) **Contributors** Alexandre Rostovtsev, Nick Gooding, Simon Stewart, Xùdōng Yáng # Release 1.3.0 **New Features** - Added `dicts.omit` and `dicts.pick` (#304) - Added `expand_template` rule (#330) - Added `subpackages` module (#348) - Added `copy_directory` rule (#366) - Added `bzlmod` support (#385) **Incompatible Changes** - `native_binary` and `native_test` now use symlinks instead of copying, if the OS supports it (#340) - `native_binary` and `native_test` now build in target configuration instead of host configuration (#341) - `copy_file` no longer adds non-executables to `default_runfiles` (#326) **Contributors** Alex Eagle, Alexandre Rostovtsev, Barry McNamara, Derek Cormier, Fabian Meumertzheim, Geoffrey Martin-Noble, hchsiao, Kevin Kres, nickgooding, Vertexwahn, Vinh Tran # Release 1.2.1 Bugfix release: fixes build failure with --incompatible_disallow_empty_glob (#359) **Contributors** Alexandre Rostovtsev, Ivo List Release 1.2.0 **New Features** - The unittest toolchain has better support for special characters in failure messages (#320) - Use portable Bash shebangs for BSD compatibility (#329) - Add loadingtest - tests which evaluate during the loading phase (#347) - Add doc parameter to analysistest.make, allowing analysis tests to be documented in a Stardoc-friendly way (#343, #352) **Contributors** Alexandre Rostovtsev, Geoffrey Martin-Noble, Kevin Kress, Samuel Freilich, UebelAndre, Yesudeep Mangalapilly # Release 1.1.1 (initially tagged as 1.1.0) **New Features** - Gazelle: support relative imports (#271) and imports from `@bazel_tools` (#273) - Add partial.is_instance() (#276) - Allow unittest.suite() to accept partial calls of test rules (#276) - Allow specifying additional aspects to target under test in analysistest.make() (#299) - Add Windows support for build_test (#302) **Incompatible Changes** - structs.to_dict() ignores deprecated to_json()/to_proto() methods (#295) **Contributors** aiuto, alandonovan, Alex Eagle, Alexandre Rostovtsev, Andrew Z Allen, c-parsons, Christopher Sauer, Daniel Wagner-Hall, David Sanderson, dmaclach, Laurent Le Brun, Mansur, Olek Wojnar, Philipp Wollermann, River, Samuel Giddins, Thaler Benedek # Release 1.0.3 **Significant Changes** - Move Gazelle extension to //gazelle/bzl and change package name - Stop depending on rules_pkg through the federation. (#259) - copy_file: Add parameter to allow symlinks (#252) - Create Gazelle language for Starlark (#251) - Create a helper rule (`select_file`) for selecting a file from outputs of another rule (#233) **Incompatible Changes** - Remove links to maprules (#213) - Remove old_sets.bzl (#231) It has been deprecated for a while, the code is not really compatible with Bazel depset-related changes. **Contributors** Andrew Z Allen, Bocete, Bor Kae Hwang, irengrig, Jay Conrod, Jonathan B Coe, Marc Plano-Lesay, Robbert van Ginkel, Thomas Van Lenten, Yannic # Release 1.0.0 **Incompatible Changes** - @bazel_skylib//:lib.bzl is removed. You now must specify specific modules via @bazel_skylib//lib:.bzl. - maprule.bzl is removed. **New Features** - Added types.is_set() to test whether an arbitrary object is a set as defined by sets.bzl. # Release 0.9.0 **New Features** - common_settings.bzl: Standard data types for user defined build configuration. Common scalar build settings for rules to use so they don't recreate them locally. This fulfills part of the SBC design doc: https://docs.google.com/document/d/1vc8v-kXjvgZOdQdnxPTaV0rrLxtP2XwnD2tAZlYJOqw/edit#bookmark=id.iiumwic0jphr - selects.bzl: Add config_setting_group for config_setting AND/OR-chaining Implements https://github.com/bazelbuild/proposals/blob/HEAD/designs/2018-11-09-config-setting-chaining.md. - Make sets.bzl point to new_sets.bzl instead of old_sets.bzl. new_sets.bzl and old_sets.bzl should be removed in the following skylib release. - run_binary: runs an executable as an action - This rule is an alternative for genrule(): it can run a binary with the desired arguments, environment, inputs, and outputs, as a single build action, without shelling out to Bash. - Fixes https://github.com/bazelbuild/bazel-skylib/issues/149 - New `native_binary()` and `native_test()` rules let you wrap a pre-built binary in a binary and test rule respectively. - native_binary() wraps a pre-built binary or script in a *_binary rule interface. Rules like genrule can tool-depend on it, and it can be executed with "bazel run". This rule can also augment the binary with runfiles. - native_test() is similar, but creates a testable rule instead of a binary rule. - Fixes https://github.com/bazelbuild/bazel-skylib/issues/148 - diff_test: test rule compares two files and passes if the files match. On Linux/macOS/non-Windows, the test compares files using 'diff'. On Windows, the test compares files using 'fc.exe'. This utility is available on all Windows versions I tried (Windows 2008 Server, Windows 2016 Datacenter Core). See https://github.com/bazelbuild/bazel/issues/5508, https://github.com/bazelbuild/bazel/issues/4319 - maprule: move functionality to maprule_util.bzl. maprule_util.bzl will benefit planned new rules (namely a genrule alternative). **This release is tested with Bazel 0.28** bazel-skylib-1.9.1/CODEOWNERS000066400000000000000000000002411517445036200155110ustar00rootroot00000000000000# More details on syntax here: https://help.github.com/articles/about-codeowners/ * @brandjon @tetromino @comius @hvadehra @c-mita /gazelle/ @achew22 @jayconrod bazel-skylib-1.9.1/CONTRIBUTING.md000066400000000000000000000026751517445036200163640ustar00rootroot00000000000000Want to contribute? Great! First, read this page (including the small print at the end). ### Before you contribute **Before we can use your code, you must sign the [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) (CLA)**, which you can do online. The CLA is necessary mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code. We also need to be sure of various other things — for instance that you'll tell us if you know that your code infringes on other people's patents. You don't have to sign the CLA until after you've submitted your code for review and a member has approved it, but you must do it before we can put your code into our codebase. Before you start working on a larger contribution, you should get in touch with us first. Use the issue tracker to explain your idea so we can help and possibly guide you. ### Code reviews and other contributions. **All submissions, including submissions by project members, require review.** Please follow the instructions in [the contributors documentation](http://bazel.io/contributing.html). ### The small print Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). bazel-skylib-1.9.1/CONTRIBUTORS000066400000000000000000000013621517445036200160030ustar00rootroot00000000000000# People who have agreed to one of the CLAs and can contribute patches. # The AUTHORS file lists the copyright holders; this file # lists people. For example, Google employees are listed here # but not in AUTHORS, because Google holds the copyright. # # https://developers.google.com/open-source/cla/individual # https://developers.google.com/open-source/cla/corporate # # Names should be added to this file as: # Name Tony Allevato Jon Brandvein bttk Chris Parsons Dave MacLachlan Dmitry Lomov Jingwen Chen Laurent Le Brun Nathan Herring bazel-skylib-1.9.1/LICENSE000066400000000000000000000261361517445036200151360ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. bazel-skylib-1.9.1/MODULE.bazel000066400000000000000000000034271517445036200161330ustar00rootroot00000000000000module( name = "bazel_skylib", # Keep in sync with version.bzl and @bazel_skylib_gazelle_plugin//:MODULE.bazel version = "1.9.1", compatibility_level = 1, ) register_toolchains( "//toolchains/unittest:cmd_toolchain", "//toolchains/unittest:bash_toolchain", ) bazel_dep(name = "platforms", version = "0.0.10") bazel_dep(name = "rules_license", version = "1.0.0") ### INTERNAL ONLY - lines after this are not included in the release packaging. # Build-only / test-only dependencies bazel_dep(name = "stardoc", version = "0.8.0", dev_dependency = True, repo_name = "io_bazel_stardoc") bazel_dep(name = "rules_pkg", version = "1.0.1", dev_dependency = True) bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True) bazel_dep(name = "rules_cc", version = "0.0.17", dev_dependency = True) bazel_dep(name = "rules_shell", version = "0.3.0", dev_dependency = True) # Needed for bazelci and for building distribution tarballs. # If using an unreleased version of bazel_skylib via git_override, apply # MODULE.bazel-remove-override.patch to remove the following lines: bazel_dep(name = "bazel_skylib_gazelle_plugin", dev_dependency = True) local_path_override( module_name = "bazel_skylib_gazelle_plugin", path = "gazelle", ) external_directory_tests_ext = use_extension("//tests/directory:external_directory_tests.bzl", "external_directory_tests_ext", dev_dependency = True) use_repo(external_directory_tests_ext, "external_directory_tests") as_extension_test_ext = use_extension("//tests:modules_test.bzl", "as_extension_test_ext", dev_dependency = True) use_repo(as_extension_test_ext, "bar", "foo") use_all_repos_test_ext = use_extension("//tests:modules_test.bzl", "use_all_repos_test_ext", dev_dependency = True) use_repo(use_all_repos_test_ext, "baz", "qux") bazel-skylib-1.9.1/MODULE.bazel-remove-override.patch000066400000000000000000000011371517445036200223350ustar00rootroot00000000000000--- MODULE.bazel +++ MODULE.bazel @@ -22,8 +22,8 @@ # Needed for bazelci and for building distribution tarballs. # If using an unreleased version of bazel_skylib via git_override, apply # MODULE.bazel-remove-override.patch to remove the following lines: -bazel_dep(name = "bazel_skylib_gazelle_plugin", dev_dependency = True) -local_path_override( - module_name = "bazel_skylib_gazelle_plugin", - path = "gazelle", -) +# bazel_dep(name = "bazel_skylib_gazelle_plugin", dev_dependency = True) +# local_path_override( +# module_name = "bazel_skylib_gazelle_plugin", +# path = "gazelle", +# ) bazel-skylib-1.9.1/README.md000066400000000000000000000147011517445036200154030ustar00rootroot00000000000000# Skylib [![Build status](https://badge.buildkite.com/921dc61e2d3a350ec40efb291914360c0bfa9b6196fa357420.svg?branch=main)](https://buildkite.com/bazel/bazel-skylib) 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](https://github.com/bazelbuild/bazel-skylib/releases). 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: ```python 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](#list-of-modules)) and access the symbols by dotting into those structs: ```python 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/) * [collections](docs/collections_doc.md) * [dicts](docs/dicts_doc.md) * [partial](docs/partial_doc.md) * [paths](docs/paths_doc.md) * [selects](docs/selects_doc.md) * [sets](docs/new_sets_doc.md) * [modules](docs/modules_doc.md) * [shell](docs/shell_doc.md) * [structs](docs/structs_doc.md) * [subpackages](docs/subpackages_doc.md) * [types](docs/types_doc.md) * [unittest](docs/unittest_doc.md) * [versions](docs/versions_doc.md) ## List of rules (in rules/) * [analysis_test](docs/analysis_test_doc.md) * [build_test](docs/build_test_doc.md) * [common_settings](docs/common_settings_doc.md) * directories * [directory](docs/directory_doc.md) * [directory_glob](docs/directory_glob_doc.md) * [subdirectory](docs/directory_subdirectory_doc.md) * [copy_directory](docs/copy_directory_doc.md) * [copy_file](docs/copy_file_doc.md) * [diff_test](docs/diff_test_doc.md) * [expand_template](docs/expand_template_doc.md) * [native_binary and native_test](docs/native_binary_doc.md) * [run_binary](docs/run_binary_doc.md) * [select_file](docs/select_file_doc.md) * [write_file](docs/write_file_doc.md) ## 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. 1. 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. 1. 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. 1. 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. 1. Write the functions or other symbols (such as constants) in that file, defining them privately (prefixed by an underscore). 1. 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: ```python def _manipulate(): ... things = struct( manipulate=_manipulate, ) ``` 1. 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](docs/maintainers_guide.md) for instructions for cutting a new release. ## Gazelle Plugin `bazel_skylib` ships with a [gazelle](https://github.com/bazelbuild/bazel-gazelle) plugin to generate `bzl_library` entries in build files. To use this, in your `WORKSPACE`: ```starlark 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: ```starlark 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-1.9.1/WORKSPACE000066400000000000000000000064221517445036200154060ustar00rootroot00000000000000workspace(name = "bazel_skylib") load(":workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() ### INTERNAL ONLY - lines after this are not included in the release packaging. # Lines below are for tests, documentation generation, and distribution archive # generation only, and should thus not be included by dependencies on bazel-skylib. load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") local_repository( name = "bazel_skylib_gazelle_plugin", path = "gazelle", ) 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() http_archive( name = "rules_cc", sha256 = "abc605dd850f813bb37004b77db20106a19311a96b2da1c92b789da529d28fe1", strip_prefix = "rules_cc-0.0.17", urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.17/rules_cc-0.0.17.tar.gz"], ) http_archive( name = "rules_shell", sha256 = "d8cd4a3a91fc1dc68d4c7d6b655f09def109f7186437e3f50a9b60ab436a0c53", strip_prefix = "rules_shell-0.3.0", url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.3.0/rules_shell-v0.3.0.tar.gz", ) load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains") rules_shell_dependencies() rules_shell_toolchains() maybe( http_archive, name = "io_bazel_stardoc", sha256 = "62bd2e60216b7a6fec3ac79341aa201e0956477e7c8f6ccc286f279ad1d96432", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/stardoc/releases/download/0.6.2/stardoc-0.6.2.tar.gz", "https://github.com/bazelbuild/stardoc/releases/download/0.6.2/stardoc-0.6.2.tar.gz", ], ) load("@io_bazel_stardoc//:setup.bzl", "stardoc_repositories") stardoc_repositories() load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps") rules_jvm_external_deps() load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup") rules_jvm_external_setup() load("@io_bazel_stardoc//:deps.bzl", "stardoc_external_deps") stardoc_external_deps() load("@stardoc_maven//:defs.bzl", stardoc_pinned_maven_install = "pinned_maven_install") stardoc_pinned_maven_install() maybe( http_archive, name = "rules_pkg", sha256 = "8f9ee2dc10c1ae514ee599a8b42ed99fa262b757058f65ad3c384289ff70c4b8", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.9.1/rules_pkg-0.9.1.tar.gz", "https://github.com/bazelbuild/rules_pkg/releases/download/0.9.1/rules_pkg-0.9.1.tar.gz", ], ) load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") rules_pkg_dependencies() http_archive( name = "rules_testing", sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4", strip_prefix = "rules_testing-0.6.0", url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.6.0/rules_testing-v0.6.0.tar.gz", ) load("//lib:unittest.bzl", "register_unittest_toolchains") load("//tests/directory:external_directory_tests.bzl", "external_directory_tests") external_directory_tests(name = "external_directory_tests") register_unittest_toolchains() bazel-skylib-1.9.1/WORKSPACE.bzlmod000066400000000000000000000001451517445036200166700ustar00rootroot00000000000000# Workaround so that targets prefixed with @bazel_skylib still work workspace(name = "bazel_skylib") bazel-skylib-1.9.1/bzl_library.bzl000066400000000000000000000027051517445036200171510ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing a library rule for aggregating rules files.""" # buildifier: disable=bzl-visibility load( "//rules/private:bzl_library.bzl", _StarlarkLibraryInfo = "StarlarkLibraryInfo", _bzl_library = "bzl_library", ) StarlarkLibraryInfo = _StarlarkLibraryInfo def bzl_library(name, **kwargs): """Wrapper for bzl_library. Args: name: name **kwargs: see the generated doc for rules/private/bzl_library. """ # buildifier: disable=unused-variable _ = kwargs.pop("compatible_with", None) _ = kwargs.pop("exec_compatible_with", None) _ = kwargs.pop("features", None) _ = kwargs.pop("target_compatible_with", None) _bzl_library( name = name, compatible_with = [], exec_compatible_with = [], features = [], target_compatible_with = [], **kwargs ) bazel-skylib-1.9.1/distribution/000077500000000000000000000000001517445036200166405ustar00rootroot00000000000000bazel-skylib-1.9.1/distribution/BUILD000066400000000000000000000044501517445036200174250ustar00rootroot00000000000000load("@bazel_skylib//:version.bzl", "version") load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("distribution.bzl", "remove_internal_only") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:private"], ) licenses(["notice"]) remove_internal_only( name = "distro_workspace", src = "//:WORKSPACE", out = "WORKSPACE", ) remove_internal_only( name = "distro_module_bazel", src = "//:MODULE.bazel", out = "MODULE.bazel", ) # remove "distribution/" path prefix pkg_files( name = "distro-files-without-prefix", srcs = [ "distro_module_bazel", "distro_workspace", ], strip_prefix = strip_prefix.from_pkg(), ) pkg_tar( name = "bazel-skylib", srcs = [ "distro-files-without-prefix", "//:distribution", ], out = "bazel-skylib-%s.tar.gz" % version, extension = "tar.gz", mode = "0644", # Make it owned by root so it does not have the uid of the CI robot. owner = "0.0", strip_prefix = strip_prefix.from_root(), ) # @bazel_skylib_gazelle_plugin//:WORKSPACE refers to bazel-skylib in the parent # directory. For distribution, use the minimal WORSKPACE.bzlmod instead. pkg_files( name = "bazel-skylib-gazelle-plugin-distro_workspace", srcs = ["@bazel_skylib_gazelle_plugin//:WORKSPACE.bzlmod"], renames = {"@bazel_skylib_gazelle_plugin//:WORKSPACE.bzlmod": "WORKSPACE"}, ) pkg_files( name = "bazel-skylib-gazelle-plugin-without-external-prefix", srcs = [ "@bazel_skylib_gazelle_plugin//:distribution", "@bazel_skylib_gazelle_plugin//bzl:distribution", ], strip_prefix = strip_prefix.from_root(), ) pkg_tar( name = "bazel-skylib-gazelle-plugin", srcs = [ "bazel-skylib-gazelle-plugin-distro_workspace", "bazel-skylib-gazelle-plugin-without-external-prefix", "//:LICENSE", ], out = "bazel-skylib-gazelle-plugin-%s.tar.gz" % version, extension = "tar.gz", mode = "0644", # Make it owned by root so it does not have the uid of the CI robot. owner = "0.0", ) # Build the artifacts to put on the github release page. filegroup( name = "distribution", srcs = [ "bazel-skylib", "bazel-skylib-gazelle-plugin", ], ) bazel-skylib-1.9.1/distribution/distribution.bzl000066400000000000000000000021371517445036200220730ustar00rootroot00000000000000# Copyright 2023 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helper utilities for generating distribution tarballs.""" def remove_internal_only(name, src, out, **kwargs): """Removes '### INTERNAL ONLY' line and all lines below from a file. Args: name: Name of the rule. src: File to process. out: Path of the output file. **kwargs: further keyword arguments. """ native.genrule( name = name, srcs = [src], outs = [out], cmd = "sed -e '/### INTERNAL ONLY/,$$d' $< >$@", **kwargs ) bazel-skylib-1.9.1/docs/000077500000000000000000000000001517445036200150515ustar00rootroot00000000000000bazel-skylib-1.9.1/docs/BUILD000066400000000000000000000105341517445036200156360ustar00rootroot00000000000000load("//docs/private:stardoc_with_diff_test.bzl", "stardoc_with_diff_test", "update_docs") package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) stardoc_with_diff_test( name = "analysis_test", bzl_library_target = "//rules:analysis_test", out_label = "//docs:analysis_test_doc.md", ) stardoc_with_diff_test( name = "build_test", bzl_library_target = "//rules:build_test", out_label = "//docs:build_test_doc.md", ) stardoc_with_diff_test( name = "bzl_library", bzl_library_target = "//rules/private:bzl_library", out_label = "//docs:bzl_library.md", ) stardoc_with_diff_test( name = "collections", bzl_library_target = "//lib:collections", out_label = "//docs:collections_doc.md", ) stardoc_with_diff_test( name = "common_settings", bzl_library_target = "//rules:common_settings", out_label = "//docs:common_settings_doc.md", ) stardoc_with_diff_test( name = "copy_directory", bzl_library_target = "//rules:copy_directory", out_label = "//docs:copy_directory_doc.md", ) stardoc_with_diff_test( name = "copy_file", bzl_library_target = "//rules:copy_file", out_label = "//docs:copy_file_doc.md", ) stardoc_with_diff_test( name = "dicts", bzl_library_target = "//lib:dicts", out_label = "//docs:dicts_doc.md", ) stardoc_with_diff_test( name = "diff_test", bzl_library_target = "//rules:diff_test", out_label = "//docs:diff_test_doc.md", ) stardoc_with_diff_test( name = "directory", bzl_library_target = "//rules/directory:directory", out_label = "//docs:directory_doc.md", ) stardoc_with_diff_test( name = "directory_glob", bzl_library_target = "//rules/directory:glob", out_label = "//docs:directory_glob_doc.md", ) stardoc_with_diff_test( name = "directory_providers", bzl_library_target = "//rules/directory:providers", out_label = "//docs:directory_providers_doc.md", ) stardoc_with_diff_test( name = "directory_subdirectory", bzl_library_target = "//rules/directory:subdirectory", out_label = "//docs:directory_subdirectory_doc.md", ) stardoc_with_diff_test( name = "expand_template", bzl_library_target = "//rules:expand_template", out_label = "//docs:expand_template_doc.md", ) stardoc_with_diff_test( name = "modules", bzl_library_target = "//lib:modules", out_label = "//docs:modules_doc.md", ) stardoc_with_diff_test( name = "native_binary", bzl_library_target = "//rules:native_binary", out_label = "//docs:native_binary_doc.md", ) stardoc_with_diff_test( name = "new_sets", bzl_library_target = "//lib:new_sets", out_label = "//docs:new_sets_doc.md", ) stardoc_with_diff_test( name = "partial", bzl_library_target = "//lib:partial", out_label = "//docs:partial_doc.md", ) stardoc_with_diff_test( name = "paths", bzl_library_target = "//lib:paths", out_label = "//docs:paths_doc.md", ) stardoc_with_diff_test( name = "run_binary", bzl_library_target = "//rules:run_binary", out_label = "//docs:run_binary_doc.md", ) stardoc_with_diff_test( name = "selects", bzl_library_target = "//lib:selects", out_label = "//docs:selects_doc.md", ) stardoc_with_diff_test( name = "select_file", bzl_library_target = "//rules:select_file", out_label = "//docs:select_file_doc.md", ) stardoc_with_diff_test( name = "shell", bzl_library_target = "//lib:shell", out_label = "//docs:shell_doc.md", ) stardoc_with_diff_test( name = "structs", bzl_library_target = "//lib:structs", out_label = "//docs:structs_doc.md", ) stardoc_with_diff_test( name = "subpackages", bzl_library_target = "//lib:subpackages", out_label = "//docs:subpackages_doc.md", ) stardoc_with_diff_test( name = "types", bzl_library_target = "//lib:types", out_label = "//docs:types_doc.md", ) stardoc_with_diff_test( name = "unittest", bzl_library_target = "//lib:unittest", out_label = "//docs:unittest_doc.md", ) stardoc_with_diff_test( name = "versions", bzl_library_target = "//lib:versions", out_label = "//docs:versions_doc.md", ) stardoc_with_diff_test( name = "write_file", bzl_library_target = "//rules:write_file", out_label = "//docs:write_file_doc.md", ) # update_docs must be at the bottom of the BUILD file update_docs( name = "update", docs_folder = "docs", ) bazel-skylib-1.9.1/docs/analysis_test_doc.md000077500000000000000000000034421517445036200211100ustar00rootroot00000000000000 A test verifying other targets can be successfully analyzed as part of a `bazel test` ## analysis_test
load("@bazel_skylib//rules:analysis_test.bzl", "analysis_test")

analysis_test(name, targets)
Test rule checking that other targets can be successfully analyzed. This rule essentially verifies that all targets under `targets` would generate no errors when analyzed with `bazel build [targets] --nobuild`. Action success/failure for the targets and their transitive dependencies are not verified. An analysis test simply ensures that each target in the transitive dependencies propagate providers appropriately and register actions for their outputs appropriately. NOTE: If the targets fail to analyze, instead of the analysis_test failing, the analysis_test will fail to build. Ideally, it would instead result in a test failure. This is a current infrastructure limitation that may be fixed in the future. Typical usage: load("@bazel_skylib//rules:analysis_test.bzl", "analysis_test") analysis_test( name = "my_analysis_test", targets = [ "//some/package:rule", ], ) Args: name: The name of the test rule. targets: A list of targets to ensure build. **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | targets | - | List of labels | required | | bazel-skylib-1.9.1/docs/build_test_doc.md000077500000000000000000000023011517445036200203550ustar00rootroot00000000000000 A test verifying other targets build as part of a `bazel test` ## build_test
load("@bazel_skylib//rules:build_test.bzl", "build_test")

build_test(name, targets, **kwargs)
Test rule checking that other targets build. This works not by an instance of this test failing, but instead by the targets it depends on failing to build, and hence failing the attempt to run this test. Typical usage: ``` load("@bazel_skylib//rules:build_test.bzl", "build_test") build_test( name = "my_build_test", targets = [ "//some/package:rule", ], ) ``` **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | The name of the test rule. | none | | targets | A list of targets to ensure build. | none | | kwargs | The [common attributes for tests](https://bazel.build/reference/be/common-definitions#common-attributes-tests). | none | bazel-skylib-1.9.1/docs/bzl_library.md000077500000000000000000000047761517445036200177270ustar00rootroot00000000000000 Skylib module containing a library rule for aggregating rules files. ## bzl_library
load("@bazel_skylib//rules/private:bzl_library.bzl", "bzl_library")

bzl_library(name, deps, srcs)
Creates a logical collection of Starlark .bzl and .scl files. Example: Suppose your project has the following structure: ``` [workspace]/ WORKSPACE BUILD checkstyle/ BUILD checkstyle.bzl lua/ BUILD lua.bzl luarocks.bzl ``` In this case, you can have `bzl_library` targets in `checkstyle/BUILD` and `lua/BUILD`: `checkstyle/BUILD`: ```python load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "checkstyle-rules", srcs = ["checkstyle.bzl"], ) ``` `lua/BUILD`: ```python load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "lua-rules", srcs = [ "lua.bzl", "luarocks.bzl", ], ) ``` **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | deps | List of other `bzl_library` or `filegroup` targets that are required by the Starlark files listed in `srcs`. | List of labels | optional | `[]` | | srcs | List of `.bzl` and `.scl` files that are processed to create this target. | List of labels | optional | `[]` | ## StarlarkLibraryInfo
load("@bazel_skylib//rules/private:bzl_library.bzl", "StarlarkLibraryInfo")

StarlarkLibraryInfo(srcs, transitive_srcs)
Information on contained Starlark rules. **FIELDS** | Name | Description | | :------------- | :------------- | | srcs | Top level rules files. | | transitive_srcs | Transitive closure of rules files required for interpretation of the srcs | bazel-skylib-1.9.1/docs/collections_doc.md000077500000000000000000000042301517445036200205400ustar00rootroot00000000000000 Skylib module containing functions that operate on collections. ## collections.after_each
load("@bazel_skylib//lib:collections.bzl", "collections")

collections.after_each(separator, iterable)
Inserts `separator` after each item in `iterable`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | separator | The value to insert after each item in `iterable`. | none | | iterable | The list into which to intersperse the separator. | none | **RETURNS** A new list with `separator` after each item in `iterable`. ## collections.before_each
load("@bazel_skylib//lib:collections.bzl", "collections")

collections.before_each(separator, iterable)
Inserts `separator` before each item in `iterable`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | separator | The value to insert before each item in `iterable`. | none | | iterable | The list into which to intersperse the separator. | none | **RETURNS** A new list with `separator` before each item in `iterable`. ## collections.uniq
load("@bazel_skylib//lib:collections.bzl", "collections")

collections.uniq(iterable)
Returns a list of unique elements in `iterable`. Requires all the elements to be hashable. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | iterable | An iterable to filter. | none | **RETURNS** A new list with all unique elements from `iterable`. bazel-skylib-1.9.1/docs/common_settings_doc.md000077500000000000000000000230001517445036200214260ustar00rootroot00000000000000 Common build setting rules These rules return a BuildSettingInfo with the value of the build setting. For label-typed settings, use the native label_flag and label_setting rules. More documentation on how to use build settings at https://bazel.build/extending/config#user-defined-build-settings ## bool_flag
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")

bool_flag(name, scope)
A bool-typed build setting that can be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## bool_setting
load("@bazel_skylib//rules:common_settings.bzl", "bool_setting")

bool_setting(name, scope)
A bool-typed build setting that cannot be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## int_flag
load("@bazel_skylib//rules:common_settings.bzl", "int_flag")

int_flag(name, make_variable, scope)
An int-typed build setting that can be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | make_variable | If set, the build setting's value will be available as a Make variable with this name in the attributes of rules that list this build setting in their 'toolchains' attribute. | String | optional | `""` | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## int_setting
load("@bazel_skylib//rules:common_settings.bzl", "int_setting")

int_setting(name, make_variable, scope)
An int-typed build setting that cannot be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | make_variable | If set, the build setting's value will be available as a Make variable with this name in the attributes of rules that list this build setting in their 'toolchains' attribute. | String | optional | `""` | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## repeatable_string_flag
load("@bazel_skylib//rules:common_settings.bzl", "repeatable_string_flag")

repeatable_string_flag(name, scope)
A build setting that accepts one or more string-typed settings on the command line, with the values concatenated into a single string list; for example, `--//my/setting=foo` `--//my/setting=bar` will be parsed as `['foo', 'bar']`. Contrast with `string_list_flag` **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## string_flag
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")

string_flag(name, make_variable, scope, values)
A string-typed build setting that can be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | make_variable | If set, the build setting's value will be available as a Make variable with this name in the attributes of rules that list this build setting in their 'toolchains' attribute. | String | optional | `""` | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | | values | The list of allowed values for this setting. An error is raised if any other value is given. | List of strings | optional | `[]` | ## string_list_flag
load("@bazel_skylib//rules:common_settings.bzl", "string_list_flag")

string_list_flag(name, scope)
A string list-typed build setting that can be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## string_list_setting
load("@bazel_skylib//rules:common_settings.bzl", "string_list_setting")

string_list_setting(name, scope)
A string list-typed build setting which expects its value on the command line to be given in comma-separated format; for example, `--//my/setting=foo,bar` will be parsed as `['foo', 'bar']`. Contrast with `repeatable_string_flag` **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | ## string_setting
load("@bazel_skylib//rules:common_settings.bzl", "string_setting")

string_setting(name, make_variable, scope, values)
A string-typed build setting that cannot be set on the command line **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | make_variable | If set, the build setting's value will be available as a Make variable with this name in the attributes of rules that list this build setting in their 'toolchains' attribute. | String | optional | `""` | | scope | The scope indicates where a flag can propagate to | String | optional | `"target"` | | values | The list of allowed values for this setting. An error is raised if any other value is given. | List of strings | optional | `[]` | ## BuildSettingInfo
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")

BuildSettingInfo(value)
A singleton provider that contains the raw value of a build setting **FIELDS** | Name | Description | | :------------- | :------------- | | value | The value of the build setting in the current configuration. This value may come from the command line or an upstream transition, or else it will be the build setting's default. | bazel-skylib-1.9.1/docs/copy_directory_doc.md000077500000000000000000000051731517445036200212670ustar00rootroot00000000000000 A rule that copies a directory to another place. The rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). ## copy_directory
load("@bazel_skylib//rules:copy_directory.bzl", "copy_directory")

copy_directory(name, src, out, **kwargs)
Copies a directory to another location. This rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). If using this rule with source directories, it is recommended that you use the `--host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1` startup option so that changes to files within source directories are detected. See https://github.com/bazelbuild/bazel/commit/c64421bc35214f0414e4f4226cc953e8c55fa0d2 for more context. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | Name of the rule. | none | | src | The directory to make a copy of. Can be a source directory or TreeArtifact. | none | | out | Path of the output directory, relative to this package. | none | | kwargs | further keyword arguments, e.g. `visibility` | none | ## copy_directory_action
load("@bazel_skylib//rules:copy_directory.bzl", "copy_directory_action")

copy_directory_action(ctx, src, dst, is_windows)
Helper function that creates an action to copy a directory from src to dst. This helper is used by copy_directory. It is exposed as a public API so it can be used within other rule implementations. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | ctx | The rule context. | none | | src | The directory to make a copy of. Can be a source directory or TreeArtifact. | none | | dst | The directory to copy to. Must be a TreeArtifact. | none | | is_windows | If true, an cmd.exe action is created so there is no bash dependency. | `False` | bazel-skylib-1.9.1/docs/copy_file_doc.md000077500000000000000000000044531517445036200202020ustar00rootroot00000000000000 A rule that copies a file to another place. native.genrule() is sometimes used to copy files (often wishing to rename them). The 'copy_file' rule does this with a simpler interface than genrule. The rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). ## copy_file
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")

copy_file(name, src, out, is_executable, allow_symlink, **kwargs)
Copies a file to another location. `native.genrule()` is sometimes used to copy files (often wishing to rename them). The 'copy_file' rule does this with a simpler interface than genrule. This rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | Name of the rule. | none | | src | A Label. The file to make a copy of. (Can also be the label of a rule that generates a file.) | none | | out | Path of the output file, relative to this package. | none | | is_executable | A boolean. Whether to make the output file executable. When True, the rule's output can be executed using `bazel run` and can be in the srcs of binary and test rules that require executable sources. WARNING: If `allow_symlink` is True, `src` must also be executable. | `False` | | allow_symlink | A boolean. Whether to allow symlinking instead of copying. When False, the output is always a hard copy. When True, the output *can* be a symlink, but there is no guarantee that a symlink is created (i.e., at the time of writing, we don't create symlinks on Windows). Set this to True if you need fast copying and your tools can handle symlinks (which most UNIX tools can). | `False` | | kwargs | further keyword arguments, e.g. `visibility` | none | bazel-skylib-1.9.1/docs/dicts_doc.md000077500000000000000000000046531517445036200173410ustar00rootroot00000000000000 Skylib module containing functions that operate on dictionaries. ## dicts.add
load("@bazel_skylib//lib:dicts.bzl", "dicts")

dicts.add(*dictionaries, **kwargs)
Returns a new `dict` that has all the entries of the given dictionaries. If the same key is present in more than one of the input dictionaries, the last of them in the argument list overrides any earlier ones. This function is designed to take zero or one arguments as well as multiple dictionaries, so that it follows arithmetic identities and callers can avoid special cases for their inputs: the sum of zero dictionaries is the empty dictionary, and the sum of a single dictionary is a copy of itself. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | dictionaries | Zero or more dictionaries to be added. | none | | kwargs | Additional dictionary passed as keyword args. | none | **RETURNS** A new `dict` that has all the entries of the given dictionaries. ## dicts.omit
load("@bazel_skylib//lib:dicts.bzl", "dicts")

dicts.omit(dictionary, keys)
Returns a new `dict` that has all the entries of `dictionary` with keys not in `keys`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | dictionary | A `dict`. | none | | keys | A sequence. | none | **RETURNS** A new `dict` that has all the entries of `dictionary` with keys not in `keys`. ## dicts.pick
load("@bazel_skylib//lib:dicts.bzl", "dicts")

dicts.pick(dictionary, keys)
Returns a new `dict` that has all the entries of `dictionary` with keys in `keys`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | dictionary | A `dict`. | none | | keys | A sequence. | none | **RETURNS** A new `dict` that has all the entries of `dictionary` with keys in `keys`. bazel-skylib-1.9.1/docs/diff_test_doc.md000077500000000000000000000025541517445036200202000ustar00rootroot00000000000000 A test rule that compares two binary files. The rule uses a Bash command (diff) on Linux/macOS/non-Windows, and a cmd.exe command (fc.exe) on Windows (no Bash is required). ## diff_test
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")

diff_test(name, failure_message, file1, file2)
A test that compares two files. The test succeeds if the files' contents match. **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | failure_message | Additional message to log if the files' contents do not match. | String | optional | `""` | | file1 | Label of the file to compare to `file2`. | Label | required | | | file2 | Label of the file to compare to `file1`. | Label | required | | bazel-skylib-1.9.1/docs/directory_doc.md000077500000000000000000000014121517445036200202250ustar00rootroot00000000000000 Skylib module containing rules to create metadata about directories. ## directory
load("@bazel_skylib//rules/directory:directory.bzl", "directory")

directory(name, srcs)
**ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | srcs | - | List of labels | optional | `[]` | bazel-skylib-1.9.1/docs/directory_glob_doc.md000077500000000000000000000037371517445036200212440ustar00rootroot00000000000000 Rules to filter files from a directory. ## directory_glob
load("@bazel_skylib//rules/directory:glob.bzl", "directory_glob")

directory_glob(name, srcs, data, allow_empty, directory, exclude)
globs files from a directory by relative path. Usage: ``` directory_glob( name = "foo", directory = ":directory", srcs = ["foo/bar"], data = ["foo/**"], exclude = ["foo/**/*.h"] ) ``` **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | srcs | A list of globs to files within the directory to put in the files.

For example, `srcs = ["foo/**"]` would collect the file at `/foo` into the files. | List of strings | optional | `[]` | | data | A list of globs to files within the directory to put in the runfiles.

For example, `data = ["foo/**"]` would collect all files contained within `/foo` into the runfiles. | List of strings | optional | `[]` | | allow_empty | If true, allows globs to not match anything. | Boolean | optional | `False` | | directory | - | Label | required | | | exclude | A list of globs to files within the directory to exclude from the files and runfiles. | List of strings | optional | `[]` | bazel-skylib-1.9.1/docs/directory_providers_doc.md000077500000000000000000000045371517445036200223350ustar00rootroot00000000000000 Skylib module containing providers for directories. ## DirectoryInfo
load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo")

DirectoryInfo(entries, transitive_files, path, human_readable, get_path, get_file, get_subdirectory,
              glob)
Information about a directory **FIELDS** | Name | Description | | :------------- | :------------- | | entries | (Dict[str, Either[File, DirectoryInfo]]) The entries contained directly within. Ordered by filename | | transitive_files | (depset[File]) All files transitively contained within this directory. | | path | (string) Path to all files contained within this directory. | | human_readable | (string) A human readable identifier for a directory. Useful for providing error messages to a user. | | get_path | (Function(str) -> DirectoryInfo\|File) A function to return the entry corresponding to the joined path. | | get_file | (Function(str) -> File) A function to return the entry corresponding to the joined path. | | get_subdirectory | (Function(str) -> DirectoryInfo) A function to return the entry corresponding to the joined path. | | glob | (Function(include, exclude, allow_empty=False)) A function that works the same as native.glob. | ## create_directory_info
load("@bazel_skylib//rules/directory:providers.bzl", "create_directory_info")

create_directory_info(**kwargs)
**PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | kwargs |

-

| none | bazel-skylib-1.9.1/docs/directory_subdirectory_doc.md000077500000000000000000000020041517445036200230210ustar00rootroot00000000000000 Skylib module containing rules to create metadata about subdirectories. ## subdirectory
load("@bazel_skylib//rules/directory:subdirectory.bzl", "subdirectory")

subdirectory(name, parent, path)
**ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | parent | A label corresponding to the parent directory (or subdirectory). | Label | required | | | path | A path within the parent directory (eg. "path/to/subdir") | String | required | | bazel-skylib-1.9.1/docs/directory_utils_doc.md000077500000000000000000000111261517445036200214500ustar00rootroot00000000000000 Skylib module containing utility functions related to directories. ## directory_glob
directory_glob(directory, include, allow_empty)
native.glob, but for DirectoryInfo. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | directory | (DirectoryInfo) The directory to look relative from. | none | | include | (List[string]) A list of globs to match. | none | | allow_empty | (bool) Whether to allow a glob to not match any files. | `False` | **RETURNS** depset[File] A set of files that match. ## directory_glob_chunk
directory_glob_chunk(directory, chunk)
Given a directory and a chunk of a glob, returns possible candidates. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | directory | (DirectoryInfo) The directory to look relative from. | none | | chunk | (string) A chunk of a glob to look at. | none | **RETURNS** List[Either[DirectoryInfo, File]]] The candidate next entries for the chunk. ## directory_single_glob
directory_single_glob(directory, glob)
Calculates all files that are matched by a glob on a directory. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | directory | (DirectoryInfo) The directory to look relative from. | none | | glob | (string) A glob to match. | none | **RETURNS** List[File] A list of files that match. ## get_child
get_child(directory, name, require_dir, require_file)
Gets the direct child of a directory. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | directory | (DirectoryInfo) The directory to look within. | none | | name | (string) The name of the directory/file to look for. | none | | require_dir | (bool) If true, throws an error if the value is not a directory. | `False` | | require_file | (bool) If true, throws an error if the value is not a file. | `False` | **RETURNS** (File|DirectoryInfo) The content contained within. ## get_relative
get_relative(directory, path, require_dir, require_file)
Gets a subdirectory contained within a tree of another directory. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | directory | (DirectoryInfo) The directory to look within. | none | | path | (string) The path of the directory to look for within it. | none | | require_dir | (bool) If true, throws an error if the value is not a directory. | `False` | | require_file | (bool) If true, throws an error if the value is not a file. | `False` | **RETURNS** (File|DirectoryInfo) The directory contained within. ## transitive_entries
transitive_entries(directory)
Returns the files and directories contained within a directory transitively. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | directory | (DirectoryInfo) The directory to look at | none | **RETURNS** List[Either[DirectoryInfo, File]] The entries contained within. bazel-skylib-1.9.1/docs/expand_template_doc.md000077500000000000000000000032521517445036200213770ustar00rootroot00000000000000 A rule that performs template expansion. ## expand_template
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")

expand_template(name, out, substitutions, template)
Template expansion This performs a simple search over the template file for the keys in substitutions, and replaces them with the corresponding values. There is no special syntax for the keys. To avoid conflicts, you would need to explicitly add delimiters to the key strings, for example "{KEY}" or "@KEY@". **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | out | The destination of the expanded file. | Label; nonconfigurable | required | | | substitutions | A dictionary mapping strings to their substitutions. | Dictionary: String -> String | required | | | template | The template file to expand. | Label | required | | bazel-skylib-1.9.1/docs/maintainers_guide.md000066400000000000000000000103521517445036200210630ustar00rootroot00000000000000# Skylib Maintainer's Guide ## The Parts of Skylib * `bzl_library.bzl` - used by almost all rule sets, and thus requiring especial attention to maintaining backwards compatibility. Ideally, it ought to be moved out of Skylib and and into Bazel's bundled `@bazel_tools` repo (see https://github.com/bazelbuild/bazel-skylib/issues/127). * Test libraries - `rules/analysis_test.bzl`, `rules/build_test.bzl`, `lib/unittest.bzl`; these are under more active development than the rest of Skylib, because we want to provide rule authors with a good testing story. Ideally, these ought to be moved out of Skylib and evolved at a faster pace. * A kitchen sink of utility modules (everything else). Formerly, these features were piled on in a rather haphazard manner. For any new additions, we want to be more conservative: add a feature only if it is widely needed (or was already independently implemented in multiple rule sets), if the interface is unimpeachable, if level of abstraction is not shallow, and the implementation is efficient. ## PR Review Standards Because Skylib is so widely used, breaking backwards compatibility can cause widespread pain, and shouldn't be done lightly. Therefore: 1. In the first place, avoid adding insufficiently thought out, insufficiently tested features which will later need to be replaced in a backwards-incompatible manner. See the criteria in README.md. 2. Given a choice between breaking backwards compatibility and keeping it, try to keep backwards compatibility. For example, if adding a new argument to a function, add it to the end of the argument list, so that existing callers' positional arguments continue to work. 3. Keep Skylib out-of-the-box compatible with the current stable Bazel release (ideally - with two most recent stable releases). * For example, when adding a new function which calls the new `native.foobar()` method which was introduced in the latest Bazel pre-release or is gated behind an `--incompatible` flag, use an `if hasattr(native, "foobar")` check to keep the rest of your module (which doesn't need `native.foobar()`) working even when `native.foobar()` is not available. In addition, make sure that new code is documented and tested. If a PR changes any docstring in an existing module, the corresponding `stardoc_with_diff_test` in `docs` will fail. To fix the test, ask the PR author to run `bazel run //docs:update`. If a PR adds a new module, make sure that the PR also adds a corresponding `stardoc_with_diff_test` target in `docs/BUILD` and a corresponding `*doc.md` file under `docs` (generated by `bazel run //docs:update`). ## Making a New Release 1. Update CHANGELOG.md at the top. You may want to use the following template: -------------------------------------------------------------------------------- ``` # Release $VERSION **New Features** - Feature - Feature **Incompatible Changes** - Change - Change **Contributors** Name 1, Name 2, Name 3 (alphabetically from `git log`) ``` -------------------------------------------------------------------------------- 2. Bump `version` in version.bzl, MODULE.bazel, *and* gazelle/MODULE.bazel to the new version. TODO(#386): add a test to make sure all the versions are in sync. 3. Ensure that the commits for steps 1 and 2 have been merged. 4. Create a new tag in the format `1.2.3` (no leading `v`) and push it to GitHub. 5. Review a PR at [Bazel Central Registry](https://github.com/bazelbuild/bazel-central-registry) created by the publish.yaml workflow. 6. Download the the `bazel-skylib-$VERSION.tar.gz` and `bazel-skylib-gazelle-plugin-$VERSION.tar.gz` tarballs from the automatically created GitHub release and upload them to the mirror (you'll need Bazel developer gcloud credentials; assuming you are a Bazel developer, you can obtain them via `gcloud init`): ```bash gsutil cp bazel-skylib{,-gazelle-plugin}-$VERSION.tar.gz gs://bazel-mirror/github.com/bazelbuild/bazel-skylib/releases/download/$VERSION/ gsutil setmeta -h "Cache-Control: public, max-age=31536000" gs://bazel-mirror/github.com/bazelbuild/bazel-skylib/releases/download/$VERSION/bazel-skylib{,-gazelle-plugin}-$VERSION.tar.gz ``` bazel-skylib-1.9.1/docs/modules_doc.md000077500000000000000000000062261517445036200177010ustar00rootroot00000000000000 Skylib module containing utilities for Bazel modules and module extensions. ## modules.as_extension
load("@bazel_skylib//lib:modules.bzl", "modules")

modules.as_extension(macro, doc)
Wraps a WORKSPACE dependency macro into a module extension. Example: ```starlark def rules_foo_deps(optional_arg = True): some_repo_rule(name = "foobar") http_archive(name = "bazqux") rules_foo_deps_ext = modules.as_extension(rules_foo_deps) ``` **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | macro | A [WORKSPACE dependency macro](https://bazel.build/rules/deploying#dependencies), i.e., a function with no required parameters that instantiates one or more repository rules. | none | | doc | A description of the module extension that can be extracted by documentation generating tools. | `None` | **RETURNS** A module extension that generates the repositories instantiated by the given macro and also uses [`use_all_repos`](#use_all_repos) to indicate that all of those repositories should be imported via `use_repo`. The extension is marked as reproducible if supported by the current version of Bazel and thus doesn't result in a lockfile entry. ## modules.use_all_repos
load("@bazel_skylib//lib:modules.bzl", "modules")

modules.use_all_repos(module_ctx, reproducible)
Return from a module extension that should have all its repositories imported via `use_repo`. Example: ```starlark def _ext_impl(module_ctx): some_repo_rule(name = "foobar") http_archive(name = "bazqux") return modules.use_all_repos(module_ctx) ext = module_extension(_ext_impl) ``` **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | module_ctx | The [`module_ctx`](https://bazel.build/rules/lib/builtins/module_ctx) object passed to the module extension's implementation function. | none | | reproducible | The value of the `reproducible` parameter to pass to the [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html) object returned by this function. This is safe to set with Bazel versions that don't support this parameter and will be ignored in that case. | `False` | **RETURNS** An [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html) object that, when returned from a module extension implementation function, specifies that all repositories generated by this extension should be imported via `use_repo`. If the current version of Bazel doesn't support `extension_metadata`, returns `None` instead, which can safely be returned from a module extension implementation function in all versions of Bazel. bazel-skylib-1.9.1/docs/native_binary_doc.md000077500000000000000000000071321517445036200210600ustar00rootroot00000000000000 native_binary() and native_test() rule implementations. These rules let you wrap a pre-built binary or script in a conventional binary and test rule respectively. They fulfill the same goal as sh_binary and sh_test do, but they run the wrapped binary directly, instead of through Bash, so they don't depend on Bash and work with --shell_executable="". ## native_binary
load("@bazel_skylib//rules:native_binary.bzl", "native_binary")

native_binary(name, src, data, out, env)
Wraps a pre-built binary or script with a binary rule. You can "bazel run" this rule like any other binary rule, and use it as a tool in genrule.tools for example. You can also augment the binary with runfiles. **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | src | path of the pre-built executable | Label | required | | | data | data dependencies. See https://bazel.build/reference/be/common-definitions#typical.data | List of labels | optional | `[]` | | out | An output name for the copy of the binary. Defaults to name.exe. (We add .exe to the name by default because it's required on Windows and tolerated on other platforms.) | String | optional | `""` | | env | Environment variables to set when running the binary. | Dictionary: String -> String | optional | `{}` | ## native_test
load("@bazel_skylib//rules:native_binary.bzl", "native_test")

native_test(name, src, data, out, env)
Wraps a pre-built binary or script with a test rule. You can "bazel test" this rule like any other test rule. You can also augment the binary with runfiles. **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | src | path of the pre-built executable | Label | required | | | data | data dependencies. See https://bazel.build/reference/be/common-definitions#typical.data | List of labels | optional | `[]` | | out | An output name for the copy of the binary. Defaults to name.exe. (We add .exe to the name by default because it's required on Windows and tolerated on other platforms.) | String | optional | `""` | | env | Environment variables to set when running the binary. | Dictionary: String -> String | optional | `{}` | bazel-skylib-1.9.1/docs/new_sets_doc.md000077500000000000000000000204201517445036200200500ustar00rootroot00000000000000 Skylib module containing common hash-set algorithms. An empty set can be created using: `sets.make()`, or it can be created with some starting values if you pass it an sequence: `sets.make([1, 2, 3])`. This returns a struct containing all of the values as keys in a dictionary - this means that all passed in values must be hashable. The values in the set can be retrieved using `sets.to_list(my_set)`. An arbitrary object can be tested whether it is a set generated by `sets.make()` or not with the `types.is_set()` method in types.bzl. ## sets.contains
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.contains(a, e)
Checks for the existence of an element in a set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | a | A set, as returned by `sets.make()`. | none | | e | The element to look for. | none | **RETURNS** True if the element exists in the set, False if the element does not. ## sets.copy
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.copy(s)
Creates a new set from another set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | **RETURNS** A new set containing the same elements as `s`. ## sets.difference
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.difference(a, b)
Returns the elements in `a` that are not in `b`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | a | A set, as returned by `sets.make()`. | none | | b | A set, as returned by `sets.make()`. | none | **RETURNS** A set containing the elements that are in `a` but not in `b`. ## sets.disjoint
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.disjoint(a, b)
Returns whether two sets are disjoint. Two sets are disjoint if they have no elements in common. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | a | A set, as returned by `sets.make()`. | none | | b | A set, as returned by `sets.make()`. | none | **RETURNS** True if `a` and `b` are disjoint, False otherwise. ## sets.insert
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.insert(s, e)
Inserts an element into the set. Element must be hashable. This mutates the original set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | | e | The element to be inserted. | none | **RETURNS** The set `s` with `e` included. ## sets.intersection
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.intersection(a, b)
Returns the intersection of two sets. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | a | A set, as returned by `sets.make()`. | none | | b | A set, as returned by `sets.make()`. | none | **RETURNS** A set containing the elements that are in both `a` and `b`. ## sets.is_equal
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.is_equal(a, b)
Returns whether two sets are equal. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | a | A set, as returned by `sets.make()`. | none | | b | A set, as returned by `sets.make()`. | none | **RETURNS** True if `a` is equal to `b`, False otherwise. ## sets.is_subset
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.is_subset(a, b)
Returns whether `a` is a subset of `b`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | a | A set, as returned by `sets.make()`. | none | | b | A set, as returned by `sets.make()`. | none | **RETURNS** True if `a` is a subset of `b`, False otherwise. ## sets.length
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.length(s)
Returns the number of elements in a set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | **RETURNS** An integer representing the number of elements in the set. ## sets.make
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.make(elements)
Creates a new set. All elements must be hashable. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | elements | Optional sequence to construct the set out of. | `None` | **RETURNS** A set containing the passed in values. ## sets.remove
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.remove(s, e)
Removes an element from the set. Element must be hashable. This mutates the original set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | | e | The element to be removed. | none | **RETURNS** The set `s` with `e` removed. ## sets.repr
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.repr(s)
Returns a string value representing the set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | **RETURNS** A string representing the set. ## sets.str
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.str(s)
Returns a string value representing the set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | **RETURNS** A string representing the set. ## sets.to_list
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.to_list(s)
Creates a list from the values in the set. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A set, as returned by `sets.make()`. | none | **RETURNS** A list of values inserted into the set. ## sets.union
load("@bazel_skylib//lib:new_sets.bzl", "sets")

sets.union(*args)
Returns the union of several sets. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | args | An arbitrary number of sets. | none | **RETURNS** The set union of all sets in `*args`. bazel-skylib-1.9.1/docs/partial_doc.md000077500000000000000000000111211517445036200176530ustar00rootroot00000000000000 Starlark module for working with partial function objects. Partial function objects allow some parameters are bound before the call. Similar to https://docs.python.org/3/library/functools.html#functools.partial. ## partial.call
load("@bazel_skylib//lib:partial.bzl", "partial")

partial.call(partial, *args, **kwargs)
Calls a partial created using `make`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | partial | The partial to be called. | none | | args | Additional positional arguments to be appended to the ones given to make. | none | | kwargs | Additional keyword arguments to augment and override the ones given to make. | none | **RETURNS** Whatever the function in the partial returns. ## partial.is_instance
load("@bazel_skylib//lib:partial.bzl", "partial")

partial.is_instance(v)
Returns True if v is a partial created using `make`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value to check. | none | **RETURNS** True if v was created by `make`, False otherwise. ## partial.make
load("@bazel_skylib//lib:partial.bzl", "partial")

partial.make(func, *args, **kwargs)
Creates a partial that can be called using `call`. A partial can have args assigned to it at the make site, and can have args passed to it at the call sites. A partial 'function' can be defined with positional args and kwargs: # function with no args ``` def function1(): ... ``` # function with 2 args ``` def function2(arg1, arg2): ... ``` # function with 2 args and keyword args ``` def function3(arg1, arg2, x, y): ... ``` The positional args passed to the function are the args passed into make followed by any additional positional args given to call. The below example illustrates a function with two positional arguments where one is supplied by make and the other by call: # function demonstrating 1 arg at make site, and 1 arg at call site ``` def _foo(make_arg1, func_arg1): print(make_arg1 + " " + func_arg1 + "!") ``` For example: ``` hi_func = partial.make(_foo, "Hello") bye_func = partial.make(_foo, "Goodbye") partial.call(hi_func, "Jennifer") partial.call(hi_func, "Dave") partial.call(bye_func, "Jennifer") partial.call(bye_func, "Dave") ``` prints: ``` "Hello, Jennifer!" "Hello, Dave!" "Goodbye, Jennifer!" "Goodbye, Dave!" ``` The keyword args given to the function are the kwargs passed into make unioned with the keyword args given to call. In case of a conflict, the keyword args given to call take precedence. This allows you to set a default value for keyword arguments and override it at the call site. Example with a make site arg, a call site arg, a make site kwarg and a call site kwarg: ``` def _foo(make_arg1, call_arg1, make_location, call_location): print(make_arg1 + " is from " + make_location + " and " + call_arg1 + " is from " + call_location + "!") func = partial.make(_foo, "Ben", make_location="Hollywood") partial.call(func, "Jennifer", call_location="Denver") ``` Prints "Ben is from Hollywood and Jennifer is from Denver!". ``` partial.call(func, "Jennifer", make_location="LA", call_location="Denver") ``` Prints "Ben is from LA and Jennifer is from Denver!". Note that keyword args may not overlap with positional args, regardless of whether they are given during the make or call step. For instance, you can't do: ``` def foo(x): pass func = partial.make(foo, 1) partial.call(func, x=2) ``` **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | func | The function to be called. | none | | args | Positional arguments to be passed to function. | none | | kwargs | Keyword arguments to be passed to function. Note that these can be overridden at the call sites. | none | **RETURNS** A new `partial` that can be called using `call` bazel-skylib-1.9.1/docs/paths_doc.md000077500000000000000000000206101517445036200173410ustar00rootroot00000000000000 Skylib module containing file path manipulation functions. NOTE: The functions in this module currently only support paths with Unix-style path separators (forward slash, "/"); they do not handle Windows-style paths with backslash separators or drive letters. ## paths.basename
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.basename(p)
Returns the basename (i.e., the file portion) of a path. Note that if `p` ends with a slash, this function returns an empty string. This matches the behavior of Python's `os.path.basename`, but differs from the Unix `basename` command (which would return the path segment preceding the final slash). **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | p | The path whose basename should be returned. | none | **RETURNS** The basename of the path, which includes the extension. ## paths.dirname
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.dirname(p)
Returns the dirname of a path. The dirname is the portion of `p` up to but not including the file portion (i.e., the basename). Any slashes immediately preceding the basename are not included, unless omitting them would make the dirname empty. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | p | The path whose dirname should be returned. | none | **RETURNS** The dirname of the path. ## paths.is_absolute
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.is_absolute(path)
Returns `True` if `path` is an absolute path. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | path | A path (which is a string). | none | **RETURNS** `True` if `path` is an absolute path. ## paths.is_normalized
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.is_normalized(str, look_for_same_level_references)
Returns true if the passed path doesn't contain uplevel references "..". Also checks for single-dot references "." if look_for_same_level_references is `True.` **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | str | The path string to check. | none | | look_for_same_level_references | If True checks if path doesn't contain uplevel references ".." or single-dot references ".". | `True` | **RETURNS** True if the path is normalized, False otherwise. ## paths.join
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.join(path, *others)
Joins one or more path components intelligently. This function mimics the behavior of Python's `os.path.join` function on POSIX platform. It returns the concatenation of `path` and any members of `others`, inserting directory separators before each component except the first. The separator is not inserted if the path up until that point is either empty or already ends in a separator. If any component is an absolute path, all previous components are discarded. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | path | A path segment. | none | | others | Additional path segments. | none | **RETURNS** A string containing the joined paths. ## paths.normalize
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.normalize(path)
Normalizes a path, eliminating double slashes and other redundant segments. This function mimics the behavior of Python's `os.path.normpath` function on POSIX platforms; specifically: - If the entire path is empty, "." is returned. - All "." segments are removed, unless the path consists solely of a single "." segment. - Trailing slashes are removed, unless the path consists solely of slashes. - ".." segments are removed as long as there are corresponding segments earlier in the path to remove; otherwise, they are retained as leading ".." segments. - Single and double leading slashes are preserved, but three or more leading slashes are collapsed into a single leading slash. - Multiple adjacent internal slashes are collapsed into a single slash. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | path | A path. | none | **RETURNS** The normalized path. ## paths.relativize
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.relativize(path, start)
Returns the portion of `path` that is relative to `start`. Because we do not have access to the underlying file system, this implementation differs slightly from Python's `os.path.relpath` in that it will fail if `path` is not beneath `start` (rather than use parent segments to walk up to the common file system root). Relativizing paths that start with parent directory references only works if the path both start with the same initial parent references. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | path | The path to relativize. | none | | start | The ancestor path against which to relativize. | none | **RETURNS** The portion of `path` that is relative to `start`. ## paths.replace_extension
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.replace_extension(p, new_extension)
Replaces the extension of the file at the end of a path. If the path has no extension, the new extension is added to it. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | p | The path whose extension should be replaced. | none | | new_extension | The new extension for the file. The new extension should begin with a dot if you want the new filename to have one. | none | **RETURNS** The path with the extension replaced (or added, if it did not have one). ## paths.split_extension
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.split_extension(p)
Splits the path `p` into a tuple containing the root and extension. Leading periods on the basename are ignored, so `path.split_extension(".bashrc")` returns `(".bashrc", "")`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | p | The path whose root and extension should be split. | none | **RETURNS** A tuple `(root, ext)` such that the root is the path without the file extension, and `ext` is the file extension (which, if non-empty, contains the leading dot). The returned tuple always satisfies the relationship `root + ext == p`. ## paths.starts_with
load("@bazel_skylib//lib:paths.bzl", "paths")

paths.starts_with(path_a, path_b)
Returns True if and only if path_b is an ancestor of path_a. Does not handle OS dependent case-insensitivity. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | path_a |

-

| none | | path_b |

-

| none | bazel-skylib-1.9.1/docs/private/000077500000000000000000000000001517445036200165235ustar00rootroot00000000000000bazel-skylib-1.9.1/docs/private/BUILD000066400000000000000000000001711517445036200173040ustar00rootroot00000000000000# This package only contains source targets package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) bazel-skylib-1.9.1/docs/private/stardoc_with_diff_test.bzl000066400000000000000000000076121517445036200237630ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helpers for keeping stardoc documentation up-to-date. These are currently a private API in bazel-skylib. See discussion: https://github.com/bazelbuild/bazel-skylib/pull/321#issuecomment-1081166216 If you need a similar feature, you can consider using a similar rule available from a third-party: https://github.com/aspect-build/bazel-lib/blob/main/docs/docs.md """ load("@bazel_skylib//rules:diff_test.bzl", "diff_test") load("@bazel_skylib//rules:native_binary.bzl", "native_binary") load("@bazel_skylib//rules:write_file.bzl", "write_file") load("@io_bazel_stardoc//stardoc:stardoc.bzl", "stardoc") def stardoc_with_diff_test( name, bzl_library_target, out_label): """Creates a stardoc target coupled with a `diff_test` for a given `bzl_library`. This is helpful for minimizing boilerplate in repos with lots of stardoc targets. Args: name: the stardoc target name bzl_library_target: the label of the `bzl_library` target to generate documentation for out_label: the label of the output MD file """ out_file = out_label.replace("//", "").replace(":", "/") # Generate MD from .bzl stardoc( name = name, out = out_file.replace(".md", "-docgen.md"), input = bzl_library_target + ".bzl", deps = [bzl_library_target], ) # Ensure that the generated MD has been updated in the local source tree diff_test( name = out_file.replace("/", "_").replace(".md", "-difftest"), failure_message = "Please run \"bazel run //docs:update\"", # Source file file1 = out_label, # Output from stardoc rule above file2 = out_file.replace(".md", "-docgen.md"), tags = ["no_windows"], ) def update_docs( name = "update", docs_folder = "docs"): """Creates a `sh_binary` target which copies over generated doc files to the local source tree. This is to be used in tandem with `stardoc_with_diff_test()` to produce a convenient workflow for generating, testing, and updating all doc files as follows: ``` bash bazel build //{docs_folder}/... && bazel test //{docs_folder}/... && bazel run //{docs_folder}:update ``` eg. ``` bash bazel build //docs/... && bazel test //docs/... && bazel run //docs:update ``` The `update_docs()` invocation must come after/below any `stardoc_with_diff_test()` invocations in the BUILD file. Args: name: the name of the `sh_binary` target docs_folder: the name of the folder containing the doc files in the local source tree """ content = ["#!/usr/bin/env bash", "cd ${BUILD_WORKSPACE_DIRECTORY}"] data = [] for r in native.existing_rules().values(): if r["kind"] == "stardoc_markdown_renderer": doc_gen = r["out"] if doc_gen.startswith(":"): doc_gen = doc_gen[1:] doc_dest = doc_gen.replace("-docgen.md", ".md") data.append(doc_gen) content.append("cp -fv bazel-bin/{0}/{1} {2}".format(docs_folder, doc_gen, doc_dest)) update_script = name + ".sh" write_file( name = "gen_" + name, out = update_script, content = content, is_executable = True, ) native_binary( name = name, src = update_script, data = data, ) bazel-skylib-1.9.1/docs/run_binary_doc.md000077500000000000000000000050101517445036200203670ustar00rootroot00000000000000 run_binary() build rule implementation. Runs a binary as a build action. This rule does not require Bash (unlike native.genrule()). ## run_binary
load("@bazel_skylib//rules:run_binary.bzl", "run_binary")

run_binary(name, srcs, outs, args, env, tool)
Runs a binary as a build action. This rule does not require Bash (unlike `native.genrule`). **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | srcs | Additional inputs of the action.

These labels are available for `$(execpath)` and `$(location)` expansion in `args` and `env`. | List of labels | optional | `[]` | | outs | Output files generated by the action.

These labels are available for `$(execpath)` and `$(location)` expansion in `args` and `env`. | List of labels; nonconfigurable | required | | | args | Command line arguments of the binary.

Subject to [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables) expansion. | List of strings | optional | `[]` | | env | Environment variables of the action.

Subject to [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables) expansion. | Dictionary: String -> String | optional | `{}` | | tool | The tool to run in the action.

Must be the label of a *_binary rule, of a rule that generates an executable file, or of a file that can be executed as a subprocess (e.g. an .exe or .bat file on Windows or a binary with executable permission on Linux). This label is available for `$(execpath)` and `$(location)` expansion in `args` and `env`. | Label | required | | bazel-skylib-1.9.1/docs/select_file_doc.md000077500000000000000000000020721517445036200205020ustar00rootroot00000000000000 select_file() build rule implementation. Selects a single file from the outputs of a target by given relative path. ## select_file
load("@bazel_skylib//rules:select_file.bzl", "select_file")

select_file(name, srcs, subpath)
Selects a single file from the outputs of a target by given relative path **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | srcs | The target producing the file among other outputs | Label | required | | | subpath | Relative path to the file | String | required | | bazel-skylib-1.9.1/docs/selects_doc.md000077500000000000000000000074161517445036200176750ustar00rootroot00000000000000 Skylib module containing convenience interfaces for select(). ## selects.config_setting_group
load("@bazel_skylib//lib:selects.bzl", "selects")

selects.config_setting_group(name, match_any, match_all, visibility)
Matches if all or any of its member `config_setting`s match. Example: ```build config_setting(name = "one", define_values = {"foo": "true"}) config_setting(name = "two", define_values = {"bar": "false"}) config_setting(name = "three", define_values = {"baz": "more_false"}) config_setting_group( name = "one_two_three", match_all = [":one", ":two", ":three"] ) cc_binary( name = "myapp", srcs = ["myapp.cc"], deps = select({ ":one_two_three": [":special_deps"], "//conditions:default": [":default_deps"] }) ``` **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | The group's name. This is how `select()`s reference it. | none | | match_any | A list of `config_settings`. This group matches if *any* member in the list matches. If this is set, `match_all` must not be set. | `[]` | | match_all | A list of `config_settings`. This group matches if *every* member in the list matches. If this is set, `match_any` must be not set. | `[]` | | visibility | Visibility of the config_setting_group. | `None` | ## selects.with_or
load("@bazel_skylib//lib:selects.bzl", "selects")

selects.with_or(input_dict, no_match_error)
Drop-in replacement for `select()` that supports ORed keys. Example: ```build deps = selects.with_or({ "//configs:one": [":dep1"], ("//configs:two", "//configs:three"): [":dep2or3"], "//configs:four": [":dep4"], "//conditions:default": [":default"] }) ``` Key labels may appear at most once anywhere in the input. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | input_dict | The same dictionary `select()` takes, except keys may take either the usual form `"//foo:config1"` or `("//foo:config1", "//foo:config2", ...)` to signify `//foo:config1` OR `//foo:config2` OR `...`. | none | | no_match_error | Optional custom error to report if no condition matches. | `""` | **RETURNS** A native `select()` that expands `("//configs:two", "//configs:three"): [":dep2or3"]` to ```build "//configs:two": [":dep2or3"], "//configs:three": [":dep2or3"], ``` ## selects.with_or_dict
load("@bazel_skylib//lib:selects.bzl", "selects")

selects.with_or_dict(input_dict)
Variation of `with_or` that returns the dict of the `select()`. Unlike `select()`, the contents of the dict can be inspected by Starlark macros. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | input_dict | Same as `with_or`. | none | **RETURNS** A dictionary usable by a native `select()`. bazel-skylib-1.9.1/docs/shell_doc.md000077500000000000000000000031351517445036200173340ustar00rootroot00000000000000 Skylib module containing shell utility functions. ## shell.array_literal
load("@bazel_skylib//lib:shell.bzl", "shell")

shell.array_literal(iterable)
Creates a string from a sequence that can be used as a shell array. For example, `shell.array_literal(["a", "b", "c"])` would return the string `("a" "b" "c")`, which can be used in a shell script wherever an array literal is needed. Note that all elements in the array are quoted (using `shell.quote`) for safety, even if they do not need to be. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | iterable | A sequence of elements. Elements that are not strings will be converted to strings first, by calling `str()`. | none | **RETURNS** A string that represents the sequence as a shell array; that is, parentheses containing the quoted elements. ## shell.quote
load("@bazel_skylib//lib:shell.bzl", "shell")

shell.quote(s)
Quotes the given string for use in a shell command. This function quotes the given string (in case it contains spaces or other shell metacharacters.) **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | The string to quote. | none | **RETURNS** A quoted version of the string that can be passed to a shell command. bazel-skylib-1.9.1/docs/structs_doc.md000077500000000000000000000012271517445036200177340ustar00rootroot00000000000000 Skylib module containing functions that operate on structs. ## structs.to_dict
load("@bazel_skylib//lib:structs.bzl", "structs")

structs.to_dict(s)
Converts a `struct` to a `dict`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | s | A `struct`. | none | **RETURNS** A `dict` whose keys and values are the same as the fields in `s`. The transformation is only applied to the struct's fields and not to any nested values. bazel-skylib-1.9.1/docs/subpackages_doc.md000077500000000000000000000051651517445036200205220ustar00rootroot00000000000000 Skylib module containing common functions for working with native.subpackages() ## subpackages.all
load("@bazel_skylib//lib:subpackages.bzl", "subpackages")

subpackages.all(exclude, allow_empty, fully_qualified)
List all direct subpackages of the current package regardless of directory depth. The returned list contains all subpackages, but not subpackages of subpackages. Example: Assuming the following BUILD files exist: BUILD foo/BUILD foo/sub/BUILD bar/BUILD baz/deep/dir/BUILD If the current package is '//' all() will return ['//foo', '//bar', '//baz/deep/dir']. //foo/sub is not included because it is a direct subpackage of '//foo' not '//' NOTE: fail()s if native.subpackages() is not supported. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | exclude | see native.subpackages(exclude) | `[]` | | allow_empty | see native.subpackages(allow_empty) | `False` | | fully_qualified | It true return fully qualified Labels for subpackages, otherwise returns subpackage path relative to current package. | `True` | **RETURNS** A mutable sorted list containing all sub-packages of the current Bazel package. ## subpackages.exists
load("@bazel_skylib//lib:subpackages.bzl", "subpackages")

subpackages.exists(relative_path)
Checks to see if relative_path is a direct subpackage of the current package. Example: BUILD foo/BUILD foo/sub/BUILD If the current package is '//' (the top-level BUILD file): subpackages.exists("foo") == True subpackages.exists("foo/sub") == False subpackages.exists("bar") == False NOTE: fail()s if native.subpackages() is not supported in the current Bazel version. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | relative_path | a path to a subpackage to test, must not be an absolute Label. | none | **RETURNS** True if 'relative_path' is a subpackage of the current package. ## subpackages.supported
load("@bazel_skylib//lib:subpackages.bzl", "subpackages")

subpackages.supported()
bazel-skylib-1.9.1/docs/types_doc.md000077500000000000000000000113451517445036200173730ustar00rootroot00000000000000 Skylib module containing functions checking types. ## types.is_bool
load("@bazel_skylib//lib:types.bzl", "types")

types.is_bool(v)
Returns True if v is an instance of a bool. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a bool, False otherwise. ## types.is_depset
load("@bazel_skylib//lib:types.bzl", "types")

types.is_depset(v)
Returns True if v is an instance of a `depset`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a `depset`, False otherwise. ## types.is_dict
load("@bazel_skylib//lib:types.bzl", "types")

types.is_dict(v)
Returns True if v is an instance of a dict. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a dict, False otherwise. ## types.is_function
load("@bazel_skylib//lib:types.bzl", "types")

types.is_function(v)
Returns True if v is an instance of a function. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a function, False otherwise. ## types.is_int
load("@bazel_skylib//lib:types.bzl", "types")

types.is_int(v)
Returns True if v is an instance of a signed integer. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a signed integer, False otherwise. ## types.is_list
load("@bazel_skylib//lib:types.bzl", "types")

types.is_list(v)
Returns True if v is an instance of a list. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a list, False otherwise. ## types.is_none
load("@bazel_skylib//lib:types.bzl", "types")

types.is_none(v)
Returns True if v has the type of None. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is None, False otherwise. ## types.is_set
load("@bazel_skylib//lib:types.bzl", "types")

types.is_set(v)
Returns True if v is a set created by sets.make(). **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v was created by sets.make(), False otherwise. ## types.is_string
load("@bazel_skylib//lib:types.bzl", "types")

types.is_string(v)
Returns True if v is an instance of a string. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a string, False otherwise. ## types.is_tuple
load("@bazel_skylib//lib:types.bzl", "types")

types.is_tuple(v)
Returns True if v is an instance of a tuple. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | v | The value whose type should be checked. | none | **RETURNS** True if v is an instance of a tuple, False otherwise. bazel-skylib-1.9.1/docs/unittest_doc.md000077500000000000000000000553131517445036200201110ustar00rootroot00000000000000 Unit testing support. Unlike most Skylib files, this exports four modules: * `unittest` contains functions to declare and define unit tests for ordinary Starlark functions; * `analysistest` contains functions to declare and define tests for analysis phase behavior of a rule, such as a given target's providers or registered actions; * `loadingtest` contains functions to declare and define tests for loading phase behavior, such as macros and `native.*`; * `asserts` contains the assertions used within tests. See https://bazel.build/extending/concepts for background about macros, rules, and the different phases of a build. ## unittest_toolchain
load("@bazel_skylib//lib:unittest.bzl", "unittest_toolchain")

unittest_toolchain(name, escape_chars_with, escape_other_chars_with, failure_templ, file_ext,
                   join_on, success_templ)
**ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | escape_chars_with | Dictionary of characters that need escaping in test failure message to prefix appended to escape those characters. For example, `{"%": "%", ">": "^"}` would replace `%` with `%%` and `>` with `^>` in the failure message before that is included in `success_templ`. | Dictionary: String -> String | optional | `{}` | | escape_other_chars_with | String to prefix every character in test failure message which is not a key in `escape_chars_with` before including that in `success_templ`. For example, `""` would prefix every character in the failure message (except those in the keys of `escape_chars_with`) with `\`. | String | optional | `""` | | failure_templ | Test script template with a single `%s`. That placeholder is replaced with the lines in the failure message joined with the string specified in `join_with`. The resulting script should print the failure message and exit with non-zero status. | String | required | | | file_ext | File extension for test script, including leading dot. | String | required | | | join_on | String used to join the lines in the failure message before including the resulting string in the script specified in `failure_templ`. | String | required | | | success_templ | Test script generated when the test passes. Should exit with status 0. | String | required | | ## analysistest.begin
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.begin(ctx)
Begins an analysis test. This should be the first function called in an analysis test implementation function. It initializes a "test environment" that is used to collect assertion failures so that they can be reported and logged at the end of the test. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | ctx | The Starlark context. Pass the implementation function's `ctx` argument in verbatim. | none | **RETURNS** A test environment struct that must be passed to assertions and finally to `analysistest.end`. Do not rely on internal details about the fields in this struct as it may change. ## analysistest.end
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.end(env)
Ends an analysis test and logs the results. This must be called and returned at the end of an analysis test implementation function so that the results are reported. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `analysistest.begin`. | none | **RETURNS** A list of providers needed to automatically register the analysis test result. ## analysistest.fail
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.fail(env, msg)
Unconditionally causes the current test to fail. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | msg | The message to log describing the failure. | none | ## analysistest.make
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.make(impl, expect_failure, attrs, fragments, config_settings,
                  extra_target_under_test_aspects, doc)
Creates an analysis test rule from its implementation function. An analysis test verifies the behavior of a "real" rule target by examining and asserting on the providers given by the real target. Each analysis test is defined in an implementation function that must then be associated with a rule so that a target can be built. This function handles the boilerplate to create and return a test rule and captures the implementation function's name so that it can be printed in test feedback. An example of an analysis test: ``` def _your_test(ctx): env = analysistest.begin(ctx) # Assert statements go here return analysistest.end(env) your_test = analysistest.make(_your_test) ``` Recall that names of test rules must end in `_test`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | impl | The implementation function of the unit test. | none | | expect_failure | If true, the analysis test will expect the target_under_test to fail. Assertions can be made on the underlying failure using asserts.expect_failure | `False` | | attrs | An optional dictionary to supplement the attrs passed to the unit test's `rule()` constructor. | `{}` | | fragments | An optional list of fragment names that can be used to give rules access to language-specific parts of configuration. | `[]` | | config_settings | A dictionary of configuration settings to change for the target under test and its dependencies. This may be used to essentially change 'build flags' for the target under test, and may thus be utilized to test multiple targets with different flags in a single build | `{}` | | extra_target_under_test_aspects | An optional list of aspects to apply to the target_under_test in addition to those set up by default for the test harness itself. | `[]` | | doc | A description of the rule that can be extracted by documentation generating tools. | `""` | **RETURNS** A rule definition that should be stored in a global whose name ends in `_test`. ## analysistest.target_actions
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.target_actions(env)
Returns a list of actions registered by the target under test. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `analysistest.begin`. | none | **RETURNS** A list of actions registered by the target under test ## analysistest.target_bin_dir_path
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.target_bin_dir_path(env)
Returns ctx.bin_dir.path for the target under test. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `analysistest.begin`. | none | **RETURNS** Output bin dir path string. ## analysistest.target_under_test
load("@bazel_skylib//lib:unittest.bzl", "analysistest")

analysistest.target_under_test(env)
Returns the target under test. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `analysistest.begin`. | none | **RETURNS** The target under test. ## asserts.equals
load("@bazel_skylib//lib:unittest.bzl", "asserts")

asserts.equals(env, expected, actual, msg)
Asserts that the given `expected` and `actual` values are equal. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | expected | The expected value of some computation. | none | | actual | The actual value returned by some computation. | none | | msg | An optional message that will be printed that describes the failure. If omitted, a default will be used. | `None` | ## asserts.expect_failure
load("@bazel_skylib//lib:unittest.bzl", "asserts")

asserts.expect_failure(env, expected_failure_msg)
Asserts that the target under test has failed with a given error message. This requires that the analysis test is created with `analysistest.make()` and `expect_failures = True` is specified. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `analysistest.begin`. | none | | expected_failure_msg | The error message to expect as a result of analysis failures. | `""` | ## asserts.false
load("@bazel_skylib//lib:unittest.bzl", "asserts")

asserts.false(env, condition, msg)
Asserts that the given `condition` is false. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | condition | A value that will be evaluated in a Boolean context. | none | | msg | An optional message that will be printed that describes the failure. If omitted, a default will be used. | `"Expected condition to be false, but was true."` | ## asserts.new_set_equals
load("@bazel_skylib//lib:unittest.bzl", "asserts")

asserts.new_set_equals(env, expected, actual, msg)
Asserts that the given `expected` and `actual` sets are equal. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | expected | The expected set resulting from some computation. | none | | actual | The actual set returned by some computation. | none | | msg | An optional message that will be printed that describes the failure. If omitted, a default will be used. | `None` | ## asserts.set_equals
load("@bazel_skylib//lib:unittest.bzl", "asserts")

asserts.set_equals(env, expected, actual, msg)
Asserts that the given `expected` and `actual` sets are equal. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | expected | The expected set resulting from some computation. | none | | actual | The actual set returned by some computation. | none | | msg | An optional message that will be printed that describes the failure. If omitted, a default will be used. | `None` | ## asserts.true
load("@bazel_skylib//lib:unittest.bzl", "asserts")

asserts.true(env, condition, msg)
Asserts that the given `condition` is true. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | condition | A value that will be evaluated in a Boolean context. | none | | msg | An optional message that will be printed that describes the failure. If omitted, a default will be used. | `"Expected condition to be true, but was false."` | ## loadingtest.equals
load("@bazel_skylib//lib:unittest.bzl", "loadingtest")

loadingtest.equals(env, test_case, expected, actual)
Creates a test case for asserting state at LOADING phase. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | Loading test env created from loadingtest.make | none | | test_case | Name of the test case | none | | expected | Expected value to test | none | | actual | Actual value received. | none | **RETURNS** None, creates test case ## loadingtest.make
load("@bazel_skylib//lib:unittest.bzl", "loadingtest")

loadingtest.make(name)
Creates a loading phase test environment and test_suite. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | name of the suite of tests to create | none | **RETURNS** loading phase environment passed to other loadingtest functions ## register_unittest_toolchains
load("@bazel_skylib//lib:unittest.bzl", "register_unittest_toolchains")

register_unittest_toolchains()
Registers the toolchains for unittest users. ## unittest.begin
load("@bazel_skylib//lib:unittest.bzl", "unittest")

unittest.begin(ctx)
Begins a unit test. This should be the first function called in a unit test implementation function. It initializes a "test environment" that is used to collect assertion failures so that they can be reported and logged at the end of the test. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | ctx | The Starlark context. Pass the implementation function's `ctx` argument in verbatim. | none | **RETURNS** A test environment struct that must be passed to assertions and finally to `unittest.end`. Do not rely on internal details about the fields in this struct as it may change. ## unittest.end
load("@bazel_skylib//lib:unittest.bzl", "unittest")

unittest.end(env)
Ends a unit test and logs the results. This must be called and returned at the end of a unit test implementation function so that the results are reported. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | **RETURNS** A list of providers needed to automatically register the test result. ## unittest.fail
load("@bazel_skylib//lib:unittest.bzl", "unittest")

unittest.fail(env, msg)
Unconditionally causes the current test to fail. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | env | The test environment returned by `unittest.begin`. | none | | msg | The message to log describing the failure. | none | ## unittest.make
load("@bazel_skylib//lib:unittest.bzl", "unittest")

unittest.make(impl, attrs, doc, toolchains)
Creates a unit test rule from its implementation function. Each unit test is defined in an implementation function that must then be associated with a rule so that a target can be built. This function handles the boilerplate to create and return a test rule and captures the implementation function's name so that it can be printed in test feedback. The optional `attrs` argument can be used to define dependencies for this test, in order to form unit tests of rules. The optional `toolchains` argument can be used to define toolchain dependencies for this test. An example of a unit test: ``` def _your_test(ctx): env = unittest.begin(ctx) # Assert statements go here return unittest.end(env) your_test = unittest.make(_your_test) ``` Recall that names of test rules must end in `_test`. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | impl | The implementation function of the unit test. | none | | attrs | An optional dictionary to supplement the attrs passed to the unit test's `rule()` constructor. | `{}` | | doc | A description of the rule that can be extracted by documentation generating tools. | `""` | | toolchains | An optional list to supplement the toolchains passed to the unit test's `rule()` constructor. | `[]` | **RETURNS** A rule definition that should be stored in a global whose name ends in `_test`. ## unittest.suite
load("@bazel_skylib//lib:unittest.bzl", "unittest")

unittest.suite(name, *test_rules)
Defines a `test_suite` target that contains multiple tests. After defining your test rules in a `.bzl` file, you need to create targets from those rules so that `blaze test` can execute them. Doing this manually in a BUILD file would consist of listing each test in your `load` statement and then creating each target one by one. To reduce duplication, we recommend writing a macro in your `.bzl` file to instantiate all targets, and calling that macro from your BUILD file so you only have to load one symbol. You can use this function to create the targets and wrap them in a single test_suite target. If a test rule requires no arguments, you can simply list it as an argument. If you wish to supply attributes explicitly, you can do so using `partial.make()`. For instance, in your `.bzl` file, you could write: ``` def your_test_suite(): unittest.suite( "your_test_suite", your_test, your_other_test, partial.make(yet_another_test, timeout = "short"), ) ``` Then, in your `BUILD` file, simply load the macro and invoke it to have all of the targets created: ``` load("//path/to/your/package:tests.bzl", "your_test_suite") your_test_suite() ``` If you pass _N_ unit test rules to `unittest.suite`, _N_ + 1 targets will be created: a `test_suite` target named `${name}` (where `${name}` is the name argument passed in here) and targets named `${name}_test_${i}`, where `${i}` is the index of the test in the `test_rules` list, which is used to uniquely name each target. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | The name of the `test_suite` target, and the prefix of all the test target names. | none | | test_rules | A list of test rules defines by `unittest.test`. | none | bazel-skylib-1.9.1/docs/versions_doc.md000077500000000000000000000063201517445036200200740ustar00rootroot00000000000000 Skylib module containing functions for checking Bazel versions. ## versions.check
load("@bazel_skylib//lib:versions.bzl", "versions")

versions.check(minimum_bazel_version, maximum_bazel_version, bazel_version)
Check that the version of Bazel is valid within the specified range. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | minimum_bazel_version | minimum version of Bazel expected | none | | maximum_bazel_version | maximum version of Bazel expected | `None` | | bazel_version | the version of Bazel to check. Used for testing, defaults to native.bazel_version | `None` | ## versions.get
load("@bazel_skylib//lib:versions.bzl", "versions")

versions.get()
Returns the current Bazel version ## versions.is_at_least
load("@bazel_skylib//lib:versions.bzl", "versions")

versions.is_at_least(threshold, version)
Check that a version is higher or equals to a threshold. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | threshold | the minimum version string | none | | version | the version string to be compared to the threshold | none | **RETURNS** True if version >= threshold. ## versions.is_at_most
load("@bazel_skylib//lib:versions.bzl", "versions")

versions.is_at_most(threshold, version)
Check that a version is lower or equals to a threshold. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | threshold | the maximum version string | none | | version | the version string to be compared to the threshold | none | **RETURNS** True if version <= threshold. ## versions.parse
load("@bazel_skylib//lib:versions.bzl", "versions")

versions.parse(bazel_version)
Parses a version string into a 3-tuple of ints int tuples can be compared directly using binary operators (<, >). For a development build of Bazel, this returns an unspecified version tuple that compares higher than any released version. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | bazel_version | the Bazel version string | none | **RETURNS** An int 3-tuple of a (major, minor, patch) version. bazel-skylib-1.9.1/docs/write_file_doc.md000077500000000000000000000035241517445036200203600ustar00rootroot00000000000000 A rule that writes a UTF-8 encoded text file from user-specified contents. native.genrule() is sometimes used to create a text file. The 'write_file' and macro does this with a simpler interface than genrule. The rules generated by the macro do not use Bash or any other shell to write the file. Instead they use Starlark's built-in file writing action (ctx.actions.write). ## write_file
load("@bazel_skylib//rules:write_file.bzl", "write_file")

write_file(name, out, content, is_executable, newline, **kwargs)
Creates a UTF-8 encoded text file. **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | Name of the rule. | none | | out | Path of the output file, relative to this package. | none | | content | A list of strings. Lines of text, the contents of the file. Newlines are added automatically after every line except the last one. | `[]` | | is_executable | A boolean. Whether to make the output file executable. When True, the rule's output can be executed using `bazel run` and can be in the srcs of binary and test rules that require executable sources. | `False` | | newline | one of ["auto", "unix", "windows"]: line endings to use. "auto" for platform-determined, "unix" for LF, and "windows" for CRLF. | `"auto"` | | kwargs | further keyword arguments, e.g. `visibility` | none | bazel-skylib-1.9.1/gazelle/000077500000000000000000000000001517445036200155445ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/BUILD000066400000000000000000000021711517445036200163270ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@rules_license//rules:license.bzl", "license") package(default_applicable_licenses = ["//:license"]) license( name = "license", package_name = "bazelbuild/bazel_skylib_gazelle_module", license_kinds = ["@rules_license//licenses/spdx:Apache-2.0"], ) licenses(["notice"]) exports_files(["WORKSPACE.bzlmod"]) bzl_library( name = "setup", srcs = ["setup.bzl"], visibility = ["//visibility:public"], deps = [ "@bazel_gazelle//:deps", "@io_bazel_rules_go//go:deps", ], ) bzl_library( name = "workspace", srcs = ["workspace.bzl"], visibility = ["//visibility:public"], deps = [ "@bazel_skylib//:workspace", "@bazel_tools//tools/build_defs/repo:http.bzl", "@bazel_tools//tools/build_defs/repo:utils.bzl", ], ) # TODO(arostovtsev): exclude everything below from distro tarball filegroup( name = "distribution", srcs = [ "BUILD", "MODULE.bazel", "WORKSPACE.bzlmod", "setup.bzl", "workspace.bzl", ], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/MODULE.bazel000066400000000000000000000016171517445036200175550ustar00rootroot00000000000000module( name = "bazel_skylib_gazelle_plugin", # Keep in sync with @bazel_skylib//:MODULE.bazel and @bazel_skylib//:version.bzl version = "1.9.1", compatibility_level = 1, ) # Keep in sync with @bazel_skylib//:MODULE.bazel and @bazel_skylib//:version.bzl bazel_dep(name = "bazel_skylib", version = "1.9.1") bazel_dep(name = "rules_license", version = "0.0.7") bazel_dep(name = "gazelle", version = "0.41.0", repo_name = "bazel_gazelle") bazel_dep(name = "rules_go", version = "0.59.0", repo_name = "io_bazel_rules_go") # `rules_go` will register a toolchain for us if the user doesn't do so go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps") go_deps.module( path = "github.com/bazelbuild/buildtools", sum = "h1:fmdo+fvvWlhldUcqkhAMpKndSxMN3vH5l7yow5cEaiQ=", version = "v0.0.0-20220531122519-a43aed7014c8", ) use_repo(go_deps, "com_github_bazelbuild_buildtools") bazel-skylib-1.9.1/gazelle/WORKSPACE000066400000000000000000000015121517445036200170240ustar00rootroot00000000000000workspace(name = "bazel_skylib_gazelle_plugin") local_repository( name = "bazel_skylib", path = "..", ) load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() load(":workspace.bzl", "bazel_skylib_gazelle_plugin_workspace") bazel_skylib_gazelle_plugin_workspace() load(":setup.bzl", "bazel_skylib_gazelle_plugin_setup") bazel_skylib_gazelle_plugin_setup() # Provide a repository hint for Gazelle to inform it that the go package # github.com/bazelbuild/rules_go is available from io_bazel_rules_go and it # doesn't need to duplicatively fetch it. # gazelle:repository go_repository name=io_bazel_rules_go importpath=github.com/bazelbuild/rules_go # Another Gazelle repository hint. # gazelle:repository go_repository name=bazel_gazelle importpath=github.com/bazelbuild/bazel-gazelle/testtools bazel-skylib-1.9.1/gazelle/WORKSPACE.bzlmod000066400000000000000000000007461517445036200203220ustar00rootroot00000000000000workspace(name = "bazel_skylib_gazelle_plugin") # Provide a repository hint for Gazelle to inform it that the go package # github.com/bazelbuild/rules_go is available from io_bazel_rules_go and it # doesn't need to duplicatively fetch it. # gazelle:repository go_repository name=io_bazel_rules_go importpath=github.com/bazelbuild/rules_go # Another Gazelle repository hint. # gazelle:repository go_repository name=bazel_gazelle importpath=github.com/bazelbuild/bazel-gazelle/testtools bazel-skylib-1.9.1/gazelle/bzl/000077500000000000000000000000001517445036200163335ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/BUILD000066400000000000000000000041061517445036200171160ustar00rootroot00000000000000load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary") load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(default_applicable_licenses = ["//:license"]) # gazelle:exclude testdata go_library( name = "bzl", srcs = ["gazelle.go"], importpath = "github.com/bazelbuild/bazel-skylib/gazelle", visibility = ["//visibility:public"], deps = [ "@bazel_gazelle//config:go_default_library", "@bazel_gazelle//label:go_default_library", "@bazel_gazelle//language:go_default_library", "@bazel_gazelle//pathtools:go_default_library", "@bazel_gazelle//repo:go_default_library", "@bazel_gazelle//resolve:go_default_library", "@bazel_gazelle//rule:go_default_library", "@com_github_bazelbuild_buildtools//build:go_default_library", ], ) go_test( name = "bzl_test", srcs = ["gazelle_test.go"], data = [ ":gazelle-skylib", ] + glob( [ "testdata/**", ], allow_empty = True, ), embed = [":bzl"], deps = [ "@bazel_gazelle//testtools:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], ) # This gazelle binary is used exclusively for testing the gazelle language # extension and thus only has the skylib language installed. gazelle_binary( name = "gazelle-skylib", languages = [":bzl"], visibility = [ # Also make the binary available in the root of the repo for use, but # not externally. "//:__pkg__", ], ) gazelle( name = "gazelle", gazelle = ":gazelle-skylib", ) # TODO(arostovtsev): exclude everything below from distro tarball # The files needed for distribution # A fake testdata directory is created so that # the build file has nothing missing, but we # do not bloat the distribution tarball filegroup( name = "distribution", srcs = glob(["*.go"]) + [ "BUILD", ":fake-testdata", ], visibility = ["//visibility:public"], ) genrule( name = "fake-testdata", outs = ["testdata"], cmd = "touch $@", ) bazel-skylib-1.9.1/gazelle/bzl/README.md000066400000000000000000000010471517445036200176140ustar00rootroot00000000000000# Gazelle Gazelle is a `BUILD` file generator for Bazel. This directory contains a language extension for the Gazelle generator that allows it to automatically parse valid `bzl_library` targets for all `.bzl` files in a repo in which it runs. It will additionally include a `deps` entry tracking every `.bzl` that is `load`ed into the primary file. This can be used, for example, to generate [`stardoc`](https://github.com/bazelbuild/stardoc) documentation for your `.bzl` files, both simplify the task of and improve the quality of documentation. bazel-skylib-1.9.1/gazelle/bzl/gazelle.go000066400000000000000000000253621517445036200203150ustar00rootroot00000000000000/* Copyright 2020 The Bazel Authors. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Package bzl generates a `bzl_library` target for every `.bzl` file in // each package. // // The `bzl_library` rule is provided by // https://github.com/bazelbuild/bazel-skylib. // // This extension is experimental and subject to change. It is not included // in the default Gazelle binary. package bzl import ( "flag" "fmt" "log" "os" "path/filepath" "sort" "strings" "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/label" "github.com/bazelbuild/bazel-gazelle/language" "github.com/bazelbuild/bazel-gazelle/pathtools" "github.com/bazelbuild/bazel-gazelle/repo" "github.com/bazelbuild/bazel-gazelle/resolve" "github.com/bazelbuild/bazel-gazelle/rule" "github.com/bazelbuild/buildtools/build" ) const languageName = "starlark" const fileType = ".bzl" var ignoreSuffix = suffixes{ "_tests.bzl", "_test.bzl", } type suffixes []string func (s suffixes) Matches(test string) bool { for _, v := range s { if strings.HasSuffix(test, v) { return true } } return false } type bzlLibraryLang struct{} // NewLanguage is called by Gazelle to install this language extension in a binary. func NewLanguage() language.Language { return &bzlLibraryLang{} } // Name returns the name of the language. This should be a prefix of the // kinds of rules generated by the language, e.g., "go" for the Go extension // since it generates "go_library" rules. func (*bzlLibraryLang) Name() string { return languageName } // The following methods are implemented to satisfy the // https://pkg.go.dev/github.com/bazelbuild/bazel-gazelle/resolve?tab=doc#Resolver // interface, but are otherwise unused. func (*bzlLibraryLang) RegisterFlags(fs *flag.FlagSet, cmd string, c *config.Config) {} func (*bzlLibraryLang) CheckFlags(fs *flag.FlagSet, c *config.Config) error { return nil } func (*bzlLibraryLang) KnownDirectives() []string { return nil } func (*bzlLibraryLang) Configure(c *config.Config, rel string, f *rule.File) {} // Kinds returns a map of maps rule names (kinds) and information on how to // match and merge attributes that may be found in rules of those kinds. All // kinds of rules generated for this language may be found here. func (*bzlLibraryLang) Kinds() map[string]rule.KindInfo { return kinds } // Loads returns .bzl files and symbols they define. Every rule generated by // GenerateRules, now or in the past, should be loadable from one of these // files. func (*bzlLibraryLang) Loads() []rule.LoadInfo { return []rule.LoadInfo{{ Name: "@bazel_skylib//:bzl_library.bzl", Symbols: []string{"bzl_library"}, }} } // Fix repairs deprecated usage of language-specific rules in f. This is // called before the file is indexed. Unless c.ShouldFix is true, fixes // that delete or rename rules should not be performed. func (*bzlLibraryLang) Fix(c *config.Config, f *rule.File) {} // Imports returns a list of ImportSpecs that can be used to import the rule // r. This is used to populate RuleIndex. // // If nil is returned, the rule will not be indexed. If any non-nil slice is // returned, including an empty slice, the rule will be indexed. func (b *bzlLibraryLang) Imports(c *config.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec { srcs := r.AttrStrings("srcs") imports := make([]resolve.ImportSpec, 0, len(srcs)) for _, src := range srcs { spec := resolve.ImportSpec{ // Lang is the language in which the import string appears (this should // match Resolver.Name). Lang: languageName, // Imp is an import string for the library. Imp: fmt.Sprintf("//%s:%s", f.Pkg, src), } imports = append(imports, spec) } return imports } // Embeds returns a list of labels of rules that the given rule embeds. If // a rule is embedded by another importable rule of the same language, only // the embedding rule will be indexed. The embedding rule will inherit // the imports of the embedded rule. // Since SkyLark doesn't support embedding this should always return nil. func (*bzlLibraryLang) Embeds(r *rule.Rule, from label.Label) []label.Label { return nil } // Resolve translates imported libraries for a given rule into Bazel // dependencies. Information about imported libraries is returned for each // rule generated by language.GenerateRules in // language.GenerateResult.Imports. Resolve generates a "deps" attribute (or // the appropriate language-specific equivalent) for each import according to // language-specific rules and heuristics. func (*bzlLibraryLang) Resolve(c *config.Config, ix *resolve.RuleIndex, rc *repo.RemoteCache, r *rule.Rule, importsRaw interface{}, from label.Label) { imports := importsRaw.([]string) r.DelAttr("deps") if len(imports) == 0 { return } deps := make([]string, 0, len(imports)) for _, imp := range imports { impLabel, err := label.Parse(imp) if err != nil { log.Printf("%s: import of %q is invalid: %v", from.String(), imp, err) continue } // the index only contains absolute labels, not relative impLabel = impLabel.Abs(from.Repo, from.Pkg) if impLabel.Repo == "bazel_tools" { // The @bazel_tools repo is tricky because it is a part of the "shipped // with bazel" core library for interacting with the outside world. // This means that it can not depend on skylib. Fortunately there is a // fairly simple workaround for this, which is that you can add those // bzl files as `deps` entries. deps = append(deps, imp) continue } if impLabel.Repo != "" || !c.IndexLibraries { // This is a dependency that is external to the current repo, or indexing // is disabled so take a guess at what the target name should be. deps = append(deps, strings.TrimSuffix(imp, fileType)) continue } res := resolve.ImportSpec{ Lang: languageName, Imp: impLabel.String(), } matches := ix.FindRulesByImportWithConfig(c, res, languageName) if len(matches) == 0 { log.Printf("%s: %q (%s) was not found in dependency index. Skipping. This may result in an incomplete deps section and require manual BUILD file intervention.\n", from.String(), imp, impLabel.String()) } for _, m := range matches { depLabel := m.Label depLabel = depLabel.Rel(from.Repo, from.Pkg) deps = append(deps, depLabel.String()) } } sort.Strings(deps) if len(deps) > 0 { r.SetAttr("deps", deps) } } var kinds = map[string]rule.KindInfo{ "bzl_library": { NonEmptyAttrs: map[string]bool{"srcs": true, "deps": true}, MergeableAttrs: map[string]bool{"srcs": true}, }, } // GenerateRules extracts build metadata from source files in a directory. // GenerateRules is called in each directory where an update is requested // in depth-first post-order. // // args contains the arguments for GenerateRules. This is passed as a // struct to avoid breaking implementations in the future when new // fields are added. // // A GenerateResult struct is returned. Optional fields may be added to this // type in the future. // // Any non-fatal errors this function encounters should be logged using // log.Print. func (*bzlLibraryLang) GenerateRules(args language.GenerateArgs) language.GenerateResult { var rules []*rule.Rule var imports []interface{} for _, f := range append(args.RegularFiles, args.GenFiles...) { if !isBzlSourceFile(f) { continue } name := strings.TrimSuffix(f, fileType) r := rule.NewRule("bzl_library", name) r.SetAttr("srcs", []string{f}) shouldSetVisibility := args.File == nil || !args.File.HasDefaultVisibility() if shouldSetVisibility { vis := checkInternalVisibility(args.Rel, "//visibility:public") r.SetAttr("visibility", []string{vis}) } fullPath := filepath.Join(args.Dir, f) loads, err := getBzlFileLoads(fullPath) if err != nil { log.Printf("%s: contains syntax errors: %v", fullPath, err) // Don't `continue` since it is reasonable to create a target even // without deps. } rules = append(rules, r) imports = append(imports, loads) } return language.GenerateResult{ Gen: rules, Imports: imports, Empty: generateEmpty(args), } } func getBzlFileLoads(path string) ([]string, error) { f, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("os.ReadFile(%q) error: %v", path, err) } ast, err := build.ParseBuild(path, f) if err != nil { return nil, fmt.Errorf("build.Parse(%q) error: %v", f, err) } var loads []string build.WalkOnce(ast, func(expr *build.Expr) { n := *expr if l, ok := n.(*build.LoadStmt); ok { loads = append(loads, l.Module.Value) } }) sort.Strings(loads) return loads, nil } func isBzlSourceFile(f string) bool { return strings.HasSuffix(f, fileType) && !ignoreSuffix.Matches(f) } // generateEmpty generates the list of rules that don't need to exist in the // BUILD file any more. // For each bzl_library rule in args.File that only has srcs that aren't in // args.RegularFiles or args.GenFiles, add a bzl_library with no srcs or deps. // That will let Gazelle delete bzl_library rules after the corresponding .bzl // files are deleted. func generateEmpty(args language.GenerateArgs) []*rule.Rule { var ret []*rule.Rule if args.File == nil { return ret } for _, r := range args.File.Rules { if r.Kind() != "bzl_library" { continue } name := r.AttrString("name") exists := make(map[string]bool) for _, f := range args.RegularFiles { exists[f] = true } for _, f := range args.GenFiles { exists[f] = true } for _, r := range args.File.Rules { srcsExist := false for _, f := range r.AttrStrings("srcs") { if exists[f] { srcsExist = true break } } if !srcsExist { ret = append(ret, rule.NewRule("bzl_library", name)) } } } return ret } type srcsList []string func (s srcsList) Contains(m string) bool { for _, e := range s { if e == m { return true } } return false } // checkInternalVisibility overrides the given visibility if the package is // internal. func checkInternalVisibility(rel, visibility string) string { if i := pathtools.Index(rel, "internal"); i > 0 { visibility = fmt.Sprintf("//%s:__subpackages__", rel[:i-1]) } else if i := pathtools.Index(rel, "private"); i > 0 { visibility = fmt.Sprintf("//%s:__subpackages__", rel[:i-1]) } else if pathtools.HasPrefix(rel, "internal") || pathtools.HasPrefix(rel, "private") { visibility = "//:__subpackages__" } return visibility } bazel-skylib-1.9.1/gazelle/bzl/gazelle_test.go000066400000000000000000000071441517445036200213520ustar00rootroot00000000000000package bzl /* Copyright 2020 The Bazel Authors. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import ( "io/ioutil" "os" "os/exec" "path/filepath" "strings" "testing" "github.com/bazelbuild/bazel-gazelle/testtools" "github.com/bazelbuild/rules_go/go/tools/bazel" ) var gazellePath = findGazelle() const testDataPath = "bzl/testdata/" // TestGazelleBinary runs a gazelle binary with starlib installed on each // directory in `testdata/*`. Please see `testdata/README.md` for more // information on each test. func TestGazelleBinary(t *testing.T) { tests := map[string][]bazel.RunfileEntry{} files, err := bazel.ListRunfiles() if err != nil { t.Fatalf("bazel.ListRunfiles() error: %v", err) } for _, f := range files { if strings.HasPrefix(f.ShortPath, testDataPath) { relativePath := strings.TrimPrefix(f.ShortPath, testDataPath) parts := strings.SplitN(relativePath, "/", 2) if len(parts) < 2 { // This file is not a part of a testcase since it must be in a dir that // is the test case and then have a path inside of that. continue } tests[parts[0]] = append(tests[parts[0]], f) } } if len(tests) == 0 { t.Fatal("no tests found") } for testName, files := range tests { testPath(t, testName, files) } } func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { t.Run(name, func(t *testing.T) { var inputs []testtools.FileSpec var goldens []testtools.FileSpec for _, f := range files { path := f.Path trim := testDataPath + name + "/" shortPath := strings.TrimPrefix(f.ShortPath, trim) info, err := os.Stat(path) if err != nil { t.Fatalf("os.Stat(%q) error: %v", path, err) } // Skip dirs. if info.IsDir() { continue } content, err := ioutil.ReadFile(path) if err != nil { t.Errorf("ioutil.ReadFile(%q) error: %v", path, err) } // Now trim the common prefix off. if strings.HasSuffix(shortPath, ".in") { inputs = append(inputs, testtools.FileSpec{ Path: strings.TrimSuffix(shortPath, ".in"), Content: string(content), }) } else if strings.HasSuffix(shortPath, ".out") { goldens = append(goldens, testtools.FileSpec{ Path: strings.TrimSuffix(shortPath, ".out"), Content: string(content), }) } else { inputs = append(inputs, testtools.FileSpec{ Path: shortPath, Content: string(content), }) goldens = append(goldens, testtools.FileSpec{ Path: shortPath, Content: string(content), }) } } dir, cleanup := testtools.CreateFiles(t, inputs) defer cleanup() cmd := exec.Command(gazellePath, "-build_file_name=BUILD") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir if err := cmd.Run(); err != nil { t.Fatal(err) } testtools.CheckFiles(t, dir, goldens) if t.Failed() { filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } t.Logf("%q exists", path) return nil }) } }) } func findGazelle() string { gazellePath, ok := bazel.FindBinary("bzl", "gazelle-skylib") if !ok { panic("could not find gazelle binary") } return gazellePath } bazel-skylib-1.9.1/gazelle/bzl/testdata/000077500000000000000000000000001517445036200201445ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/README.md000066400000000000000000000035721517445036200214320ustar00rootroot00000000000000# Gazelle test cases This directory contains a suite of test cases for the Skylark language plugin for Gazelle. Please note that there are no `BUILD` or `BUILD.bazel` files in subdirs, instead there are `BUILD.in` and `BUILD.out` describing what the `BUILD` should look like initially and what the `BUILD` file should look like after the run. These names are special because they are not recognized by Bazel as a proper `BUILD` file, and therefore are included in the data dependency by the recursive data glob in `//gazelle:go_default_test`. If you would like to include any extremely complicated tests that contain proper `BUILD` files you will need to manually add them to the `//gazelle:go_default_test` target's `data` section. ## `simple` Simple is a base test case that was used to validate the parser. ## `nobuildfiles` A test just like `simple` that has no `BUILD` files at the beginning. ## `import` Import is a test case that imports a `.bzl` from the same directory. ## `multidir` Multidir is a test that has a `.bzl` that imports from a different dirrectory. ## `tests` Using the skylib as an example, this test has `.bzl` files that end in `_tests.bzl` which are `load`ed into `BUILD` files and never imported by another repo. ## `private` Using the skylib as an example, this test has `.bzl` files that live in a directory called `private` which is used to indicate that they are repo private. Note that this is distict from the expectations of go's `internal` where the relative position in the hierarchy determines the visibility. ## `defaultvisibility` If the package declares a `default_visibility` the generated `bzl_library` should not set its own `visibility`. ## `external` This test demonstrates that if you load from another repo, it is able to generate a `deps` entry for the dependency. ## `empty` Gazelle has the ability to remove old and unused targets. Test that. bazel-skylib-1.9.1/gazelle/bzl/testdata/bazel_tools/000077500000000000000000000000001517445036200224615ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/bazel_tools/BUILD.in000066400000000000000000000001351517445036200236470ustar00rootroot00000000000000# Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bazel-skylib-1.9.1/gazelle/bzl/testdata/bazel_tools/BUILD.out000066400000000000000000000004661517445036200240570ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") # Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = ["@bazel_tools//tools/build_defs/repo:http.bzl"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/bazel_tools/WORKSPACE000066400000000000000000000000001517445036200237300ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/bazel_tools/foo.bzl000066400000000000000000000002471517445036200237600ustar00rootroot00000000000000""" Doc string """ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") def wrapped_http_archive(**kwargs): http_archive( **kwargs ) bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/000077500000000000000000000000001517445036200237005ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/BUILD.in000066400000000000000000000000001517445036200250550ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/BUILD.out000066400000000000000000000002741517445036200252730ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = ["//nested/dir:bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/WORKSPACE000066400000000000000000000000001517445036200251470ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/foo.bzl000066400000000000000000000001011517445036200251640ustar00rootroot00000000000000""" Doc string """ load("//nested/dir:bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/nested/000077500000000000000000000000001517445036200251625ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/nested/dir/000077500000000000000000000000001517445036200257405ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/nested/dir/BUILD.in000066400000000000000000000000551517445036200271270ustar00rootroot00000000000000package(default_visibility = ["//:__pkg__"]) bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/nested/dir/BUILD.out000066400000000000000000000002371517445036200273320ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") package(default_visibility = ["//:__pkg__"]) bzl_library( name = "bar", srcs = ["bar.bzl"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/defaultvisibility/nested/dir/bar.bzl000066400000000000000000000000511517445036200272110ustar00rootroot00000000000000""" Doc string """ def asdf(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/empty/000077500000000000000000000000001517445036200213025ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/empty/BUILD.in000066400000000000000000000005231517445036200224710ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "weirdly_named_target_that_will_be_removed", srcs = ["nonexistent.bzl"], visibility = ["//visibility:public"], ) bzl_library( name = "weirdly_named_target_that_will_be_renamed", srcs = ["foo.bzl"], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/empty/BUILD.out000066400000000000000000000002331517445036200226700ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/empty/WORKSPACE000066400000000000000000000000001517445036200225510ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/empty/foo.bzl000066400000000000000000000000001517445036200225640ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/external/000077500000000000000000000000001517445036200217665ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/external/BUILD.in000066400000000000000000000002251517445036200231540ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") # Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bazel-skylib-1.9.1/gazelle/bzl/testdata/external/BUILD.out000066400000000000000000000004461517445036200233620ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") # Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = ["@external_repo//path/to:file"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/external/WORKSPACE000066400000000000000000000000001517445036200232350ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/external/foo.bzl000066400000000000000000000001241517445036200232570ustar00rootroot00000000000000""" Test sample code. """ load("@external_repo//path/to:file.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/import/000077500000000000000000000000001517445036200214565ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/import/BUILD.in000066400000000000000000000000001517445036200226330ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/import/BUILD.out000066400000000000000000000004241517445036200230460ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//visibility:public"], ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = [":bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/import/WORKSPACE000066400000000000000000000000001517445036200227250ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/import/bar.bzl000066400000000000000000000000511517445036200227270ustar00rootroot00000000000000""" Doc string """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/import/foo.bzl000066400000000000000000000000671517445036200227550ustar00rootroot00000000000000""" Doc string """ load("//:bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/000077500000000000000000000000001517445036200217755ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/BUILD.in000066400000000000000000000000001517445036200231520ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/BUILD.out000066400000000000000000000002741517445036200233700ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = ["//nested/dir:bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/WORKSPACE000066400000000000000000000000001517445036200232440ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/foo.bzl000066400000000000000000000001011517445036200232610ustar00rootroot00000000000000""" Doc string """ load("//nested/dir:bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/nested/000077500000000000000000000000001517445036200232575ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/nested/dir/000077500000000000000000000000001517445036200240355ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/nested/dir/BUILD.out000066400000000000000000000002331517445036200254230ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/multidir/nested/dir/bar.bzl000066400000000000000000000000511517445036200253060ustar00rootroot00000000000000""" Doc string """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/nobuildfiles/000077500000000000000000000000001517445036200226235ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/nobuildfiles/BUILD.out000066400000000000000000000002331517445036200242110ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/nobuildfiles/WORKSPACE000066400000000000000000000000001517445036200240720ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/nobuildfiles/foo.bzl000066400000000000000000000000001517445036200241050ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/000077500000000000000000000000001517445036200216165ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/BUILD.in000066400000000000000000000000001517445036200227730ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/BUILD.out000066400000000000000000000002711517445036200232060ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = ["//private:bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/private/WORKSPACE000066400000000000000000000000001517445036200230650ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/foo.bzl000066400000000000000000000001051517445036200231060ustar00rootroot00000000000000""" Test sample code. """ load("//private:bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/000077500000000000000000000000001517445036200231005ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/000077500000000000000000000000001517445036200245525ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/BUILD.out000066400000000000000000000002401517445036200261360ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//nested:__subpackages__"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/bar.bzl000066400000000000000000000000601517445036200260230ustar00rootroot00000000000000""" Test sample code. """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/inside/000077500000000000000000000000001517445036200260255ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/inside/internal/000077500000000000000000000000001517445036200276415ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/inside/internal/BUILD.out000066400000000000000000000002571517445036200312350ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//nested/private/inside:__subpackages__"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/private/nested/private/inside/internal/bar.bzl000066400000000000000000000000601517445036200311120ustar00rootroot00000000000000""" Test sample code. """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/private/private/000077500000000000000000000000001517445036200232705ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/private/private/BUILD.out000066400000000000000000000002321517445036200246550ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//:__subpackages__"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/private/private/bar.bzl000066400000000000000000000000601517445036200245410ustar00rootroot00000000000000""" Test sample code. """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/000077500000000000000000000000001517445036200233515ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/BUILD.in000066400000000000000000000000001517445036200245260ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/BUILD.out000066400000000000000000000004241517445036200247410ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//visibility:public"], ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = [":bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/WORKSPACE000066400000000000000000000000001517445036200246200ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/bar.bzl000066400000000000000000000000511517445036200246220ustar00rootroot00000000000000""" Doc string """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/foo.bzl000066400000000000000000000000651517445036200246460ustar00rootroot00000000000000""" Doc string """ load(":bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/nested/000077500000000000000000000000001517445036200246335ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/nested/dir/000077500000000000000000000000001517445036200254115ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/nested/dir/BUILD.in000066400000000000000000000000001517445036200265660ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/nested/dir/BUILD.out000066400000000000000000000004241517445036200270010ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//visibility:public"], ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = [":bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/nested/dir/bar.bzl000066400000000000000000000000511517445036200266620ustar00rootroot00000000000000""" Doc string """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/relative_import/nested/dir/foo.bzl000066400000000000000000000000651517445036200267060ustar00rootroot00000000000000""" Doc string """ load(":bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/bzl/testdata/simple/000077500000000000000000000000001517445036200214355ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/simple/BUILD.in000066400000000000000000000001351517445036200226230ustar00rootroot00000000000000# Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bazel-skylib-1.9.1/gazelle/bzl/testdata/simple/BUILD.out000066400000000000000000000003711517445036200230260ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") # Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/simple/WORKSPACE000066400000000000000000000000001517445036200227040ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/simple/foo.bzl000066400000000000000000000000001517445036200227170ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/tests/000077500000000000000000000000001517445036200213065ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/tests/BUILD.in000066400000000000000000000001351517445036200224740ustar00rootroot00000000000000# Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bazel-skylib-1.9.1/gazelle/bzl/testdata/tests/BUILD.out000066400000000000000000000003711517445036200226770ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") # Some comment to be preserved filegroup( name = "allfiles", srcs = glob(["**"]), ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/tests/WORKSPACE000066400000000000000000000000001517445036200225550ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/tests/foo.bzl000066400000000000000000000000001517445036200225700ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/tests/foo_tests.bzl000066400000000000000000000000001517445036200240120ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/workspace_name/000077500000000000000000000000001517445036200231425ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/workspace_name/BUILD.in000066400000000000000000000000001517445036200243170ustar00rootroot00000000000000bazel-skylib-1.9.1/gazelle/bzl/testdata/workspace_name/BUILD.out000066400000000000000000000004241517445036200245320ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "bar", srcs = ["bar.bzl"], visibility = ["//visibility:public"], ) bzl_library( name = "foo", srcs = ["foo.bzl"], visibility = ["//visibility:public"], deps = [":bar"], ) bazel-skylib-1.9.1/gazelle/bzl/testdata/workspace_name/WORKSPACE000066400000000000000000000000401517445036200244150ustar00rootroot00000000000000workspace(name = "com_example") bazel-skylib-1.9.1/gazelle/bzl/testdata/workspace_name/bar.bzl000066400000000000000000000000511517445036200244130ustar00rootroot00000000000000""" Doc string """ def func(): pass bazel-skylib-1.9.1/gazelle/bzl/testdata/workspace_name/foo.bzl000066400000000000000000000000671517445036200244410ustar00rootroot00000000000000""" Doc string """ load("//:bar.bzl", "func") func() bazel-skylib-1.9.1/gazelle/setup.bzl000066400000000000000000000024561517445036200174240ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Dependency registration helpers for the gazelle plugin.""" load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") def bazel_skylib_gazelle_plugin_setup(go_version = "1.20.5", register_go_toolchains = True): """Set up the dependencies needed by the Gazelle plugin. Args: go_version: The version of Go registered as part of the build as a string register_go_toolchains: A boolean indicating whether or not to register the Go toolchains. Defaults to `True` """ go_rules_dependencies() if register_go_toolchains: go_register_toolchains(version = go_version) gazelle_dependencies() bazel-skylib-1.9.1/gazelle/workspace.bzl000066400000000000000000000044131517445036200202550ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Dependency registration helpers for repositories which need to load bazel-skylib's gazelle plugin.""" load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") def bazel_skylib_gazelle_plugin_workspace(): """Loads dependencies required to use skylib's gazelle plugin""" bazel_skylib_workspace() maybe( http_archive, name = "rules_license", sha256 = "4531deccb913639c30e5c7512a054d5d875698daeb75d8cf90f284375fe7c360", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz", "https://github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz", ], ) maybe( http_archive, name = "io_bazel_rules_go", sha256 = "278b7ff5a826f3dc10f04feaf0b70d48b68748ccd512d7f98bf442077f043fe3", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", "https://github.com/bazelbuild/rules_go/releases/download/v0.41.0/rules_go-v0.41.0.zip", ], ) maybe( http_archive, name = "bazel_gazelle", sha256 = "ecba0f04f96b4960a5b250c8e8eeec42281035970aa8852dda73098274d14a1d", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.29.0/bazel-gazelle-v0.29.0.tar.gz", ], ) bazel-skylib-1.9.1/lib.bzl000066400000000000000000000014331517445036200154010ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Index from which multiple modules can be loaded.""" fail( "lib.bzl has been removed, please directly load the bzl file(s) of the" + " module(s) needed as it is more efficient.", ) bazel-skylib-1.9.1/lib/000077500000000000000000000000001517445036200146675ustar00rootroot00000000000000bazel-skylib-1.9.1/lib/BUILD000066400000000000000000000047271517445036200154630ustar00rootroot00000000000000load("//:bzl_library.bzl", "bzl_library") load("//rules:common_settings.bzl", "bool_setting") load(":selects.bzl", "selects") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) # export bzl files for the documentation exports_files( glob(["*.bzl"]), visibility = ["//:__subpackages__"], ) bzl_library( name = "collections", srcs = ["collections.bzl"], ) bzl_library( name = "dicts", srcs = ["dicts.bzl"], ) bzl_library( name = "modules", srcs = ["modules.bzl"], ) bzl_library( name = "partial", srcs = ["partial.bzl"], ) bzl_library( name = "paths", srcs = ["paths.bzl"], ) bzl_library( name = "selects", srcs = ["selects.bzl"], ) bzl_library( name = "sets", srcs = ["sets.bzl"], deps = [ ":new_sets", ], ) bzl_library( name = "new_sets", srcs = ["new_sets.bzl"], deps = [ ":dicts", ], ) bzl_library( name = "shell", srcs = ["shell.bzl"], ) bzl_library( name = "structs", srcs = ["structs.bzl"], ) bzl_library( name = "subpackages", srcs = ["subpackages.bzl"], ) bzl_library( name = "types", srcs = ["types.bzl"], ) bzl_library( name = "unittest", srcs = ["unittest.bzl"], deps = [ ":new_sets", ":partial", ":sets", ":types", ], ) bzl_library( name = "versions", srcs = ["versions.bzl"], ) filegroup( name = "test_deps", testonly = True, srcs = ["BUILD"] + glob(["*.bzl"]), visibility = ["//:__subpackages__"], # Needs skylib's root BUILD file for default_applicable_licenses ) # The files needed for distribution filegroup( name = "distribution", srcs = glob(["*"]), visibility = [ "//:__pkg__", "//distribution:__pkg__", ], ) bzl_library( name = "old_sets", srcs = ["old_sets.bzl"], ) # The following are used construct an "always true" config_setting, which is used in selects.bzl. bool_setting( name = "bool", build_setting_default = False, visibility = ["//visibility:private"], ) config_setting( name = "bool_on", flag_values = {":bool": "true"}, visibility = ["//visibility:private"], ) config_setting( name = "bool_off", flag_values = {":bool": "false"}, visibility = ["//visibility:private"], ) selects.config_setting_group( name = "always_true", match_any = [ ":bool_on", ":bool_off", ], ) bazel-skylib-1.9.1/lib/collections.bzl000066400000000000000000000042001517445036200177120ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing functions that operate on collections.""" def _after_each(separator, iterable): """Inserts `separator` after each item in `iterable`. Args: separator: The value to insert after each item in `iterable`. iterable: The list into which to intersperse the separator. Returns: A new list with `separator` after each item in `iterable`. """ result = [] for x in iterable: result.append(x) result.append(separator) return result def _before_each(separator, iterable): """Inserts `separator` before each item in `iterable`. Args: separator: The value to insert before each item in `iterable`. iterable: The list into which to intersperse the separator. Returns: A new list with `separator` before each item in `iterable`. """ result = [] for x in iterable: result.append(separator) result.append(x) return result def _uniq(iterable): """Returns a list of unique elements in `iterable`. Requires all the elements to be hashable. Args: iterable: An iterable to filter. Returns: A new list with all unique elements from `iterable`. """ unique_elements = {element: None for element in iterable} # list() used here for python3 compatibility. # TODO(bazel-team): Remove when testing frameworks no longer require python compatibility. return list(unique_elements.keys()) collections = struct( after_each = _after_each, before_each = _before_each, uniq = _uniq, ) bazel-skylib-1.9.1/lib/dicts.bzl000066400000000000000000000045521517445036200165140ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing functions that operate on dictionaries.""" def _add(*dictionaries, **kwargs): """Returns a new `dict` that has all the entries of the given dictionaries. If the same key is present in more than one of the input dictionaries, the last of them in the argument list overrides any earlier ones. This function is designed to take zero or one arguments as well as multiple dictionaries, so that it follows arithmetic identities and callers can avoid special cases for their inputs: the sum of zero dictionaries is the empty dictionary, and the sum of a single dictionary is a copy of itself. Args: *dictionaries: Zero or more dictionaries to be added. **kwargs: Additional dictionary passed as keyword args. Returns: A new `dict` that has all the entries of the given dictionaries. """ result = {} for d in dictionaries: result.update(d) result.update(kwargs) return result def _omit(dictionary, keys): """Returns a new `dict` that has all the entries of `dictionary` with keys not in `keys`. Args: dictionary: A `dict`. keys: A sequence. Returns: A new `dict` that has all the entries of `dictionary` with keys not in `keys`. """ keys_set = {k: None for k in keys} return {k: dictionary[k] for k in dictionary if k not in keys_set} def _pick(dictionary, keys): """Returns a new `dict` that has all the entries of `dictionary` with keys in `keys`. Args: dictionary: A `dict`. keys: A sequence. Returns: A new `dict` that has all the entries of `dictionary` with keys in `keys`. """ return {k: dictionary[k] for k in keys if k in dictionary} dicts = struct( add = _add, omit = _omit, pick = _pick, ) bazel-skylib-1.9.1/lib/modules.bzl000066400000000000000000000115651517445036200170600ustar00rootroot00000000000000# Copyright 2023 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing utilities for Bazel modules and module extensions.""" def _as_extension(macro, doc = None): """Wraps a WORKSPACE dependency macro into a module extension. Example: ```starlark def rules_foo_deps(optional_arg = True): some_repo_rule(name = "foobar") http_archive(name = "bazqux") rules_foo_deps_ext = modules.as_extension(rules_foo_deps) ``` Args: macro: A [WORKSPACE dependency macro](https://bazel.build/rules/deploying#dependencies), i.e., a function with no required parameters that instantiates one or more repository rules. doc: A description of the module extension that can be extracted by documentation generating tools. Returns: A module extension that generates the repositories instantiated by the given macro and also uses [`use_all_repos`](#use_all_repos) to indicate that all of those repositories should be imported via `use_repo`. The extension is marked as reproducible if supported by the current version of Bazel and thus doesn't result in a lockfile entry. """ def _ext_impl(module_ctx): macro() # Setting `reproducible` is safe since `macro`, as a function without parameters, must be # deterministic. return _use_all_repos(module_ctx, reproducible = True) kwargs = {} if doc != None: kwargs["doc"] = doc return module_extension( implementation = _ext_impl, **kwargs ) def _use_all_repos(module_ctx, reproducible = False): """Return from a module extension that should have all its repositories imported via `use_repo`. Example: ```starlark def _ext_impl(module_ctx): some_repo_rule(name = "foobar") http_archive(name = "bazqux") return modules.use_all_repos(module_ctx) ext = module_extension(_ext_impl) ``` Args: module_ctx: The [`module_ctx`](https://bazel.build/rules/lib/builtins/module_ctx) object passed to the module extension's implementation function. reproducible: The value of the `reproducible` parameter to pass to the [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html) object returned by this function. This is safe to set with Bazel versions that don't support this parameter and will be ignored in that case. Returns: An [`extension_metadata`](https://bazel.build/rules/lib/builtins/extension_metadata.html) object that, when returned from a module extension implementation function, specifies that all repositories generated by this extension should be imported via `use_repo`. If the current version of Bazel doesn't support `extension_metadata`, returns `None` instead, which can safely be returned from a module extension implementation function in all versions of Bazel. """ # module_ctx.extension_metadata is available in Bazel 6.2.0 and later. # If not available, returning None from a module extension is equivalent to not returning # anything. extension_metadata = getattr(module_ctx, "extension_metadata", None) if not extension_metadata: return None # module_ctx.root_module_has_non_dev_dependency is available in Bazel 6.3.0 and later. root_module_has_non_dev_dependency = getattr( module_ctx, "root_module_has_non_dev_dependency", None, ) if root_module_has_non_dev_dependency == None: return None # module_ctx.extension_metadata has the paramater `reproducible` as of Bazel 7.1.0. We can't # test for it directly and would ideally use bazel_features to check for it, but adding a # dependency on it would require complicating the WORKSPACE setup for skylib. Thus, test for # it by checking the availability of another feature introduced in 7.1.0. extension_metadata_kwargs = {} if hasattr(module_ctx, "watch"): extension_metadata_kwargs["reproducible"] = reproducible return extension_metadata( root_module_direct_deps = "all" if root_module_has_non_dev_dependency else [], root_module_direct_dev_deps = [] if root_module_has_non_dev_dependency else "all", **extension_metadata_kwargs ) modules = struct( as_extension = _as_extension, use_all_repos = _use_all_repos, ) bazel-skylib-1.9.1/lib/new_sets.bzl000066400000000000000000000143271517445036200172360ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing common hash-set algorithms. An empty set can be created using: `sets.make()`, or it can be created with some starting values if you pass it an sequence: `sets.make([1, 2, 3])`. This returns a struct containing all of the values as keys in a dictionary - this means that all passed in values must be hashable. The values in the set can be retrieved using `sets.to_list(my_set)`. An arbitrary object can be tested whether it is a set generated by `sets.make()` or not with the `types.is_set()` method in types.bzl. """ load(":dicts.bzl", "dicts") def _make(elements = None): """Creates a new set. All elements must be hashable. Args: elements: Optional sequence to construct the set out of. Returns: A set containing the passed in values. """ # If you change the structure of a set, you need to also update the _is_set method # in types.bzl. elements = elements if elements else [] return struct(_values = {e: None for e in elements}) def _copy(s): """Creates a new set from another set. Args: s: A set, as returned by `sets.make()`. Returns: A new set containing the same elements as `s`. """ return struct(_values = dict(s._values)) def _to_list(s): """Creates a list from the values in the set. Args: s: A set, as returned by `sets.make()`. Returns: A list of values inserted into the set. """ return s._values.keys() def _insert(s, e): """Inserts an element into the set. Element must be hashable. This mutates the original set. Args: s: A set, as returned by `sets.make()`. e: The element to be inserted. Returns: The set `s` with `e` included. """ s._values[e] = None return s def _remove(s, e): """Removes an element from the set. Element must be hashable. This mutates the original set. Args: s: A set, as returned by `sets.make()`. e: The element to be removed. Returns: The set `s` with `e` removed. """ s._values.pop(e) return s def _contains(a, e): """Checks for the existence of an element in a set. Args: a: A set, as returned by `sets.make()`. e: The element to look for. Returns: True if the element exists in the set, False if the element does not. """ return e in a._values def _get_shorter_and_longer(a, b): """Returns two sets in the order of shortest and longest. Args: a: A set, as returned by `sets.make()`. b: A set, as returned by `sets.make()`. Returns: `a`, `b` if `a` is shorter than `b` - or `b`, `a` if `b` is shorter than `a`. """ if _length(a) < _length(b): return a, b return b, a def _is_equal(a, b): """Returns whether two sets are equal. Args: a: A set, as returned by `sets.make()`. b: A set, as returned by `sets.make()`. Returns: True if `a` is equal to `b`, False otherwise. """ return a._values == b._values def _is_subset(a, b): """Returns whether `a` is a subset of `b`. Args: a: A set, as returned by `sets.make()`. b: A set, as returned by `sets.make()`. Returns: True if `a` is a subset of `b`, False otherwise. """ for e in a._values.keys(): if e not in b._values: return False return True def _disjoint(a, b): """Returns whether two sets are disjoint. Two sets are disjoint if they have no elements in common. Args: a: A set, as returned by `sets.make()`. b: A set, as returned by `sets.make()`. Returns: True if `a` and `b` are disjoint, False otherwise. """ shorter, longer = _get_shorter_and_longer(a, b) for e in shorter._values.keys(): if e in longer._values: return False return True def _intersection(a, b): """Returns the intersection of two sets. Args: a: A set, as returned by `sets.make()`. b: A set, as returned by `sets.make()`. Returns: A set containing the elements that are in both `a` and `b`. """ shorter, longer = _get_shorter_and_longer(a, b) return struct(_values = {e: None for e in shorter._values.keys() if e in longer._values}) def _union(*args): """Returns the union of several sets. Args: *args: An arbitrary number of sets. Returns: The set union of all sets in `*args`. """ return struct(_values = dicts.add(*[s._values for s in args])) def _difference(a, b): """Returns the elements in `a` that are not in `b`. Args: a: A set, as returned by `sets.make()`. b: A set, as returned by `sets.make()`. Returns: A set containing the elements that are in `a` but not in `b`. """ return struct(_values = {e: None for e in a._values.keys() if e not in b._values}) def _length(s): """Returns the number of elements in a set. Args: s: A set, as returned by `sets.make()`. Returns: An integer representing the number of elements in the set. """ return len(s._values) def _repr(s): """Returns a string value representing the set. Args: s: A set, as returned by `sets.make()`. Returns: A string representing the set. """ return repr(s._values.keys()) sets = struct( make = _make, copy = _copy, to_list = _to_list, insert = _insert, contains = _contains, is_equal = _is_equal, is_subset = _is_subset, disjoint = _disjoint, intersection = _intersection, union = _union, difference = _difference, length = _length, remove = _remove, repr = _repr, str = _repr, # is_set is declared in types.bzl ) bazel-skylib-1.9.1/lib/old_sets.bzl000066400000000000000000000013121517445036200172110ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Obsolete file, see sets.bzl instead.""" fail("old_sets.bzl has been removed, please use sets.bzl instead") bazel-skylib-1.9.1/lib/partial.bzl000066400000000000000000000127231517445036200170410ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Starlark module for working with partial function objects. Partial function objects allow some parameters are bound before the call. Similar to https://docs.python.org/3/library/functools.html#functools.partial. """ # create instance singletons to avoid unnecessary allocations _a_dict_type = type({}) _a_tuple_type = type(()) _a_struct_type = type(struct()) def _call(partial, *args, **kwargs): """Calls a partial created using `make`. Args: partial: The partial to be called. *args: Additional positional arguments to be appended to the ones given to make. **kwargs: Additional keyword arguments to augment and override the ones given to make. Returns: Whatever the function in the partial returns. """ function_args = partial.args + args function_kwargs = dict(partial.kwargs) function_kwargs.update(kwargs) return partial.function(*function_args, **function_kwargs) def _make(func, *args, **kwargs): """Creates a partial that can be called using `call`. A partial can have args assigned to it at the make site, and can have args passed to it at the call sites. A partial 'function' can be defined with positional args and kwargs: # function with no args ``` def function1(): ... ``` # function with 2 args ``` def function2(arg1, arg2): ... ``` # function with 2 args and keyword args ``` def function3(arg1, arg2, x, y): ... ``` The positional args passed to the function are the args passed into make followed by any additional positional args given to call. The below example illustrates a function with two positional arguments where one is supplied by make and the other by call: # function demonstrating 1 arg at make site, and 1 arg at call site ``` def _foo(make_arg1, func_arg1): print(make_arg1 + " " + func_arg1 + "!") ``` For example: ``` hi_func = partial.make(_foo, "Hello") bye_func = partial.make(_foo, "Goodbye") partial.call(hi_func, "Jennifer") partial.call(hi_func, "Dave") partial.call(bye_func, "Jennifer") partial.call(bye_func, "Dave") ``` prints: ``` "Hello, Jennifer!" "Hello, Dave!" "Goodbye, Jennifer!" "Goodbye, Dave!" ``` The keyword args given to the function are the kwargs passed into make unioned with the keyword args given to call. In case of a conflict, the keyword args given to call take precedence. This allows you to set a default value for keyword arguments and override it at the call site. Example with a make site arg, a call site arg, a make site kwarg and a call site kwarg: ``` def _foo(make_arg1, call_arg1, make_location, call_location): print(make_arg1 + " is from " + make_location + " and " + call_arg1 + " is from " + call_location + "!") func = partial.make(_foo, "Ben", make_location="Hollywood") partial.call(func, "Jennifer", call_location="Denver") ``` Prints "Ben is from Hollywood and Jennifer is from Denver!". ``` partial.call(func, "Jennifer", make_location="LA", call_location="Denver") ``` Prints "Ben is from LA and Jennifer is from Denver!". Note that keyword args may not overlap with positional args, regardless of whether they are given during the make or call step. For instance, you can't do: ``` def foo(x): pass func = partial.make(foo, 1) partial.call(func, x=2) ``` Args: func: The function to be called. *args: Positional arguments to be passed to function. **kwargs: Keyword arguments to be passed to function. Note that these can be overridden at the call sites. Returns: A new `partial` that can be called using `call` """ return struct(function = func, args = args, kwargs = kwargs) def _is_instance(v): """Returns True if v is a partial created using `make`. Args: v: The value to check. Returns: True if v was created by `make`, False otherwise. """ # Note that in bazel 3.7.0 and earlier, type(v.function) is the same # as the type of a function even if v.function is a rule. But we # cannot rely on this in later bazels due to breaking change # https://github.com/bazelbuild/bazel/commit/e379ece1908aafc852f9227175dd3283312b4b82 # # Since this check is heuristic anyway, we simply check for the # presence of a "function" attribute without checking its type. return type(v) == _a_struct_type and \ hasattr(v, "function") and \ hasattr(v, "args") and type(v.args) == _a_tuple_type and \ hasattr(v, "kwargs") and type(v.kwargs) == _a_dict_type partial = struct( make = _make, call = _call, is_instance = _is_instance, ) bazel-skylib-1.9.1/lib/paths.bzl000066400000000000000000000242121517445036200165200ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing file path manipulation functions. NOTE: The functions in this module currently only support paths with Unix-style path separators (forward slash, "/"); they do not handle Windows-style paths with backslash separators or drive letters. """ def _basename(p): """Returns the basename (i.e., the file portion) of a path. Note that if `p` ends with a slash, this function returns an empty string. This matches the behavior of Python's `os.path.basename`, but differs from the Unix `basename` command (which would return the path segment preceding the final slash). Args: p: The path whose basename should be returned. Returns: The basename of the path, which includes the extension. """ return p.rpartition("/")[-1] def _dirname(p): """Returns the dirname of a path. The dirname is the portion of `p` up to but not including the file portion (i.e., the basename). Any slashes immediately preceding the basename are not included, unless omitting them would make the dirname empty. Args: p: The path whose dirname should be returned. Returns: The dirname of the path. """ prefix, sep, _ = p.rpartition("/") if not prefix: return sep else: # If there are multiple consecutive slashes, strip them all out as Python's # os.path.dirname does. return prefix.rstrip("/") def _is_absolute(path): """Returns `True` if `path` is an absolute path. Args: path: A path (which is a string). Returns: `True` if `path` is an absolute path. """ return path.startswith("/") or (len(path) > 2 and path[1] == ":") def _join(path, *others): """Joins one or more path components intelligently. This function mimics the behavior of Python's `os.path.join` function on POSIX platform. It returns the concatenation of `path` and any members of `others`, inserting directory separators before each component except the first. The separator is not inserted if the path up until that point is either empty or already ends in a separator. If any component is an absolute path, all previous components are discarded. Args: path: A path segment. *others: Additional path segments. Returns: A string containing the joined paths. """ result = path for p in others: if _is_absolute(p): result = p elif not result or result.endswith("/"): result += p else: result += "/" + p return result def _normalize(path): """Normalizes a path, eliminating double slashes and other redundant segments. This function mimics the behavior of Python's `os.path.normpath` function on POSIX platforms; specifically: - If the entire path is empty, "." is returned. - All "." segments are removed, unless the path consists solely of a single "." segment. - Trailing slashes are removed, unless the path consists solely of slashes. - ".." segments are removed as long as there are corresponding segments earlier in the path to remove; otherwise, they are retained as leading ".." segments. - Single and double leading slashes are preserved, but three or more leading slashes are collapsed into a single leading slash. - Multiple adjacent internal slashes are collapsed into a single slash. Args: path: A path. Returns: The normalized path. """ if not path: return "." if path.startswith("//") and not path.startswith("///"): initial_slashes = 2 elif path.startswith("/"): initial_slashes = 1 else: initial_slashes = 0 is_relative = (initial_slashes == 0) components = path.split("/") new_components = [] for component in components: if component in ("", "."): continue if component == "..": if new_components and new_components[-1] != "..": # Only pop the last segment if it isn't another "..". new_components.pop() elif is_relative: # Preserve leading ".." segments for relative paths. new_components.append(component) else: new_components.append(component) path = "/".join(new_components) if not is_relative: path = ("/" * initial_slashes) + path return path or "." _BASE = 0 _SEPARATOR = 1 _DOT = 2 _DOTDOT = 3 def _is_normalized(str, look_for_same_level_references = True): """Returns true if the passed path doesn't contain uplevel references "..". Also checks for single-dot references "." if look_for_same_level_references is `True.` Args: str: The path string to check. look_for_same_level_references: If True checks if path doesn't contain uplevel references ".." or single-dot references ".". Returns: True if the path is normalized, False otherwise. """ state = _SEPARATOR for c in str.elems(): is_separator = False if c == "/": is_separator = True if state == _BASE: if is_separator: state = _SEPARATOR else: state = _BASE elif state == _SEPARATOR: if is_separator: state = _SEPARATOR elif c == ".": state = _DOT else: state = _BASE elif state == _DOT: if is_separator: if look_for_same_level_references: # "." segment found. return False state = _SEPARATOR elif c == ".": state = _DOTDOT else: state = _BASE elif state == _DOTDOT: if is_separator: return False else: state = _BASE if state == _DOT: if look_for_same_level_references: # "." segment found. return False elif state == _DOTDOT: return False return True def _relativize(path, start): """Returns the portion of `path` that is relative to `start`. Because we do not have access to the underlying file system, this implementation differs slightly from Python's `os.path.relpath` in that it will fail if `path` is not beneath `start` (rather than use parent segments to walk up to the common file system root). Relativizing paths that start with parent directory references only works if the path both start with the same initial parent references. Args: path: The path to relativize. start: The ancestor path against which to relativize. Returns: The portion of `path` that is relative to `start`. """ segments = _normalize(path).split("/") start_segments = _normalize(start).split("/") if start_segments == ["."]: start_segments = [] start_length = len(start_segments) if (path.startswith("/") != start.startswith("/") or len(segments) < start_length): fail("Path '%s' is not beneath '%s'" % (path, start)) for ancestor_segment, segment in zip(start_segments, segments): if ancestor_segment != segment: fail("Path '%s' is not beneath '%s'" % (path, start)) length = len(segments) - start_length result_segments = segments[-length:] return "/".join(result_segments) def _replace_extension(p, new_extension): """Replaces the extension of the file at the end of a path. If the path has no extension, the new extension is added to it. Args: p: The path whose extension should be replaced. new_extension: The new extension for the file. The new extension should begin with a dot if you want the new filename to have one. Returns: The path with the extension replaced (or added, if it did not have one). """ return _split_extension(p)[0] + new_extension def _split_extension(p): """Splits the path `p` into a tuple containing the root and extension. Leading periods on the basename are ignored, so `path.split_extension(".bashrc")` returns `(".bashrc", "")`. Args: p: The path whose root and extension should be split. Returns: A tuple `(root, ext)` such that the root is the path without the file extension, and `ext` is the file extension (which, if non-empty, contains the leading dot). The returned tuple always satisfies the relationship `root + ext == p`. """ b = _basename(p) last_dot_in_basename = b.rfind(".") # If there is no dot or the only dot in the basename is at the front, then # there is no extension. if last_dot_in_basename <= 0: return (p, "") dot_distance_from_end = len(b) - last_dot_in_basename return (p[:-dot_distance_from_end], p[-dot_distance_from_end:]) def _starts_with(path_a, path_b): """Returns True if and only if path_b is an ancestor of path_a. Does not handle OS dependent case-insensitivity.""" if not path_b: # all paths start with the empty string return True norm_a = _normalize(path_a) norm_b = _normalize(path_b) if len(norm_b) > len(norm_a): return False if not norm_a.startswith(norm_b): return False return len(norm_a) == len(norm_b) or norm_a[len(norm_b)] == "/" paths = struct( basename = _basename, dirname = _dirname, is_absolute = _is_absolute, join = _join, normalize = _normalize, is_normalized = _is_normalized, relativize = _relativize, replace_extension = _replace_extension, split_extension = _split_extension, starts_with = _starts_with, ) bazel-skylib-1.9.1/lib/selects.bzl000066400000000000000000000215671517445036200170550ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing convenience interfaces for select().""" def _with_or(input_dict, no_match_error = ""): """Drop-in replacement for `select()` that supports ORed keys. Example: ```build deps = selects.with_or({ "//configs:one": [":dep1"], ("//configs:two", "//configs:three"): [":dep2or3"], "//configs:four": [":dep4"], "//conditions:default": [":default"] }) ``` Key labels may appear at most once anywhere in the input. Args: input_dict: The same dictionary `select()` takes, except keys may take either the usual form `"//foo:config1"` or `("//foo:config1", "//foo:config2", ...)` to signify `//foo:config1` OR `//foo:config2` OR `...`. no_match_error: Optional custom error to report if no condition matches. Returns: A native `select()` that expands `("//configs:two", "//configs:three"): [":dep2or3"]` to ```build "//configs:two": [":dep2or3"], "//configs:three": [":dep2or3"], ``` """ return select(_with_or_dict(input_dict), no_match_error = no_match_error) def _with_or_dict(input_dict): """Variation of `with_or` that returns the dict of the `select()`. Unlike `select()`, the contents of the dict can be inspected by Starlark macros. Args: input_dict: Same as `with_or`. Returns: A dictionary usable by a native `select()`. """ output_dict = {} for (key, value) in input_dict.items(): if type(key) == type(()): for config_setting in key: if config_setting in output_dict.keys(): fail("key %s appears multiple times" % config_setting) output_dict[config_setting] = value else: if key in output_dict.keys(): fail("key %s appears multiple times" % key) output_dict[key] = value return output_dict def _config_setting_group(name, match_any = [], match_all = [], visibility = None): """Matches if all or any of its member `config_setting`s match. Example: ```build config_setting(name = "one", define_values = {"foo": "true"}) config_setting(name = "two", define_values = {"bar": "false"}) config_setting(name = "three", define_values = {"baz": "more_false"}) config_setting_group( name = "one_two_three", match_all = [":one", ":two", ":three"] ) cc_binary( name = "myapp", srcs = ["myapp.cc"], deps = select({ ":one_two_three": [":special_deps"], "//conditions:default": [":default_deps"] }) ``` Args: name: The group's name. This is how `select()`s reference it. match_any: A list of `config_settings`. This group matches if *any* member in the list matches. If this is set, `match_all` must not be set. match_all: A list of `config_settings`. This group matches if *every* member in the list matches. If this is set, `match_any` must be not set. visibility: Visibility of the config_setting_group. """ empty1 = not bool(len(match_any)) empty2 = not bool(len(match_all)) if (empty1 and empty2) or (not empty1 and not empty2): fail('Either "match_any" or "match_all" must be set, but not both.') _check_duplicates(match_any) _check_duplicates(match_all) if ((len(match_any) == 1 and match_any[0] == "//conditions:default") or (len(match_all) == 1 and match_all[0] == "//conditions:default")): # If the only entry is "//conditions:default", the condition is # automatically true. _config_setting_always_true(name, visibility) elif not empty1: _config_setting_or_group(name, match_any, visibility) else: _config_setting_and_group(name, match_all, visibility) def _check_duplicates(settings): """Fails if any entry in settings appears more than once.""" seen = {} for setting in settings: if setting in seen: fail(setting + " appears more than once. Duplicates not allowed.") seen[setting] = True def _remove_default_condition(settings): """Returns settings with "//conditions:default" entries filtered out.""" new_settings = [] for setting in settings: if settings != "//conditions:default": new_settings.append(setting) return new_settings def _config_setting_or_group(name, settings, visibility): """ORs multiple config_settings together (inclusively). The core idea is to create a sequential chain of alias targets where each is select-resolved as follows: If alias n matches config_setting n, the chain is true so it resolves to config_setting n. Else it resolves to alias n+1 (which checks config_setting n+1, and so on). If none of the config_settings match, the final alias resolves to one of them arbitrarily, which by definition doesn't match. """ # "//conditions:default" is present, the whole chain is automatically true. if len(_remove_default_condition(settings)) < len(settings): _config_setting_always_true(name, visibility) return elif len(settings) == 1: # One entry? Just alias directly to it. native.alias( name = name, actual = settings[0], visibility = visibility, ) return # We need n-1 aliases for n settings. The first alias has no extension. The # second alias is named name + "_2", and so on. For the first n-2 aliases, # if they don't match they reference the next alias over. If the n-1st alias # doesn't match, it references the final setting (which is then evaluated # directly to determine the final value of the AND chain). actual = [name + "_" + str(i) for i in range(2, len(settings))] actual.append(settings[-1]) for i in range(1, len(settings)): native.alias( name = name if i == 1 else name + "_" + str(i), actual = select({ native.package_relative_label(settings[i - 1]): settings[i - 1], "//conditions:default": actual[i - 1], }), visibility = visibility if i == 1 else ["//visibility:private"], ) def _config_setting_and_group(name, settings, visibility): """ANDs multiple config_settings together. The core idea is to create a sequential chain of alias targets where each is select-resolved as follows: If alias n matches config_setting n, it resolves to alias n+1 (which evaluates config_setting n+1, and so on). Else it resolves to config_setting n, which doesn't match by definition. The only way to get a matching final result is if all config_settings match. """ # "//conditions:default" is automatically true so doesn't need checking. settings = _remove_default_condition(settings) # One config_setting input? Just alias directly to it. if len(settings) == 1: native.alias( name = name, actual = settings[0], visibility = visibility, ) return # We need n-1 aliases for n settings. The first alias has no extension. The # second alias is named name + "_2", and so on. For the first n-2 aliases, # if they match they reference the next alias over. If the n-1st alias matches, # it references the final setting (which is then evaluated directly to determine # the final value of the AND chain). actual = [name + "_" + str(i) for i in range(2, len(settings))] actual.append(settings[-1]) for i in range(1, len(settings)): native.alias( name = name if i == 1 else name + "_" + str(i), actual = select({ native.package_relative_label(settings[i - 1]): actual[i - 1], "//conditions:default": settings[i - 1], }), visibility = visibility if i == 1 else ["//visibility:private"], ) def _config_setting_always_true(name, visibility): """Creates a config_setting with the given name that's always true.""" native.alias( name = name, actual = Label(":always_true"), visibility = visibility, ) selects = struct( with_or = _with_or, with_or_dict = _with_or_dict, config_setting_group = _config_setting_group, ) bazel-skylib-1.9.1/lib/sets.bzl000066400000000000000000000013131517445036200163540ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module reexporting deprecated set algorithms.""" load(":new_sets.bzl", _sets = "sets") sets = _sets bazel-skylib-1.9.1/lib/shell.bzl000066400000000000000000000035131517445036200165110ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing shell utility functions.""" def _array_literal(iterable): """Creates a string from a sequence that can be used as a shell array. For example, `shell.array_literal(["a", "b", "c"])` would return the string `("a" "b" "c")`, which can be used in a shell script wherever an array literal is needed. Note that all elements in the array are quoted (using `shell.quote`) for safety, even if they do not need to be. Args: iterable: A sequence of elements. Elements that are not strings will be converted to strings first, by calling `str()`. Returns: A string that represents the sequence as a shell array; that is, parentheses containing the quoted elements. """ return "(" + " ".join([_quote(str(i)) for i in iterable]) + ")" def _quote(s): """Quotes the given string for use in a shell command. This function quotes the given string (in case it contains spaces or other shell metacharacters.) Args: s: The string to quote. Returns: A quoted version of the string that can be passed to a shell command. """ return "'" + s.replace("'", "'\\''") + "'" shell = struct( array_literal = _array_literal, quote = _quote, ) bazel-skylib-1.9.1/lib/structs.bzl000066400000000000000000000023611517445036200171110ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing functions that operate on structs.""" def _to_dict(s): """Converts a `struct` to a `dict`. Args: s: A `struct`. Returns: A `dict` whose keys and values are the same as the fields in `s`. The transformation is only applied to the struct's fields and not to any nested values. """ # to_json()/to_proto() are disabled by --incompatible_struct_has_no_methods # and will be removed entirely in a future Bazel release. return { key: getattr(s, key) for key in dir(s) if key != "to_json" and key != "to_proto" } structs = struct( to_dict = _to_dict, ) bazel-skylib-1.9.1/lib/subpackages.bzl000066400000000000000000000062441517445036200176760ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing common functions for working with native.subpackages() """ _SUBPACKAGES_SUPPORTED = hasattr(native, "subpackages") def _supported(): return _SUBPACKAGES_SUPPORTED def _check_supported(): if not _SUBPACKAGES_SUPPORTED: fail("native.subpackages not supported in this version of Bazel.") def _all(exclude = [], allow_empty = False, fully_qualified = True): """List all direct subpackages of the current package regardless of directory depth. The returned list contains all subpackages, but not subpackages of subpackages. Example: Assuming the following BUILD files exist: BUILD foo/BUILD foo/sub/BUILD bar/BUILD baz/deep/dir/BUILD If the current package is '//' all() will return ['//foo', '//bar', '//baz/deep/dir']. //foo/sub is not included because it is a direct subpackage of '//foo' not '//' NOTE: fail()s if native.subpackages() is not supported. Args: exclude: see native.subpackages(exclude) allow_empty: see native.subpackages(allow_empty) fully_qualified: It true return fully qualified Labels for subpackages, otherwise returns subpackage path relative to current package. Returns: A mutable sorted list containing all sub-packages of the current Bazel package. """ _check_supported() subs = native.subpackages(include = ["**"], exclude = exclude, allow_empty = allow_empty) if fully_qualified: return [_fully_qualified(s) for s in subs] return subs def _fully_qualified(relative_path): package_name = native.package_name() if package_name: return "//%s/%s" % (package_name, relative_path) return "//" + relative_path def _exists(relative_path): """Checks to see if relative_path is a direct subpackage of the current package. Example: BUILD foo/BUILD foo/sub/BUILD If the current package is '//' (the top-level BUILD file): subpackages.exists("foo") == True subpackages.exists("foo/sub") == False subpackages.exists("bar") == False NOTE: fail()s if native.subpackages() is not supported in the current Bazel version. Args: relative_path: a path to a subpackage to test, must not be an absolute Label. Returns: True if 'relative_path' is a subpackage of the current package. """ _check_supported() return relative_path in native.subpackages(include = [relative_path], allow_empty = True) subpackages = struct( all = _all, exists = _exists, supported = _supported, ) bazel-skylib-1.9.1/lib/types.bzl000066400000000000000000000073541517445036200165550ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing functions checking types.""" # create instance singletons to avoid unnecessary allocations _a_bool_type = type(True) _a_dict_type = type({}) _a_list_type = type([]) _a_string_type = type("") _a_tuple_type = type(()) _an_int_type = type(1) _a_depset_type = type(depset()) _a_struct_type = type(struct()) def _a_function(): pass _a_function_type = type(_a_function) def _is_list(v): """Returns True if v is an instance of a list. Args: v: The value whose type should be checked. Returns: True if v is an instance of a list, False otherwise. """ return type(v) == _a_list_type def _is_string(v): """Returns True if v is an instance of a string. Args: v: The value whose type should be checked. Returns: True if v is an instance of a string, False otherwise. """ return type(v) == _a_string_type def _is_bool(v): """Returns True if v is an instance of a bool. Args: v: The value whose type should be checked. Returns: True if v is an instance of a bool, False otherwise. """ return type(v) == _a_bool_type def _is_none(v): """Returns True if v has the type of None. Args: v: The value whose type should be checked. Returns: True if v is None, False otherwise. """ return type(v) == type(None) def _is_int(v): """Returns True if v is an instance of a signed integer. Args: v: The value whose type should be checked. Returns: True if v is an instance of a signed integer, False otherwise. """ return type(v) == _an_int_type def _is_tuple(v): """Returns True if v is an instance of a tuple. Args: v: The value whose type should be checked. Returns: True if v is an instance of a tuple, False otherwise. """ return type(v) == _a_tuple_type def _is_dict(v): """Returns True if v is an instance of a dict. Args: v: The value whose type should be checked. Returns: True if v is an instance of a dict, False otherwise. """ return type(v) == _a_dict_type def _is_function(v): """Returns True if v is an instance of a function. Args: v: The value whose type should be checked. Returns: True if v is an instance of a function, False otherwise. """ return type(v) == _a_function_type def _is_depset(v): """Returns True if v is an instance of a `depset`. Args: v: The value whose type should be checked. Returns: True if v is an instance of a `depset`, False otherwise. """ return type(v) == _a_depset_type def _is_set(v): """Returns True if v is a set created by sets.make(). Args: v: The value whose type should be checked. Returns: True if v was created by sets.make(), False otherwise. """ return type(v) == _a_struct_type and hasattr(v, "_values") and _is_dict(v._values) types = struct( is_list = _is_list, is_string = _is_string, is_bool = _is_bool, is_none = _is_none, is_int = _is_int, is_tuple = _is_tuple, is_dict = _is_dict, is_function = _is_function, is_depset = _is_depset, is_set = _is_set, ) bazel-skylib-1.9.1/lib/unittest.bzl000066400000000000000000000564421517445036200172720ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit testing support. Unlike most Skylib files, this exports four modules: * `unittest` contains functions to declare and define unit tests for ordinary Starlark functions; * `analysistest` contains functions to declare and define tests for analysis phase behavior of a rule, such as a given target's providers or registered actions; * `loadingtest` contains functions to declare and define tests for loading phase behavior, such as macros and `native.*`; * `asserts` contains the assertions used within tests. See https://bazel.build/extending/concepts for background about macros, rules, and the different phases of a build. """ load(":new_sets.bzl", new_sets = "sets") load(":partial.bzl", "partial") load(":types.bzl", "types") # The following function should only be called from WORKSPACE files and workspace macros. # buildifier: disable=unnamed-macro def register_unittest_toolchains(): """Registers the toolchains for unittest users.""" native.register_toolchains( "@bazel_skylib//toolchains/unittest:cmd_toolchain", "@bazel_skylib//toolchains/unittest:bash_toolchain", ) TOOLCHAIN_TYPE = "@bazel_skylib//toolchains/unittest:toolchain_type" _UnittestToolchainInfo = provider( doc = "Execution platform information for rules in the bazel_skylib repository.", fields = [ "file_ext", "success_templ", "failure_templ", "join_on", "escape_chars_with", "escape_other_chars_with", ], ) def _unittest_toolchain_impl(ctx): return [ platform_common.ToolchainInfo( unittest_toolchain_info = _UnittestToolchainInfo( file_ext = ctx.attr.file_ext, success_templ = ctx.attr.success_templ, failure_templ = ctx.attr.failure_templ, join_on = ctx.attr.join_on, escape_chars_with = ctx.attr.escape_chars_with, escape_other_chars_with = ctx.attr.escape_other_chars_with, ), ), ] unittest_toolchain = rule( implementation = _unittest_toolchain_impl, attrs = { "failure_templ": attr.string( mandatory = True, doc = ( "Test script template with a single `%s`. That " + "placeholder is replaced with the lines in the " + "failure message joined with the string " + "specified in `join_with`. The resulting script " + "should print the failure message and exit with " + "non-zero status." ), ), "file_ext": attr.string( mandatory = True, doc = ( "File extension for test script, including leading dot." ), ), "join_on": attr.string( mandatory = True, doc = ( "String used to join the lines in the failure " + "message before including the resulting string " + "in the script specified in `failure_templ`." ), ), "success_templ": attr.string( mandatory = True, doc = ( "Test script generated when the test passes. " + "Should exit with status 0." ), ), "escape_chars_with": attr.string_dict( doc = ( "Dictionary of characters that need escaping in " + "test failure message to prefix appended to escape " + "those characters. For example, " + '`{"%": "%", ">": "^"}` would replace `%` with ' + "`%%` and `>` with `^>` in the failure message " + "before that is included in `success_templ`." ), ), "escape_other_chars_with": attr.string( default = "", doc = ( "String to prefix every character in test failure " + "message which is not a key in `escape_chars_with` " + "before including that in `success_templ`. For " + 'example, `"\"` would prefix every character in ' + "the failure message (except those in the keys of " + "`escape_chars_with`) with `\\`." ), ), }, ) def _impl_function_name(impl): """Derives the name of the given rule implementation function. This can be used for better test feedback. Args: impl: the rule implementation function Returns: The name of the given function """ # Starlark currently stringifies a function as "", so we use # that knowledge to parse the "NAME" portion out. If this behavior ever # changes, we'll need to update this. # TODO(bazel-team): Expose a ._name field on functions to avoid this. impl_name = str(impl) impl_name = impl_name.partition("")[0] def _make(impl, attrs = {}, doc = "", toolchains = []): """Creates a unit test rule from its implementation function. Each unit test is defined in an implementation function that must then be associated with a rule so that a target can be built. This function handles the boilerplate to create and return a test rule and captures the implementation function's name so that it can be printed in test feedback. The optional `attrs` argument can be used to define dependencies for this test, in order to form unit tests of rules. The optional `toolchains` argument can be used to define toolchain dependencies for this test. An example of a unit test: ``` def _your_test(ctx): env = unittest.begin(ctx) # Assert statements go here return unittest.end(env) your_test = unittest.make(_your_test) ``` Recall that names of test rules must end in `_test`. Args: impl: The implementation function of the unit test. attrs: An optional dictionary to supplement the attrs passed to the unit test's `rule()` constructor. doc: A description of the rule that can be extracted by documentation generating tools. toolchains: An optional list to supplement the toolchains passed to the unit test's `rule()` constructor. Returns: A rule definition that should be stored in a global whose name ends in `_test`. """ attrs = dict(attrs) attrs["_impl_name"] = attr.string(default = _impl_function_name(impl)) return rule( impl, doc = doc, attrs = attrs, _skylark_testable = True, test = True, toolchains = toolchains + [TOOLCHAIN_TYPE], ) _ActionInfo = provider( doc = "Information relating to the target under test.", fields = ["actions", "bin_path"], ) def _action_retrieving_aspect_impl(target, ctx): return [ _ActionInfo( actions = target.actions, bin_path = ctx.bin_dir.path, ), ] _action_retrieving_aspect = aspect( attr_aspects = [], implementation = _action_retrieving_aspect_impl, ) # TODO(cparsons): Provide more full documentation on analysis testing in README. def _make_analysis_test( impl, expect_failure = False, attrs = {}, fragments = [], config_settings = {}, extra_target_under_test_aspects = [], doc = ""): """Creates an analysis test rule from its implementation function. An analysis test verifies the behavior of a "real" rule target by examining and asserting on the providers given by the real target. Each analysis test is defined in an implementation function that must then be associated with a rule so that a target can be built. This function handles the boilerplate to create and return a test rule and captures the implementation function's name so that it can be printed in test feedback. An example of an analysis test: ``` def _your_test(ctx): env = analysistest.begin(ctx) # Assert statements go here return analysistest.end(env) your_test = analysistest.make(_your_test) ``` Recall that names of test rules must end in `_test`. Args: impl: The implementation function of the unit test. expect_failure: If true, the analysis test will expect the target_under_test to fail. Assertions can be made on the underlying failure using asserts.expect_failure attrs: An optional dictionary to supplement the attrs passed to the unit test's `rule()` constructor. fragments: An optional list of fragment names that can be used to give rules access to language-specific parts of configuration. config_settings: A dictionary of configuration settings to change for the target under test and its dependencies. This may be used to essentially change 'build flags' for the target under test, and may thus be utilized to test multiple targets with different flags in a single build extra_target_under_test_aspects: An optional list of aspects to apply to the target_under_test in addition to those set up by default for the test harness itself. doc: A description of the rule that can be extracted by documentation generating tools. Returns: A rule definition that should be stored in a global whose name ends in `_test`. """ attrs = dict(attrs) attrs["_impl_name"] = attr.string(default = _impl_function_name(impl)) changed_settings = dict(config_settings) if expect_failure: changed_settings["//command_line_option:allow_analysis_failures"] = "True" target_attr_kwargs = {} if changed_settings: test_transition = analysis_test_transition( settings = changed_settings, ) target_attr_kwargs["cfg"] = test_transition attrs["target_under_test"] = attr.label( aspects = [_action_retrieving_aspect] + extra_target_under_test_aspects, mandatory = True, **target_attr_kwargs ) return rule( impl, doc = doc, attrs = attrs, fragments = fragments, test = True, toolchains = [TOOLCHAIN_TYPE], analysis_test = True, ) def _suite(name, *test_rules): """Defines a `test_suite` target that contains multiple tests. After defining your test rules in a `.bzl` file, you need to create targets from those rules so that `blaze test` can execute them. Doing this manually in a BUILD file would consist of listing each test in your `load` statement and then creating each target one by one. To reduce duplication, we recommend writing a macro in your `.bzl` file to instantiate all targets, and calling that macro from your BUILD file so you only have to load one symbol. You can use this function to create the targets and wrap them in a single test_suite target. If a test rule requires no arguments, you can simply list it as an argument. If you wish to supply attributes explicitly, you can do so using `partial.make()`. For instance, in your `.bzl` file, you could write: ``` def your_test_suite(): unittest.suite( "your_test_suite", your_test, your_other_test, partial.make(yet_another_test, timeout = "short"), ) ``` Then, in your `BUILD` file, simply load the macro and invoke it to have all of the targets created: ``` load("//path/to/your/package:tests.bzl", "your_test_suite") your_test_suite() ``` If you pass _N_ unit test rules to `unittest.suite`, _N_ + 1 targets will be created: a `test_suite` target named `${name}` (where `${name}` is the name argument passed in here) and targets named `${name}_test_${i}`, where `${i}` is the index of the test in the `test_rules` list, which is used to uniquely name each target. Args: name: The name of the `test_suite` target, and the prefix of all the test target names. *test_rules: A list of test rules defines by `unittest.test`. """ test_names = [] for index, test_rule in enumerate(test_rules): test_name = "%s_test_%d" % (name, index) if partial.is_instance(test_rule): partial.call(test_rule, name = test_name) else: test_rule(name = test_name) test_names.append(test_name) native.test_suite( name = name, tests = [":%s" % t for t in test_names], ) def _begin(ctx): """Begins a unit test. This should be the first function called in a unit test implementation function. It initializes a "test environment" that is used to collect assertion failures so that they can be reported and logged at the end of the test. Args: ctx: The Starlark context. Pass the implementation function's `ctx` argument in verbatim. Returns: A test environment struct that must be passed to assertions and finally to `unittest.end`. Do not rely on internal details about the fields in this struct as it may change. """ return struct(ctx = ctx, failures = []) def _begin_analysis_test(ctx): """Begins an analysis test. This should be the first function called in an analysis test implementation function. It initializes a "test environment" that is used to collect assertion failures so that they can be reported and logged at the end of the test. Args: ctx: The Starlark context. Pass the implementation function's `ctx` argument in verbatim. Returns: A test environment struct that must be passed to assertions and finally to `analysistest.end`. Do not rely on internal details about the fields in this struct as it may change. """ return struct(ctx = ctx, failures = []) def _end_analysis_test(env): """Ends an analysis test and logs the results. This must be called and returned at the end of an analysis test implementation function so that the results are reported. Args: env: The test environment returned by `analysistest.begin`. Returns: A list of providers needed to automatically register the analysis test result. """ return [AnalysisTestResultInfo( success = (len(env.failures) == 0), message = "\n".join(env.failures), )] def _end(env): """Ends a unit test and logs the results. This must be called and returned at the end of a unit test implementation function so that the results are reported. Args: env: The test environment returned by `unittest.begin`. Returns: A list of providers needed to automatically register the test result. """ tc = env.ctx.toolchains[TOOLCHAIN_TYPE].unittest_toolchain_info testbin = env.ctx.actions.declare_file(env.ctx.label.name + tc.file_ext) if env.failures: failure_message_lines = "\n".join(env.failures).split("\n") escaped_failure_message_lines = [ "".join([ tc.escape_chars_with.get(c, tc.escape_other_chars_with) + c for c in line.elems() ]) for line in failure_message_lines ] cmd = tc.failure_templ % tc.join_on.join(escaped_failure_message_lines) else: cmd = tc.success_templ env.ctx.actions.write( output = testbin, content = cmd, is_executable = True, ) return [DefaultInfo(executable = testbin)] def _fail(env, msg): """Unconditionally causes the current test to fail. Args: env: The test environment returned by `unittest.begin`. msg: The message to log describing the failure. """ full_msg = "In test %s: %s" % (env.ctx.attr._impl_name, msg) # There isn't a better way to output the message in Starlark, so use print. # buildifier: disable=print print(full_msg) env.failures.append(full_msg) def _assert_true( env, condition, msg = "Expected condition to be true, but was false."): """Asserts that the given `condition` is true. Args: env: The test environment returned by `unittest.begin`. condition: A value that will be evaluated in a Boolean context. msg: An optional message that will be printed that describes the failure. If omitted, a default will be used. """ if not condition: _fail(env, msg) def _assert_false( env, condition, msg = "Expected condition to be false, but was true."): """Asserts that the given `condition` is false. Args: env: The test environment returned by `unittest.begin`. condition: A value that will be evaluated in a Boolean context. msg: An optional message that will be printed that describes the failure. If omitted, a default will be used. """ if condition: _fail(env, msg) def _assert_equals(env, expected, actual, msg = None): """Asserts that the given `expected` and `actual` values are equal. Args: env: The test environment returned by `unittest.begin`. expected: The expected value of some computation. actual: The actual value returned by some computation. msg: An optional message that will be printed that describes the failure. If omitted, a default will be used. """ if expected != actual: expectation_msg = 'Expected "%s", but got "%s"' % (expected, actual) if msg: full_msg = "%s (%s)" % (msg, expectation_msg) else: full_msg = expectation_msg _fail(env, full_msg) def _assert_set_equals(env, expected, actual, msg = None): """Asserts that the given `expected` and `actual` sets are equal. Args: env: The test environment returned by `unittest.begin`. expected: The expected set resulting from some computation. actual: The actual set returned by some computation. msg: An optional message that will be printed that describes the failure. If omitted, a default will be used. """ if not new_sets.is_equal(expected, actual): missing = new_sets.difference(expected, actual) unexpected = new_sets.difference(actual, expected) expectation_msg = "Expected %s, but got %s" % (new_sets.str(expected), new_sets.str(actual)) if new_sets.length(missing) > 0: expectation_msg += ", missing are %s" % (new_sets.str(missing)) if new_sets.length(unexpected) > 0: expectation_msg += ", unexpected are %s" % (new_sets.str(unexpected)) if msg: full_msg = "%s (%s)" % (msg, expectation_msg) else: full_msg = expectation_msg _fail(env, full_msg) _assert_new_set_equals = _assert_set_equals def _expect_failure(env, expected_failure_msg = ""): """Asserts that the target under test has failed with a given error message. This requires that the analysis test is created with `analysistest.make()` and `expect_failures = True` is specified. Args: env: The test environment returned by `analysistest.begin`. expected_failure_msg: The error message to expect as a result of analysis failures. """ dep = _target_under_test(env) if AnalysisFailureInfo in dep: actual_errors = "" for cause in dep[AnalysisFailureInfo].causes.to_list(): actual_errors += cause.message + "\n" if actual_errors.find(expected_failure_msg) < 0: expectation_msg = "Expected errors to contain '%s' but did not. " % expected_failure_msg expectation_msg += "Actual errors:%s" % actual_errors _fail(env, expectation_msg) else: _fail(env, "Expected failure of target_under_test, but found success") def _target_actions(env): """Returns a list of actions registered by the target under test. Args: env: The test environment returned by `analysistest.begin`. Returns: A list of actions registered by the target under test """ # Validate? return _target_under_test(env)[_ActionInfo].actions def _target_bin_dir_path(env): """Returns ctx.bin_dir.path for the target under test. Args: env: The test environment returned by `analysistest.begin`. Returns: Output bin dir path string. """ return _target_under_test(env)[_ActionInfo].bin_path def _target_under_test(env): """Returns the target under test. Args: env: The test environment returned by `analysistest.begin`. Returns: The target under test. """ result = getattr(env.ctx.attr, "target_under_test") if types.is_list(result): if result: return result[0] else: fail("test rule does not have a target_under_test") return result def _loading_test_impl(ctx): tc = ctx.toolchains[TOOLCHAIN_TYPE].unittest_toolchain_info content = tc.success_templ if ctx.attr.failure_message: content = tc.failure_templ % ctx.attr.failure_message testbin = ctx.actions.declare_file("loading_test_" + ctx.label.name + tc.file_ext) ctx.actions.write( output = testbin, content = content, is_executable = True, ) return [DefaultInfo(executable = testbin)] _loading_test = rule( implementation = _loading_test_impl, attrs = { "failure_message": attr.string(), }, toolchains = [TOOLCHAIN_TYPE], test = True, ) def _loading_make(name): """Creates a loading phase test environment and test_suite. Args: name: name of the suite of tests to create Returns: loading phase environment passed to other loadingtest functions """ native.test_suite( name = name + "_tests", tags = [name + "_test_case"], ) return struct(name = name) def _loading_assert_equals(env, test_case, expected, actual): """Creates a test case for asserting state at LOADING phase. Args: env: Loading test env created from loadingtest.make test_case: Name of the test case expected: Expected value to test actual: Actual value received. Returns: None, creates test case """ msg = None if expected != actual: msg = 'Expected "%s", but got "%s"' % (expected, actual) _loading_test( name = "%s_%s" % (env.name, test_case), failure_message = msg, tags = [env.name + "_test_case"], ) asserts = struct( expect_failure = _expect_failure, equals = _assert_equals, false = _assert_false, set_equals = _assert_set_equals, new_set_equals = _assert_new_set_equals, true = _assert_true, ) unittest = struct( make = _make, suite = _suite, begin = _begin, end = _end, fail = _fail, ) analysistest = struct( make = _make_analysis_test, begin = _begin_analysis_test, end = _end_analysis_test, fail = _fail, target_actions = _target_actions, target_bin_dir_path = _target_bin_dir_path, target_under_test = _target_under_test, ) loadingtest = struct( make = _loading_make, equals = _loading_assert_equals, ) bazel-skylib-1.9.1/lib/versions.bzl000066400000000000000000000103451517445036200172530ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing functions for checking Bazel versions.""" def _get_bazel_version(): """Returns the current Bazel version""" return native.bazel_version def _extract_version_number(bazel_version): """Extracts the semantic version number from a version string Args: bazel_version: the version string that begins with the semantic version e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash. Returns: The semantic version string, like "1.2.3". """ for i in range(len(bazel_version)): c = bazel_version[i] if not (c.isdigit() or c == "."): return bazel_version[:i] return bazel_version # Parse the bazel version string from `native.bazel_version`. # e.g. # "0.10.0rc1 abc123d" => (0, 10, 0) # "0.3.0" => (0, 3, 0) def _parse_bazel_version(bazel_version): """Parses a version string into a 3-tuple of ints int tuples can be compared directly using binary operators (<, >). For a development build of Bazel, this returns an unspecified version tuple that compares higher than any released version. Args: bazel_version: the Bazel version string Returns: An int 3-tuple of a (major, minor, patch) version. """ version = _extract_version_number(bazel_version) if not version: return (999999, 999999, 999999) return tuple([int(n) for n in version.split(".")]) def _is_at_most(threshold, version): """Check that a version is lower or equals to a threshold. Args: threshold: the maximum version string version: the version string to be compared to the threshold Returns: True if version <= threshold. """ return _parse_bazel_version(version) <= _parse_bazel_version(threshold) def _is_at_least(threshold, version): """Check that a version is higher or equals to a threshold. Args: threshold: the minimum version string version: the version string to be compared to the threshold Returns: True if version >= threshold. """ return _parse_bazel_version(version) >= _parse_bazel_version(threshold) def _check_bazel_version(minimum_bazel_version, maximum_bazel_version = None, bazel_version = None): """Check that the version of Bazel is valid within the specified range. Args: minimum_bazel_version: minimum version of Bazel expected maximum_bazel_version: maximum version of Bazel expected bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version """ if not bazel_version: if "bazel_version" not in dir(native): fail("Current Bazel version is lower than 0.2.1; expected at least {}".format( minimum_bazel_version, )) elif not native.bazel_version: # Using a non-release version, assume it is good. return else: bazel_version = native.bazel_version if not _is_at_least( threshold = minimum_bazel_version, version = bazel_version, ): fail("Current Bazel version is {}; expected at least {}".format( bazel_version, minimum_bazel_version, )) if maximum_bazel_version: if not _is_at_most( threshold = maximum_bazel_version, version = bazel_version, ): fail("Current Bazel version is {}; expected at most {}".format( bazel_version, maximum_bazel_version, )) pass versions = struct( get = _get_bazel_version, parse = _parse_bazel_version, check = _check_bazel_version, is_at_most = _is_at_most, is_at_least = _is_at_least, ) bazel-skylib-1.9.1/rules/000077500000000000000000000000001517445036200152535ustar00rootroot00000000000000bazel-skylib-1.9.1/rules/BUILD000066400000000000000000000034201517445036200160340ustar00rootroot00000000000000load("//:bzl_library.bzl", "bzl_library") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) bzl_library( name = "analysis_test", srcs = ["analysis_test.bzl"], ) bzl_library( name = "build_test", srcs = ["build_test.bzl"], deps = ["//lib:new_sets"], ) bzl_library( name = "copy_file", srcs = ["copy_file.bzl"], deps = ["//rules/private:copy_file_private"], ) bzl_library( name = "copy_directory", srcs = ["copy_directory.bzl"], deps = ["//rules/private:copy_directory_private"], ) bzl_library( name = "write_file", srcs = ["write_file.bzl"], deps = ["//rules/private:write_file_private"], ) bzl_library( name = "diff_test", srcs = ["diff_test.bzl"], deps = ["//lib:shell"], ) bzl_library( name = "expand_template", srcs = ["expand_template.bzl"], ) bzl_library( name = "native_binary", srcs = ["native_binary.bzl"], ) bzl_library( name = "run_binary", srcs = ["run_binary.bzl"], deps = ["//lib:dicts"], ) bzl_library( name = "common_settings", srcs = ["common_settings.bzl"], ) filegroup( name = "test_deps", testonly = True, srcs = [ "BUILD", "//rules/private:test_deps", ] + glob(["*.bzl"]), visibility = ["//:__subpackages__"], # Needs skylib's root BUILD file for default_applicable_licenses ) # The files needed for distribution filegroup( name = "distribution", srcs = [ "BUILD", ] + glob(["*.bzl"]), visibility = [ "//:__pkg__", ], ) # export bzl files for the documentation exports_files( glob(["*.bzl"]), visibility = ["//:__subpackages__"], ) bzl_library( name = "select_file", srcs = ["select_file.bzl"], ) bazel-skylib-1.9.1/rules/analysis_test.bzl000066400000000000000000000042041517445036200206460ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A test verifying other targets can be successfully analyzed as part of a `bazel test`""" def _analysis_test_impl(ctx): """Implementation function for analysis_test. """ _ignore = [ctx] # @unused return [AnalysisTestResultInfo( success = True, message = "All targets succeeded analysis", )] analysis_test = rule( _analysis_test_impl, attrs = {"targets": attr.label_list(mandatory = True)}, test = True, analysis_test = True, doc = """Test rule checking that other targets can be successfully analyzed. This rule essentially verifies that all targets under `targets` would generate no errors when analyzed with `bazel build [targets] --nobuild`. Action success/failure for the targets and their transitive dependencies are not verified. An analysis test simply ensures that each target in the transitive dependencies propagate providers appropriately and register actions for their outputs appropriately. NOTE: If the targets fail to analyze, instead of the analysis_test failing, the analysis_test will fail to build. Ideally, it would instead result in a test failure. This is a current infrastructure limitation that may be fixed in the future. Typical usage: load("@bazel_skylib//rules:analysis_test.bzl", "analysis_test") analysis_test( name = "my_analysis_test", targets = [ "//some/package:rule", ], ) Args: name: The name of the test rule. targets: A list of targets to ensure build.""", ) bazel-skylib-1.9.1/rules/build_test.bzl000066400000000000000000000103731517445036200201260ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A test verifying other targets build as part of a `bazel test`""" load("//lib:new_sets.bzl", "sets") def _empty_test_impl(ctx): is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) extension = ".bat" if is_windows else ".sh" content = "exit 0" if is_windows else "#!/usr/bin/env bash\nexit 0" executable = ctx.actions.declare_file(ctx.label.name + extension) ctx.actions.write( output = executable, is_executable = True, content = content, ) return [DefaultInfo( files = depset([executable]), executable = executable, runfiles = ctx.runfiles(files = ctx.files.data), )] _empty_test = rule( implementation = _empty_test_impl, attrs = { "data": attr.label_list(allow_files = True), "_windows_constraint": attr.label(default = "@platforms//os:windows"), }, test = True, ) _GENRULE_ATTRS = [ "compatible_with", "exec_compatible_with", "restricted_to", "tags", "target_compatible_with", ] def build_test(name, targets, **kwargs): """Test rule checking that other targets build. This works not by an instance of this test failing, but instead by the targets it depends on failing to build, and hence failing the attempt to run this test. Typical usage: ``` load("@bazel_skylib//rules:build_test.bzl", "build_test") build_test( name = "my_build_test", targets = [ "//some/package:rule", ], ) ``` Args: name: The name of the test rule. targets: A list of targets to ensure build. **kwargs: The [common attributes for tests](https://bazel.build/reference/be/common-definitions#common-attributes-tests). """ if len(targets) == 0: fail("targets must be non-empty", "targets") if kwargs.get("data", None): fail("data is not supported on a build_test()", "data") # Remove any duplicate test targets. targets = sets.to_list(sets.make(targets)) # Use a genrule to ensure the targets are built (works because it forces # the outputs of the other rules on as data for the genrule) # Split into batches to hopefully avoid things becoming so large they are # too much for a remote execution set up. batch_size = max(1, len(targets) // 100) # Pull a few args over from the test to the genrule. genrule_args = {k: kwargs.get(k) for k in _GENRULE_ATTRS if k in kwargs} # Only the test target should be used to determine whether or not the deps # are built. Tagging the genrule targets as manual accomplishes this by # preventing them from being picked up by recursive build patterns (`//...`). genrule_tags = genrule_args.pop("tags", []) if "manual" not in genrule_tags: genrule_tags = genrule_tags + ["manual"] # Pass an output from the genrules as data to a shell test to bundle # it all up in a test. test_data = [] for idx, batch in enumerate([targets[i:i + batch_size] for i in range(0, len(targets), batch_size)]): full_name = "{name}_{idx}__deps".format(name = name, idx = idx) test_data.append(full_name) native.genrule( name = full_name, srcs = batch, outs = [full_name + ".out"], testonly = 1, visibility = ["//visibility:private"], cmd = "touch $@", cmd_bat = "type nul > $@", tags = genrule_tags, **genrule_args ) _empty_test( name = name, data = test_data, size = kwargs.pop("size", "small"), # Default to small for test size **kwargs ) bazel-skylib-1.9.1/rules/common_settings.bzl000066400000000000000000000145021517445036200211760ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Common build setting rules These rules return a BuildSettingInfo with the value of the build setting. For label-typed settings, use the native label_flag and label_setting rules. More documentation on how to use build settings at https://bazel.build/extending/config#user-defined-build-settings """ BuildSettingInfo = provider( doc = "A singleton provider that contains the raw value of a build setting", fields = { "value": "The value of the build setting in the current configuration. " + "This value may come from the command line or an upstream transition, " + "or else it will be the build setting's default.", }, ) _MAKE_VARIABLE_ATTR = attr.string( doc = "If set, the build setting's value will be available as a Make variable with this " + "name in the attributes of rules that list this build setting in their 'toolchains' " + "attribute.", ) _SCOPE_ATTR = attr.string( doc = "The scope indicates where a flag can propagate to", default = "target", ) def _is_valid_make_variable_char(c): # Restrict make variable names for consistency with predefined ones. There are no enforced # restrictions on make variable names, but when they contain e.g. spaces or braces, they # aren't expanded by e.g. cc_binary. return c == "_" or c.isdigit() or (c.isalpha() and c.isupper()) def _get_template_variable_info(ctx): make_variable = getattr(ctx.attr, "make_variable", None) if not make_variable: return [] if not all([_is_valid_make_variable_char(c) for c in make_variable.elems()]): fail("Error setting " + _no_at_str(ctx.label) + ": invalid make variable name '" + make_variable + "'. Make variable names may only contain uppercase letters, digits, and underscores.") return [ platform_common.TemplateVariableInfo({ make_variable: str(ctx.build_setting_value), }), ] def _impl(ctx): return [ BuildSettingInfo(value = ctx.build_setting_value), ] + _get_template_variable_info(ctx) int_flag = rule( implementation = _impl, build_setting = config.int(flag = True), attrs = { "make_variable": _MAKE_VARIABLE_ATTR, "scope": _SCOPE_ATTR, }, doc = "An int-typed build setting that can be set on the command line", ) int_setting = rule( implementation = _impl, build_setting = config.int(), attrs = { "make_variable": _MAKE_VARIABLE_ATTR, "scope": _SCOPE_ATTR, }, doc = "An int-typed build setting that cannot be set on the command line", ) bool_flag = rule( implementation = _impl, build_setting = config.bool(flag = True), attrs = { "scope": _SCOPE_ATTR, }, doc = "A bool-typed build setting that can be set on the command line", ) bool_setting = rule( implementation = _impl, build_setting = config.bool(), attrs = { "scope": _SCOPE_ATTR, }, doc = "A bool-typed build setting that cannot be set on the command line", ) string_list_flag = rule( implementation = _impl, build_setting = config.string_list(flag = True), attrs = { "scope": _SCOPE_ATTR, }, doc = "A string list-typed build setting that can be set on the command line", ) def _repeatable_string_flag_impl(ctx): return BuildSettingInfo(value = ctx.build_setting_value) repeatable_string_flag = rule( implementation = _repeatable_string_flag_impl, build_setting = config.string_list( flag = True, repeatable = True, ), attrs = { "scope": _SCOPE_ATTR, }, doc = "A build setting that accepts one or more string-typed settings on the command line, with the values concatenated into a single string list; for example, `--//my/setting=foo` `--//my/setting=bar` will be parsed as `['foo', 'bar']`. Contrast with `string_list_flag`", ) string_list_setting = rule( implementation = _impl, build_setting = config.string_list(), attrs = { "scope": _SCOPE_ATTR, }, doc = "A string list-typed build setting which expects its value on the command line to be given in comma-separated format; for example, `--//my/setting=foo,bar` will be parsed as `['foo', 'bar']`. Contrast with `repeatable_string_flag`", ) def _no_at_str(label): """Strips any leading '@'s for labels in the main repo, so that the error string is more friendly.""" s = str(label) # buildifier: disable=canonical-repository if s.startswith("@@//"): return s[2:] if s.startswith("@//"): return s[1:] return s def _string_impl(ctx): allowed_values = ctx.attr.values value = ctx.build_setting_value if len(allowed_values) == 0 or value in ctx.attr.values: return [BuildSettingInfo(value = value)] + _get_template_variable_info(ctx) else: fail("Error setting " + _no_at_str(ctx.label) + ": invalid value '" + value + "'. Allowed values are " + str(allowed_values)) string_flag = rule( implementation = _string_impl, build_setting = config.string(flag = True), attrs = { "values": attr.string_list( doc = "The list of allowed values for this setting. An error is raised if any other value is given.", ), "make_variable": _MAKE_VARIABLE_ATTR, "scope": _SCOPE_ATTR, }, doc = "A string-typed build setting that can be set on the command line", ) string_setting = rule( implementation = _string_impl, build_setting = config.string(), attrs = { "values": attr.string_list( doc = "The list of allowed values for this setting. An error is raised if any other value is given.", ), "make_variable": _MAKE_VARIABLE_ATTR, "scope": _SCOPE_ATTR, }, doc = "A string-typed build setting that cannot be set on the command line", ) bazel-skylib-1.9.1/rules/copy_directory.bzl000066400000000000000000000017571517445036200210340ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A rule that copies a directory to another place. The rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). """ load( "//rules/private:copy_directory_private.bzl", _copy_directory = "copy_directory", _copy_directory_action = "copy_directory_action", ) copy_directory = _copy_directory copy_directory_action = _copy_directory_action bazel-skylib-1.9.1/rules/copy_file.bzl000066400000000000000000000020041517445036200177310ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A rule that copies a file to another place. native.genrule() is sometimes used to copy files (often wishing to rename them). The 'copy_file' rule does this with a simpler interface than genrule. The rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). """ load( "//rules/private:copy_file_private.bzl", _copy_file = "copy_file", ) copy_file = _copy_file bazel-skylib-1.9.1/rules/diff_test.bzl000066400000000000000000000123501517445036200177340ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A test rule that compares two binary files. The rule uses a Bash command (diff) on Linux/macOS/non-Windows, and a cmd.exe command (fc.exe) on Windows (no Bash is required). """ load("//lib:shell.bzl", "shell") def _runfiles_path(f): if f.root.path: return f.path[len(f.root.path) + 1:] # generated file else: return f.path # source file def _diff_test_impl(ctx): if ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]): test_bin = ctx.actions.declare_file(ctx.label.name + "-test.bat") ctx.actions.write( output = test_bin, content = """@rem Generated by diff_test.bzl, do not edit. @echo off SETLOCAL ENABLEEXTENSIONS SETLOCAL ENABLEDELAYEDEXPANSION set MF=%RUNFILES_MANIFEST_FILE:/=\\% set PATH=%SYSTEMROOT%\\system32 set F1={file1} set F2={file2} if "!F1:~0,9!" equ "external/" (set F1=!F1:~9!) else (set F1=!TEST_WORKSPACE!/!F1!) if "!F2:~0,9!" equ "external/" (set F2=!F2:~9!) else (set F2=!TEST_WORKSPACE!/!F2!) for /F "tokens=2* usebackq" %%i in (`findstr.exe /l /c:"!F1! " "%MF%"`) do ( set RF1=%%i set RF1=!RF1:/=\\! ) if "!RF1!" equ "" ( if "%RUNFILES_MANIFEST_ONLY%" neq "1" if exist "%RUNFILES_DIR%\\%F1%" ( set RF1="%RUNFILES_DIR%\\%F1%" ) else ( if exist "{file1}" ( set RF1="{file1}" ) ) if "!RF1!" neq "" ( set RF1=!RF1:/=\\! ) else ( echo>&2 ERROR: !F1! not found exit /b 1 ) ) for /F "tokens=2* usebackq" %%i in (`findstr.exe /l /c:"!F2! " "%MF%"`) do ( set RF2=%%i set RF2=!RF2:/=\\! ) if "!RF2!" equ "" ( if "%RUNFILES_MANIFEST_ONLY%" neq "1" if exist "%RUNFILES_DIR%\\%F2%" ( set RF2="%RUNFILES_DIR%\\%F2%" ) else ( if exist "{file2}" ( set RF2="{file2}" ) ) if "!RF2!" neq "" ( set RF2=!RF2:/=\\! ) else ( echo>&2 ERROR: !F2! not found exit /b 1 ) ) fc.exe 2>NUL 1>NUL /B "!RF1!" "!RF2!" if %ERRORLEVEL% neq 0 ( if %ERRORLEVEL% equ 1 ( echo>&2 FAIL: files "{file1}" and "{file2}" differ. {fail_msg} exit /b 1 ) else ( fc.exe /B "!RF1!" "!RF2!" exit /b %errorlevel% ) ) """.format( # TODO(arostovtsev): use shell.escape_for_bat when https://github.com/bazelbuild/bazel-skylib/pull/363 is merged fail_msg = ctx.attr.failure_message, file1 = _runfiles_path(ctx.file.file1), file2 = _runfiles_path(ctx.file.file2), ), is_executable = True, ) else: test_bin = ctx.actions.declare_file(ctx.label.name + "-test.sh") ctx.actions.write( output = test_bin, content = r"""#!/usr/bin/env bash set -euo pipefail F1="{file1}" F2="{file2}" [[ "$F1" =~ ^external/* ]] && F1="${{F1#external/}}" || F1="$TEST_WORKSPACE/$F1" [[ "$F2" =~ ^external/* ]] && F2="${{F2#external/}}" || F2="$TEST_WORKSPACE/$F2" if [[ -d "${{RUNFILES_DIR:-/dev/null}}" && "${{RUNFILES_MANIFEST_ONLY:-}}" != 1 ]]; then RF1="$RUNFILES_DIR/$F1" RF2="$RUNFILES_DIR/$F2" elif [[ -f "${{RUNFILES_MANIFEST_FILE:-/dev/null}}" ]]; then RF1="$(grep -F -m1 "$F1 " "$RUNFILES_MANIFEST_FILE" | sed 's/^[^ ]* //')" RF2="$(grep -F -m1 "$F2 " "$RUNFILES_MANIFEST_FILE" | sed 's/^[^ ]* //')" elif [[ -f "$TEST_SRCDIR/$F1" && -f "$TEST_SRCDIR/$F2" ]]; then RF1="$TEST_SRCDIR/$F1" RF2="$TEST_SRCDIR/$F2" else echo >&2 "ERROR: could not find \"{file1}\" and \"{file2}\"" exit 1 fi if ! diff "$RF1" "$RF2"; then echo >&2 "FAIL: files \"{file1}\" and \"{file2}\" differ. "{fail_msg} exit 1 fi """.format( fail_msg = shell.quote(ctx.attr.failure_message), file1 = _runfiles_path(ctx.file.file1), file2 = _runfiles_path(ctx.file.file2), ), is_executable = True, ) return DefaultInfo( executable = test_bin, files = depset(direct = [test_bin]), runfiles = ctx.runfiles(files = [test_bin, ctx.file.file1, ctx.file.file2]), ) diff_test = rule( doc = """A test that compares two files. The test succeeds if the files' contents match. """, attrs = { "file1": attr.label( doc = "Label of the file to compare to `file2`.", allow_single_file = True, mandatory = True, ), "file2": attr.label( doc = "Label of the file to compare to `file1`.", allow_single_file = True, mandatory = True, ), "failure_message": attr.string( doc = "Additional message to log if the files' contents do not match.", ), "_windows_constraint": attr.label(default = "@platforms//os:windows"), }, test = True, implementation = _diff_test_impl, ) bazel-skylib-1.9.1/rules/directory/000077500000000000000000000000001517445036200172575ustar00rootroot00000000000000bazel-skylib-1.9.1/rules/directory/BUILD000066400000000000000000000021531517445036200200420ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) # export bzl files for the documentation exports_files( glob(["*.bzl"]), visibility = ["//:__subpackages__"], ) bzl_library( name = "directory", srcs = ["directory.bzl"], visibility = ["//visibility:public"], deps = [ ":providers", "//lib:paths", ], ) bzl_library( name = "glob", srcs = ["glob.bzl"], visibility = ["//visibility:public"], deps = [ ":providers", ], ) bzl_library( name = "providers", srcs = ["providers.bzl"], visibility = ["//visibility:public"], deps = [ "//rules/directory/private:glob", "//rules/directory/private:paths", ], ) bzl_library( name = "subdirectory", srcs = ["subdirectory.bzl"], visibility = ["//visibility:public"], deps = [ ":providers", ], ) # The files needed for distribution filegroup( name = "distribution", srcs = [ "BUILD", ] + glob(["*.bzl"]), visibility = [ "//:__pkg__", ], ) bazel-skylib-1.9.1/rules/directory/directory.bzl000066400000000000000000000121711517445036200217760ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing rules to create metadata about directories.""" load("//lib:paths.bzl", "paths") load(":providers.bzl", "DirectoryInfo", "create_directory_info") def _prefix_match(f, prefixes): for prefix in prefixes: if f.path.startswith(prefix): return prefix fail("Expected {path} to start with one of {prefixes}".format(path = f.path, prefixes = list(prefixes))) def _choose_path(prefixes): filtered = {prefix: example for prefix, example in prefixes.items() if example} if len(filtered) > 1: examples = list(filtered.values()) fail( "Your sources contain {} and {}.\n\n".format( examples[0], examples[1], ) + "Having both source and generated files in a single directory is " + "unsupported, since they will appear in two different " + "directories in the bazel execroot. You may want to consider " + "splitting your directory into one for source files and one for " + "generated files.", ) # If there's no entries, use the source path (it's always first in the dict) return list(filtered if filtered else prefixes)[0][:-1] def _directory_impl(ctx): # Declare a generated file so that we can get the path to generated files. f = ctx.actions.declare_file("_directory_rule_" + ctx.label.name) ctx.actions.write(f, "") source_prefix = ctx.label.package if ctx.label.workspace_root: source_prefix = ctx.label.workspace_root + "/" + source_prefix source_prefix = source_prefix.rstrip("/") + "/" # Mapping of a prefix to an arbitrary (but deterministic) file matching that path. # The arbitrary file is used to present error messages if we have both generated files and source files. prefixes = { source_prefix: None, f.dirname + "/": None, } root_metadata = struct( directories = {}, files = [], relative = "", human_readable = str(ctx.label), ) topological = [root_metadata] for src in ctx.files.srcs: prefix = _prefix_match(src, prefixes) prefixes[prefix] = src relative = src.path[len(prefix):].split("/") current_path = root_metadata for dirname in relative[:-1]: if dirname not in current_path.directories: dir_metadata = struct( directories = {}, files = [], relative = paths.join(current_path.relative, dirname), human_readable = paths.join(current_path.human_readable, dirname), ) current_path.directories[dirname] = dir_metadata topological.append(dir_metadata) current_path = current_path.directories[dirname] current_path.files.append(src) # The output DirectoryInfos. Key them by something arbitrary but unique. # In this case, we choose relative. out = {} root_path = _choose_path(prefixes) # By doing it in reversed topological order, we ensure that a child is # created before its parents. This means that when we create a provider, # we can always guarantee that a depset of its children will work. for dir_metadata in reversed(topological): directories = { dirname: out[subdir_metadata.relative] for dirname, subdir_metadata in sorted(dir_metadata.directories.items()) } entries = { file.basename: file for file in dir_metadata.files } entries.update(directories) transitive_files = depset( direct = sorted(dir_metadata.files, key = lambda f: f.basename), transitive = [ d.transitive_files for d in directories.values() ], order = "preorder", ) directory = create_directory_info( entries = {k: v for k, v in sorted(entries.items())}, transitive_files = transitive_files, path = paths.join(root_path, dir_metadata.relative) if dir_metadata.relative else root_path, human_readable = dir_metadata.human_readable, ) out[dir_metadata.relative] = directory root_directory = out[root_metadata.relative] return [ root_directory, DefaultInfo(files = root_directory.transitive_files), ] directory = rule( implementation = _directory_impl, attrs = { "srcs": attr.label_list( allow_files = True, ), }, provides = [DirectoryInfo], ) bazel-skylib-1.9.1/rules/directory/glob.bzl000066400000000000000000000044261517445036200207210ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules to filter files from a directory.""" load(":providers.bzl", "DirectoryInfo") def _directory_glob_impl(ctx): directory = ctx.attr.directory[DirectoryInfo] srcs = directory.glob( ctx.attr.srcs, exclude = ctx.attr.exclude, allow_empty = ctx.attr.allow_empty, ) data = directory.glob( ctx.attr.data, exclude = ctx.attr.exclude, allow_empty = ctx.attr.allow_empty, ) return DefaultInfo( files = srcs, runfiles = ctx.runfiles(transitive_files = depset(transitive = [srcs, data])), ) directory_glob = rule( implementation = _directory_glob_impl, attrs = { "allow_empty": attr.bool( doc = "If true, allows globs to not match anything.", ), "data": attr.string_list( doc = """A list of globs to files within the directory to put in the runfiles. For example, `data = ["foo/**"]` would collect all files contained within `/foo` into the runfiles.""", ), "directory": attr.label(providers = [DirectoryInfo], mandatory = True), "exclude": attr.string_list( doc = "A list of globs to files within the directory to exclude from the files and runfiles.", ), "srcs": attr.string_list( doc = """A list of globs to files within the directory to put in the files. For example, `srcs = ["foo/**"]` would collect the file at `/foo` into the files.""", ), }, doc = """globs files from a directory by relative path. Usage: ``` directory_glob( name = "foo", directory = ":directory", srcs = ["foo/bar"], data = ["foo/**"], exclude = ["foo/**/*.h"] ) ``` """, ) bazel-skylib-1.9.1/rules/directory/private/000077500000000000000000000000001517445036200207315ustar00rootroot00000000000000bazel-skylib-1.9.1/rules/directory/private/BUILD000066400000000000000000000012661517445036200215200ustar00rootroot00000000000000load("@bazel_skylib//:bzl_library.bzl", "bzl_library") package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) # export bzl files for the documentation exports_files( glob(["*.bzl"]), visibility = ["//:__subpackages__"], ) bzl_library( name = "glob", srcs = ["glob.bzl"], visibility = ["//rules/directory:__pkg__"], ) bzl_library( name = "paths", srcs = ["paths.bzl"], visibility = ["//rules/directory:__pkg__"], deps = [ "//lib:paths", ], ) # The files needed for distribution filegroup( name = "distribution", srcs = [ "BUILD", ] + glob(["*.bzl"]), visibility = [ "//:__pkg__", ], ) bazel-skylib-1.9.1/rules/directory/private/glob.bzl000066400000000000000000000111611517445036200223650ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing glob operations on directories.""" _NO_GLOB_MATCHES = "{glob} failed to match any files in {dir}" def transitive_entries(directory): """Returns the files and directories contained within a directory transitively. Args: directory: (DirectoryInfo) The directory to look at Returns: List[Either[DirectoryInfo, File]] The entries contained within. """ entries = [directory] stack = [directory] for _ in range(99999999): if not stack: return entries d = stack.pop() for entry in d.entries.values(): entries.append(entry) if type(entry) != "File": stack.append(entry) fail("Should never get to here") def directory_glob_chunk(directory, chunk): """Given a directory and a chunk of a glob, returns possible candidates. Args: directory: (DirectoryInfo) The directory to look relative from. chunk: (string) A chunk of a glob to look at. Returns: List[Either[DirectoryInfo, File]]] The candidate next entries for the chunk. """ if chunk == "*": return directory.entries.values() elif chunk == "**": return transitive_entries(directory) elif "*" not in chunk: if chunk in directory.entries: return [directory.entries[chunk]] else: return [] elif chunk.count("*") > 2: fail("glob chunks with more than two asterixes are unsupported. Got", chunk) if chunk.count("*") == 2: left, middle, right = chunk.split("*") else: middle = "" left, right = chunk.split("*") entries = [] for name, entry in directory.entries.items(): if name.startswith(left) and name.endswith(right) and len(left) + len(right) <= len(name) and middle in name[len(left):len(name) - len(right)]: entries.append(entry) return entries def directory_single_glob(directory, glob): """Calculates all files that are matched by a glob on a directory. Args: directory: (DirectoryInfo) The directory to look relative from. glob: (string) A glob to match. Returns: List[File] A list of files that match. """ # Treat a glob as a nondeterministic finite state automata. We can be in # multiple places at the one time. candidate_dirs = [directory] candidate_files = [] for chunk in glob.split("/"): next_candidate_dirs = {} candidate_files = {} for candidate in candidate_dirs: for e in directory_glob_chunk(candidate, chunk): if type(e) == "File": candidate_files[e] = None else: next_candidate_dirs[e.human_readable] = e candidate_dirs = next_candidate_dirs.values() return list(candidate_files) def glob(directory, include, exclude = [], allow_empty = False): """native.glob, but for DirectoryInfo. Args: directory: (DirectoryInfo) The directory to look relative from. include: (List[string]) A list of globs to match. exclude: (List[string]) A list of globs to exclude. allow_empty: (bool) Whether to allow a glob to not match any files. Returns: depset[File] A set of files that match. """ include_files = [] for g in include: matches = directory_single_glob(directory, g) if not matches and not allow_empty: fail(_NO_GLOB_MATCHES.format( glob = repr(g), dir = directory.human_readable, )) include_files.extend(matches) if not exclude: return depset(include_files) include_files = {k: None for k in include_files} for g in exclude: matches = directory_single_glob(directory, g) if not matches and not allow_empty: fail(_NO_GLOB_MATCHES.format( glob = repr(g), dir = directory.human_readable, )) for f in matches: include_files.pop(f, None) return depset(include_files.keys()) bazel-skylib-1.9.1/rules/directory/private/paths.bzl000066400000000000000000000061331517445036200225640ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing path operations on directories.""" load("//lib:paths.bzl", "paths") _NOT_FOUND = """{directory} does not contain an entry named {name}. Instead, it contains the following entries: {children} """ _WRONG_TYPE = "Expected {dir}/{name} to have type {want}, but got {got}" # These correspond to an "enum". FILE = "file" DIRECTORY = "directory" def _check_path_relative(path): if paths.is_absolute(path): fail("Path must be relative. Got {path}".format(path = path)) def _get_direct_child(directory, name, require_type = None): """Gets the direct child of a directory. Args: directory: (DirectoryInfo) The directory to look within. name: (string) The name of the directory/file to look for. require_type: (Optional[DIRECTORY|FILE]) If provided, must return either a the corresponding type. Returns: (File|DirectoryInfo) The content contained within. """ entry = directory.entries.get(name, None) if entry == None: fail(_NOT_FOUND.format( directory = directory.human_readable, name = repr(name), children = "\n".join(directory.entries.keys()), )) if require_type == DIRECTORY and type(entry) == "File": fail(_WRONG_TYPE.format( dir = directory.human_readable, name = name, want = "Directory", got = "File", )) if require_type == FILE and type(entry) != "File": fail(_WRONG_TYPE.format( dir = directory.human_readable, name = name, want = "File", got = "Directory", )) return entry def get_path(directory, path, require_type = None): """Gets a subdirectory or file contained within a directory. Example: `get_path(directory, "a/b", require_type=FILE)` -> the file corresponding to `directory.path + "/a/b"` Args: directory: (DirectoryInfo) The directory to look within. path: (string) The path of the directory to look for within it. require_type: (Optional[DIRECTORY|FILE]) If provided, must return either a the corresponding type. Returns: (File|DirectoryInfo) The directory contained within. """ _check_path_relative(path) chunks = path.split("/") for dirname in chunks[:-1]: directory = _get_direct_child(directory, dirname, require_type = DIRECTORY) return _get_direct_child( directory, chunks[-1], require_type = require_type, ) bazel-skylib-1.9.1/rules/directory/providers.bzl000066400000000000000000000047721517445036200220170ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing providers for directories.""" load("//rules/directory/private:glob.bzl", "glob") load("//rules/directory/private:paths.bzl", "DIRECTORY", "FILE", "get_path") def _init_directory_info(**kwargs): self = struct(**kwargs) kwargs.update( get_path = lambda path: get_path(self, path, require_type = None), get_file = lambda path: get_path(self, path, require_type = FILE), get_subdirectory = lambda path: get_path(self, path, require_type = DIRECTORY), glob = lambda include, exclude = [], allow_empty = False: glob(self, include, exclude, allow_empty), ) return kwargs # TODO: Once bazel 5 no longer needs to be supported, remove this function, and add # init = _init_directory_info to the provider below # buildifier: disable=function-docstring def create_directory_info(**kwargs): return DirectoryInfo(**_init_directory_info(**kwargs)) DirectoryInfo = provider( doc = "Information about a directory", # @unsorted-dict-items fields = { "entries": "(Dict[str, Either[File, DirectoryInfo]]) The entries contained directly within. Ordered by filename", "transitive_files": "(depset[File]) All files transitively contained within this directory.", "path": "(string) Path to all files contained within this directory.", "human_readable": "(string) A human readable identifier for a directory. Useful for providing error messages to a user.", "get_path": "(Function(str) -> DirectoryInfo|File) A function to return the entry corresponding to the joined path.", "get_file": "(Function(str) -> File) A function to return the entry corresponding to the joined path.", "get_subdirectory": "(Function(str) -> DirectoryInfo) A function to return the entry corresponding to the joined path.", "glob": "(Function(include, exclude, allow_empty=False)) A function that works the same as native.glob.", }, ) bazel-skylib-1.9.1/rules/directory/subdirectory.bzl000066400000000000000000000025371517445036200225150ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing rules to create metadata about subdirectories.""" load(":providers.bzl", "DirectoryInfo") def _subdirectory_impl(ctx): dir = ctx.attr.parent[DirectoryInfo].get_subdirectory(ctx.attr.path) return [ dir, DefaultInfo(files = dir.transitive_files), ] subdirectory = rule( implementation = _subdirectory_impl, attrs = { "parent": attr.label( providers = [DirectoryInfo], mandatory = True, doc = "A label corresponding to the parent directory (or subdirectory).", ), "path": attr.string( mandatory = True, doc = "A path within the parent directory (eg. \"path/to/subdir\")", ), }, provides = [DirectoryInfo], ) bazel-skylib-1.9.1/rules/expand_template.bzl000066400000000000000000000032561517445036200211440ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A rule that performs template expansion. """ def _expand_template_impl(ctx): ctx.actions.expand_template( template = ctx.file.template, output = ctx.outputs.out, substitutions = ctx.attr.substitutions, ) expand_template = rule( implementation = _expand_template_impl, doc = """Template expansion This performs a simple search over the template file for the keys in substitutions, and replaces them with the corresponding values. There is no special syntax for the keys. To avoid conflicts, you would need to explicitly add delimiters to the key strings, for example "{KEY}" or "@KEY@".""", attrs = { "template": attr.label( mandatory = True, allow_single_file = True, doc = "The template file to expand.", ), "substitutions": attr.string_dict( mandatory = True, doc = "A dictionary mapping strings to their substitutions.", ), "out": attr.output( mandatory = True, doc = "The destination of the expanded file.", ), }, ) bazel-skylib-1.9.1/rules/native_binary.bzl000066400000000000000000000062641517445036200206260ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """native_binary() and native_test() rule implementations. These rules let you wrap a pre-built binary or script in a conventional binary and test rule respectively. They fulfill the same goal as sh_binary and sh_test do, but they run the wrapped binary directly, instead of through Bash, so they don't depend on Bash and work with --shell_executable="". """ def _impl_rule(ctx): out = ctx.actions.declare_file(ctx.attr.out if (ctx.attr.out != "") else ctx.attr.name + ".exe") ctx.actions.symlink( target_file = ctx.executable.src, output = out, is_executable = True, ) runfiles = ctx.runfiles(files = ctx.files.data) runfiles = runfiles.merge_all([ d[DefaultInfo].default_runfiles for d in ctx.attr.data + [ctx.attr.src] ]) return [ DefaultInfo( executable = out, files = depset([out]), runfiles = runfiles, ), RunEnvironmentInfo( environment = ctx.attr.env, ), ] _ATTRS = { "src": attr.label( executable = True, # This must be used instead of `allow_single_file` because otherwise a # target with multiple default outputs (e.g. py_binary) would not be # allowed. allow_files = True, mandatory = True, cfg = "target", doc = "path of the pre-built executable", ), "data": attr.label_list( allow_files = True, doc = "data dependencies. See" + " https://bazel.build/reference/be/common-definitions#typical.data", ), # "out" is attr.string instead of attr.output, so that it is select()'able. "out": attr.string( default = "", doc = "An output name for the copy of the binary. Defaults to " + "name.exe. (We add .exe to the name by default because it's " + "required on Windows and tolerated on other platforms.)", ), "env": attr.string_dict( doc = "Environment variables to set when running the binary.", ), } native_binary = rule( implementation = _impl_rule, attrs = _ATTRS, executable = True, doc = """ Wraps a pre-built binary or script with a binary rule. You can "bazel run" this rule like any other binary rule, and use it as a tool in genrule.tools for example. You can also augment the binary with runfiles. """, ) native_test = rule( implementation = _impl_rule, attrs = _ATTRS, test = True, doc = """ Wraps a pre-built binary or script with a test rule. You can "bazel test" this rule like any other test rule. You can also augment the binary with runfiles. """, ) bazel-skylib-1.9.1/rules/private/000077500000000000000000000000001517445036200167255ustar00rootroot00000000000000bazel-skylib-1.9.1/rules/private/BUILD000066400000000000000000000027031517445036200175110ustar00rootroot00000000000000load("//:bzl_library.bzl", "bzl_library") load(":copy_common.bzl", "is_windows") package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) is_windows( name = "is_windows", applicable_licenses = [], # no output artifacts visibility = ["//visibility:public"], ) bzl_library( name = "bzl_library", srcs = ["bzl_library.bzl"], visibility = [ "//:__pkg__", "//docs:__pkg__", ], ) exports_files( ["bzl_library.bzl"], visibility = ["//docs:__pkg__"], ) bzl_library( name = "copy_common", srcs = ["copy_common.bzl"], visibility = ["//rules:__pkg__"], ) bzl_library( name = "copy_directory_private", srcs = ["copy_directory_private.bzl"], visibility = ["//rules:__pkg__"], deps = [":copy_common"], ) bzl_library( name = "copy_file_private", srcs = ["copy_file_private.bzl"], visibility = ["//rules:__pkg__"], deps = [":copy_common"], ) bzl_library( name = "write_file_private", srcs = ["write_file_private.bzl"], visibility = ["//rules:__pkg__"], ) bzl_library( name = "maprule_util", srcs = ["maprule_util.bzl"], ) filegroup( name = "test_deps", testonly = True, srcs = [ "BUILD", ] + glob(["*.bzl"]), visibility = [ "//rules:__pkg__", ], ) # The files needed for distribution filegroup( name = "distribution", srcs = glob(["*"]), visibility = [ "//:__subpackages__", ], ) bazel-skylib-1.9.1/rules/private/bzl_library.bzl000066400000000000000000000060621517445036200217550ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing a library rule for aggregating rules files.""" StarlarkLibraryInfo = provider( "Information on contained Starlark rules.", fields = { "srcs": "Top level rules files.", "transitive_srcs": "Transitive closure of rules files required for " + "interpretation of the srcs", }, ) def _bzl_library_impl(ctx): deps_files = [x[DefaultInfo].files for x in ctx.attr.deps] all_files = depset(ctx.files.srcs, order = "postorder", transitive = deps_files) if not ctx.files.srcs and not deps_files: fail("bzl_library rule '%s' has no srcs or deps" % ctx.label) return [ # All dependent files should be listed in both `files` and in `runfiles`; # this ensures that a `bzl_library` can be referenced as `data` from # a separate program, or from `tools` of a genrule(). DefaultInfo( files = all_files, runfiles = ctx.runfiles(transitive_files = all_files), ), # We also define our own provider struct, for aggregation and testing. StarlarkLibraryInfo( srcs = ctx.files.srcs, transitive_srcs = all_files, ), ] bzl_library = rule( implementation = _bzl_library_impl, attrs = { "srcs": attr.label_list( allow_files = [".bzl", ".scl"], doc = "List of `.bzl` and `.scl` files that are processed to create this target.", ), "deps": attr.label_list( allow_files = [".bzl", ".scl"], doc = """List of other `bzl_library` or `filegroup` targets that are required by the Starlark files listed in `srcs`.""", ), }, doc = """Creates a logical collection of Starlark .bzl and .scl files. Example: Suppose your project has the following structure: ``` [workspace]/ WORKSPACE BUILD checkstyle/ BUILD checkstyle.bzl lua/ BUILD lua.bzl luarocks.bzl ``` In this case, you can have `bzl_library` targets in `checkstyle/BUILD` and `lua/BUILD`: `checkstyle/BUILD`: ```python load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "checkstyle-rules", srcs = ["checkstyle.bzl"], ) ``` `lua/BUILD`: ```python load("@bazel_skylib//:bzl_library.bzl", "bzl_library") bzl_library( name = "lua-rules", srcs = [ "lua.bzl", "luarocks.bzl", ], ) ``` """, ) bazel-skylib-1.9.1/rules/private/copy_common.bzl000066400000000000000000000054611517445036200217660ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. "Helpers for copy rules" # Hints for Bazel spawn strategy COPY_EXECUTION_REQUIREMENTS = { # ----------------+----------------------------------------------------------------------------- # no-remote | Prevents the action or test from being executed remotely or cached remotely. # | This is equivalent to using both `no-remote-cache` and `no-remote-exec`. # ----------------+----------------------------------------------------------------------------- # no-cache | Results in the action or test never being cached (remotely or locally) # ----------------+----------------------------------------------------------------------------- # See https://bazel.build/reference/be/common-definitions#common-attributes # # Copying file & directories is entirely IO-bound and there is no point doing this work # remotely. # # Also, remote-execution does not allow source directory inputs, see # https://github.com/bazelbuild/bazel/commit/c64421bc35214f0414e4f4226cc953e8c55fa0d2 So we must # not attempt to execute remotely in that case. # # There is also no point pulling the output file or directory from the remote cache since the # bytes to copy are already available locally. Conversely, no point in writing to the cache if # no one has any reason to check it for this action. # # Read and writing to disk cache is disabled as well primarily to reduce disk usage on the local # machine. A disk cache hit of a directory copy could be slghtly faster than a copy since the # disk cache stores the directory artifact as a single entry, but the slight performance bump # comes at the cost of heavy disk cache usage, which is an unmanaged directory that grow beyond # the bounds of the physical disk. "no-remote": "1", "no-cache": "1", } OsInfo = provider( doc = "Information about the target platform's OS.", fields = ["is_windows"], ) is_windows = rule( implementation = lambda ctx: OsInfo( is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]), ), attrs = { "_windows_constraint": attr.label(default = "@platforms//os:windows"), }, ) bazel-skylib-1.9.1/rules/private/copy_directory_private.bzl000066400000000000000000000132701517445036200242310ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Implementation of copy_directory macro and underlying rules. This rule copies a directory to another location using Bash (on Linux/macOS) or cmd.exe (on Windows). """ load(":copy_common.bzl", "COPY_EXECUTION_REQUIREMENTS", "OsInfo") def _copy_cmd(ctx, src, dst): # Most Windows binaries built with MSVC use a certain argument quoting # scheme. Bazel uses that scheme too to quote arguments. However, # cmd.exe uses different semantics, so Bazel's quoting is wrong here. # To fix that we write the command to a .bat file so no command line # quoting or escaping is required. # Put a hash of the file name into the name of the generated batch file to # make it unique within the package, so that users can define multiple copy_file's. bat = ctx.actions.declare_file("%s-%s-cmd.bat" % (ctx.label.name, hash(src.path))) # Flags are documented at # https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy # NB: robocopy return non-zero exit codes on success so we must exit 0 after calling it cmd_tmpl = """\ if not exist \"{src}\\\" ( echo Error: \"{src}\" is not a directory @exit 1 ) @robocopy \"{src}\" \"{dst}\" /E /MIR >NUL & @exit 0 """ mnemonic = "CopyDirectory" progress_message = "Copying directory %{input}" ctx.actions.write( output = bat, # Do not use lib/shell.bzl's shell.quote() method, because that uses # Bash quoting syntax, which is different from cmd.exe's syntax. content = cmd_tmpl.format( src = src.path.replace("/", "\\"), dst = dst.path.replace("/", "\\"), ), is_executable = True, ) ctx.actions.run( inputs = [src, bat], outputs = [dst], executable = "cmd.exe", arguments = ["/C", bat.path.replace("/", "\\")], mnemonic = mnemonic, progress_message = progress_message, use_default_shell_env = True, execution_requirements = COPY_EXECUTION_REQUIREMENTS, ) def _copy_bash(ctx, src, dst): cmd = """\ if [ ! -d \"$1\" ]; then echo \"Error: $1 is not a directory\" exit 1 fi rm -rf \"$2\" && cp -fR \"$1/\" \"$2\" """ mnemonic = "CopyDirectory" progress_message = "Copying directory %s" % src.path ctx.actions.run_shell( inputs = [src], outputs = [dst], command = cmd, arguments = [src.path, dst.path], mnemonic = mnemonic, progress_message = progress_message, use_default_shell_env = True, execution_requirements = COPY_EXECUTION_REQUIREMENTS, ) def copy_directory_action(ctx, src, dst, is_windows = False): """Helper function that creates an action to copy a directory from src to dst. This helper is used by copy_directory. It is exposed as a public API so it can be used within other rule implementations. Args: ctx: The rule context. src: The directory to make a copy of. Can be a source directory or TreeArtifact. dst: The directory to copy to. Must be a TreeArtifact. is_windows: If true, an cmd.exe action is created so there is no bash dependency. """ if dst.is_source or not dst.is_directory: fail("dst must be a TreeArtifact") if is_windows: _copy_cmd(ctx, src, dst) else: _copy_bash(ctx, src, dst) def _copy_directory_impl(ctx): dst = ctx.actions.declare_directory(ctx.attr.out) copy_directory_action(ctx, ctx.file.src, dst, ctx.attr._exec_is_windows[OsInfo].is_windows) files = depset(direct = [dst]) runfiles = ctx.runfiles(files = [dst]) return [DefaultInfo(files = files, runfiles = runfiles)] _copy_directory = rule( implementation = _copy_directory_impl, provides = [DefaultInfo], attrs = { "src": attr.label(mandatory = True, allow_single_file = True), # Cannot declare out as an output here, because there's no API for declaring # TreeArtifact outputs. "out": attr.string(mandatory = True), "_exec_is_windows": attr.label( default = ":is_windows", # The exec transition must match the exec group of the actions, which in # this case is the default exec group. cfg = "exec", ), }, ) def copy_directory(name, src, out, **kwargs): """Copies a directory to another location. This rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). If using this rule with source directories, it is recommended that you use the `--host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1` startup option so that changes to files within source directories are detected. See https://github.com/bazelbuild/bazel/commit/c64421bc35214f0414e4f4226cc953e8c55fa0d2 for more context. Args: name: Name of the rule. src: The directory to make a copy of. Can be a source directory or TreeArtifact. out: Path of the output directory, relative to this package. **kwargs: further keyword arguments, e.g. `visibility` """ _copy_directory( name = name, src = src, out = out, **kwargs ) bazel-skylib-1.9.1/rules/private/copy_file_private.bzl000066400000000000000000000127661517445036200231550ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Implementation of copy_file macro and underlying rules. These rules copy a file to another location using Bash (on Linux/macOS) or cmd.exe (on Windows). '_copy_xfile' marks the resulting file executable, '_copy_file' does not. """ load(":copy_common.bzl", "OsInfo") def copy_cmd(ctx, src, dst): # Most Windows binaries built with MSVC use a certain argument quoting # scheme. Bazel uses that scheme too to quote arguments. However, # cmd.exe uses different semantics, so Bazel's quoting is wrong here. # To fix that we write the command to a .bat file so no command line # quoting or escaping is required. bat = ctx.actions.declare_file(ctx.label.name + "-cmd.bat") ctx.actions.write( output = bat, # Do not use lib/shell.bzl's shell.quote() method, because that uses # Bash quoting syntax, which is different from cmd.exe's syntax. content = "@copy /Y \"%s\" \"%s\" >NUL" % ( src.path.replace("/", "\\"), dst.path.replace("/", "\\"), ), is_executable = True, ) ctx.actions.run( inputs = [src, bat], outputs = [dst], executable = "cmd.exe", arguments = ["/C", bat.path.replace("/", "\\")], mnemonic = "CopyFile", progress_message = "Copying files", use_default_shell_env = True, ) def copy_bash(ctx, src, dst): ctx.actions.run_shell( inputs = [src], outputs = [dst], command = "cp -f \"$1\" \"$2\"", arguments = [src.path, dst.path], mnemonic = "CopyFile", progress_message = "Copying files", use_default_shell_env = True, ) def _copy_file_impl(ctx): if ctx.attr.allow_symlink: ctx.actions.symlink( output = ctx.outputs.out, target_file = ctx.file.src, is_executable = ctx.attr.is_executable, ) elif ctx.attr._exec_is_windows[OsInfo].is_windows: copy_cmd(ctx, ctx.file.src, ctx.outputs.out) else: copy_bash(ctx, ctx.file.src, ctx.outputs.out) files = depset(direct = [ctx.outputs.out]) runfiles = ctx.runfiles(files = [ctx.outputs.out]) if ctx.attr.is_executable: return [DefaultInfo(files = files, runfiles = runfiles, executable = ctx.outputs.out)] else: # Do not include the copied file into the default runfiles of the # target, but ensure that it is picked up by native rule's data # attribute despite https://github.com/bazelbuild/bazel/issues/15043. return [DefaultInfo(files = files, data_runfiles = runfiles)] _ATTRS = { "src": attr.label(mandatory = True, allow_single_file = True), "out": attr.output(mandatory = True), "is_executable": attr.bool(mandatory = True), "allow_symlink": attr.bool(mandatory = True), "_exec_is_windows": attr.label( default = ":is_windows", # The exec transition must match the exec group of the actions, which in # this case is the default exec group. cfg = "exec", ), } _copy_file = rule( implementation = _copy_file_impl, provides = [DefaultInfo], attrs = _ATTRS, ) _copy_xfile = rule( implementation = _copy_file_impl, executable = True, provides = [DefaultInfo], attrs = _ATTRS, ) def copy_file(name, src, out, is_executable = False, allow_symlink = False, **kwargs): """Copies a file to another location. `native.genrule()` is sometimes used to copy files (often wishing to rename them). The 'copy_file' rule does this with a simpler interface than genrule. This rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). Args: name: Name of the rule. src: A Label. The file to make a copy of. (Can also be the label of a rule that generates a file.) out: Path of the output file, relative to this package. is_executable: A boolean. Whether to make the output file executable. When True, the rule's output can be executed using `bazel run` and can be in the srcs of binary and test rules that require executable sources. WARNING: If `allow_symlink` is True, `src` must also be executable. allow_symlink: A boolean. Whether to allow symlinking instead of copying. When False, the output is always a hard copy. When True, the output *can* be a symlink, but there is no guarantee that a symlink is created (i.e., at the time of writing, we don't create symlinks on Windows). Set this to True if you need fast copying and your tools can handle symlinks (which most UNIX tools can). **kwargs: further keyword arguments, e.g. `visibility` """ copy_file_impl = _copy_file if is_executable: copy_file_impl = _copy_xfile copy_file_impl( name = name, src = src, out = out, is_executable = is_executable, allow_symlink = allow_symlink, **kwargs ) bazel-skylib-1.9.1/rules/private/maprule_util.bzl000066400000000000000000000111661517445036200221450ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utilities for maprule.""" def resolve_locations(ctx, strategy, d): """Resolve $(location) references in the values of a dictionary. Args: ctx: the 'ctx' argument of the rule implementation function strategy: a struct with an 'as_path(string) -> string' function d: {string: string} dictionary; values may contain $(location) references for labels declared in the rule's 'srcs' and 'tools' attributes Returns: {string: string} dict, same as 'd' except "$(location)" references are resolved. """ location_expressions = [] parts = {} was_anything_to_resolve = False for k, v in d.items(): # Look for "$(location ...)" or "$(locations ...)", resolve if found. # _validate_attributes already ensured that there's at most one $(location/s ...) in "v". if "$(location" in v: tokens = v.split("$(location") was_anything_to_resolve = True closing_paren = tokens[1].find(")") location_expressions.append("$(location" + tokens[1][:closing_paren + 1]) parts[k] = (tokens[0], tokens[1][closing_paren + 1:]) else: location_expressions.append("") resolved = {} if was_anything_to_resolve: # Resolve all $(location) expressions in one go. Should be faster than resolving them # one-by-one. all_location_expressions = "".join(location_expressions) all_resolved_locations = ctx.expand_location(all_location_expressions) resolved_locations = strategy.as_path(all_resolved_locations).split("") i = 0 # Starlark dictionaries have a deterministic order of iteration, so the element order in # "resolved_locations" matches the order in "location_expressions", i.e. the previous # iteration order of "d". for k, v in d.items(): if location_expressions[i]: head, tail = parts[k] resolved[k] = head + resolved_locations[i] + tail else: resolved[k] = v i += 1 else: resolved = d return resolved def fail_if_errors(errors): """Reports errors and fails the rule. Args: errors: list of strings; the errors to report. At most 10 are reported. """ if errors: # Don't overwhelm the user; report up to ten errors. fail("\n".join(errors[:10])) def _as_windows_path(s): """Returns the input path as a Windows path (replaces all of "/" with "\").""" return s.replace("/", "\\") def _unchanged_path(s): """Returns the input string (path) unchanged.""" return s def _create_cmd_action( ctx, outputs, command, inputs = None, env = None, progress_message = None, mnemonic = None, manifests_from_tools = None): """Create one action using cmd.exe.""" ctx.actions.run( inputs = inputs or [], outputs = outputs, executable = "cmd.exe", env = env, arguments = ["/C", command], progress_message = progress_message or "Running cmd.exe command", mnemonic = mnemonic or "CmdExeCommand", input_manifests = manifests_from_tools, ) def _create_bash_action( ctx, outputs, command, inputs = None, env = None, progress_message = None, mnemonic = None, manifests_from_tools = None): """Create one action using Bash.""" ctx.actions.run_shell( inputs = inputs or [], outputs = outputs, env = env, command = command, progress_message = progress_message or "Running Bash command", mnemonic = mnemonic or "BashCommand", input_manifests = manifests_from_tools, ) # Action creation utilities for cmd.exe actions. CMD_STRATEGY = struct( as_path = _as_windows_path, create_action = _create_cmd_action, ) # Action creation utilities for Bash actions. BASH_STRATEGY = struct( as_path = _unchanged_path, create_action = _create_bash_action, ) bazel-skylib-1.9.1/rules/private/write_file_private.bzl000066400000000000000000000074151517445036200233300ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Implementation of write_file macro and underlying rules. These rules write a UTF-8 encoded text file, using Bazel's FileWriteAction. '_write_xfile' marks the resulting file executable, '_write_file' does not. """ def _common_impl(ctx, is_executable): is_windows = ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]) if ctx.attr.newline == "auto": newline = "\r\n" if is_windows else "\n" elif ctx.attr.newline == "windows": newline = "\r\n" else: newline = "\n" # ctx.actions.write creates a FileWriteAction which uses UTF-8 encoding. ctx.actions.write( output = ctx.outputs.out, content = newline.join(ctx.attr.content) if ctx.attr.content else "", is_executable = is_executable, ) files = depset(direct = [ctx.outputs.out]) runfiles = ctx.runfiles(files = [ctx.outputs.out]) if is_executable: return [DefaultInfo(files = files, runfiles = runfiles, executable = ctx.outputs.out)] else: # Do not include the copied file into the default runfiles of the # target, but ensure that it is picked up by native rule's data # attribute despite https://github.com/bazelbuild/bazel/issues/15043. return [DefaultInfo(files = files, data_runfiles = runfiles)] def _impl(ctx): return _common_impl(ctx, False) def _ximpl(ctx): return _common_impl(ctx, True) _ATTRS = { "out": attr.output(mandatory = True), "content": attr.string_list(mandatory = False, allow_empty = True), "newline": attr.string(values = ["unix", "windows", "auto"], default = "auto"), "_windows_constraint": attr.label(default = "@platforms//os:windows"), } _write_file = rule( implementation = _impl, provides = [DefaultInfo], attrs = _ATTRS, ) _write_xfile = rule( implementation = _ximpl, executable = True, provides = [DefaultInfo], attrs = _ATTRS, ) def write_file( name, out, content = [], is_executable = False, newline = "auto", **kwargs): """Creates a UTF-8 encoded text file. Args: name: Name of the rule. out: Path of the output file, relative to this package. content: A list of strings. Lines of text, the contents of the file. Newlines are added automatically after every line except the last one. is_executable: A boolean. Whether to make the output file executable. When True, the rule's output can be executed using `bazel run` and can be in the srcs of binary and test rules that require executable sources. newline: one of ["auto", "unix", "windows"]: line endings to use. "auto" for platform-determined, "unix" for LF, and "windows" for CRLF. **kwargs: further keyword arguments, e.g. `visibility` """ if is_executable: _write_xfile( name = name, content = content, out = out, newline = newline or "auto", **kwargs ) else: _write_file( name = name, content = content, out = out, newline = newline or "auto", **kwargs ) bazel-skylib-1.9.1/rules/run_binary.bzl000066400000000000000000000102361517445036200201360ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ run_binary() build rule implementation. Runs a binary as a build action. This rule does not require Bash (unlike native.genrule()). """ load("//lib:dicts.bzl", "dicts") def _run_binary_impl(ctx): tool_as_list = [ctx.attr.tool] args = [ # Expand $(execpath ...) / $(execpaths ...) / $(location ...) / $(locations ...) in args. # # To keep the rule simple, do not expand Make Variables (like *_binary.args usually would). # (We can add this feature later if users ask for it.) # # Also for simple implementation and usage, do not Bash-tokenize the arguments. Without # tokenization the user can write args=["a b"] to pass (a b) as one argument, but with # tokenization they would have to write args=["'a b'"] or args=["a\\ b"]. There's no # documented tokenization function anyway (as of 2019-05-21 ctx.tokenize exists but is # undocumented, see https://github.com/bazelbuild/bazel/issues/8389). ctx.expand_location(a, tool_as_list) for a in ctx.attr.args ] envs = { # Expand $(execpath ...) / $(execpaths ...) / $(location ...) / $(locations ...) in the values. k: ctx.expand_location(v, tool_as_list) for k, v in ctx.attr.env.items() } ctx.actions.run( outputs = ctx.outputs.outs, inputs = ctx.files.srcs, tools = [ctx.executable.tool], executable = ctx.executable.tool, arguments = args, mnemonic = "RunBinary", use_default_shell_env = False, env = dicts.add(ctx.configuration.default_shell_env, envs), ) return DefaultInfo( files = depset(ctx.outputs.outs), runfiles = ctx.runfiles(files = ctx.outputs.outs), ) run_binary = rule( implementation = _run_binary_impl, doc = "Runs a binary as a build action.\n\nThis rule does not require Bash (unlike" + " `native.genrule`).", attrs = { "tool": attr.label( doc = "The tool to run in the action.\n\nMust be the label of a *_binary rule," + " of a rule that generates an executable file, or of a file that can be" + " executed as a subprocess (e.g. an .exe or .bat file on Windows or a binary" + " with executable permission on Linux). This label is available for" + " `$(execpath)` and `$(location)` expansion in `args` and `env`.", executable = True, allow_files = True, mandatory = True, cfg = "exec", ), "env": attr.string_dict( doc = "Environment variables of the action.\n\nSubject to " + " [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables)" + " expansion.", ), "srcs": attr.label_list( allow_files = True, doc = "Additional inputs of the action.\n\nThese labels are available for" + " `$(execpath)` and `$(location)` expansion in `args` and `env`.", ), "outs": attr.output_list( mandatory = True, doc = "Output files generated by the action.\n\nThese labels are available for" + " `$(execpath)` and `$(location)` expansion in `args` and `env`.", ), "args": attr.string_list( doc = "Command line arguments of the binary.\n\nSubject to" + " [`$(execpath)` and `$(location)`](https://bazel.build/reference/be/make-variables#predefined_label_variables)" + " expansion.", ), }, ) bazel-skylib-1.9.1/rules/select_file.bzl000066400000000000000000000033731517445036200202500ustar00rootroot00000000000000# Copyright 2020 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ select_file() build rule implementation. Selects a single file from the outputs of a target by given relative path. """ def _impl(ctx): if ctx.attr.subpath and len(ctx.attr.subpath) == 0: fail("Subpath can not be empty.") out = None canonical = ctx.attr.subpath.replace("\\", "/") for file_ in ctx.attr.srcs[DefaultInfo].files.to_list(): if file_.path.replace("\\", "/").endswith(canonical): out = file_ break if not out: files_str = ",\n".join([ str(f.path) for f in ctx.attr.srcs[DefaultInfo].files.to_list() ]) fail("Can not find specified file in [%s]" % files_str) return [DefaultInfo(files = depset([out]))] select_file = rule( implementation = _impl, doc = "Selects a single file from the outputs of a target by given relative path", attrs = { "srcs": attr.label( allow_files = True, mandatory = True, doc = "The target producing the file among other outputs", ), "subpath": attr.string( mandatory = True, doc = "Relative path to the file", ), }, ) bazel-skylib-1.9.1/rules/write_file.bzl000066400000000000000000000021131517445036200201120ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A rule that writes a UTF-8 encoded text file from user-specified contents. native.genrule() is sometimes used to create a text file. The 'write_file' and macro does this with a simpler interface than genrule. The rules generated by the macro do not use Bash or any other shell to write the file. Instead they use Starlark's built-in file writing action (ctx.actions.write). """ load( "//rules/private:write_file_private.bzl", _write_file = "write_file", ) write_file = _write_file bazel-skylib-1.9.1/skylark_library.bzl000066400000000000000000000014711517445036200200410ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Skylib module containing a library rule for aggregating rules files. Removed: Use bzl_library in bzl_library.bzl instead. """ fail( "skylark_library.bzl has been removed, please use bzl_library.bzl instead.", ) bazel-skylib-1.9.1/tests/000077500000000000000000000000001517445036200152635ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/BUILD000066400000000000000000000050631517445036200160510ustar00rootroot00000000000000load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//:bzl_library.bzl", "bzl_library") load(":build_test_tests.bzl", "build_test_test_suite") load(":collections_tests.bzl", "collections_test_suite") load(":common_settings_tests.bzl", "common_settings_test_suite") load(":dicts_tests.bzl", "dicts_test_suite") load(":modules_test.bzl", "modules_test_suite") load(":new_sets_tests.bzl", "new_sets_test_suite") load(":partial_tests.bzl", "partial_test_suite") load(":paths_tests.bzl", "paths_test_suite") load(":selects_tests.bzl", "selects_test_suite") load(":shell_tests.bzl", "shell_args_test_gen", "shell_test_suite") load(":structs_tests.bzl", "structs_test_suite") load(":subpackages_tests.bzl", "subpackages_test_suite") load(":types_tests.bzl", "types_test_suite") load(":unittest_tests.bzl", "unittest_passing_tests_suite") load(":versions_tests.bzl", "versions_test_suite") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) exports_files( ["unittest.bash"], visibility = ["//tests:__subpackages__"], ) build_test_test_suite() collections_test_suite() common_settings_test_suite() dicts_test_suite() modules_test_suite() new_sets_test_suite() partial_test_suite() paths_test_suite() selects_test_suite() shell_test_suite() structs_test_suite() subpackages_test_suite() types_test_suite() unittest_passing_tests_suite() versions_test_suite() bzl_library( name = "unittest_tests_bzl", srcs = ["unittest_tests.bzl"], visibility = ["//visibility:private"], deps = ["//lib:unittest"], ) sh_test( name = "unittest_e2e_test", srcs = ["unittest_test.sh"], data = [ ":unittest.bash", ":unittest_tests_bzl", "//lib:dicts", "//lib:new_sets", "//lib:sets", "//lib:types", "//lib:unittest", "//toolchains/unittest:test_deps", "@bazel_tools//tools/bash/runfiles", ], tags = ["local"], ) sh_test( name = "analysis_test_e2e_test", srcs = ["analysis_test_test.sh"], data = [ ":unittest.bash", "//rules:analysis_test.bzl", "@bazel_tools//tools/bash/runfiles", ], tags = ["local"], ) sh_test( name = "common_settings_e2e_test", srcs = ["common_settings_test.sh"], data = [ ":unittest.bash", "//rules:common_settings.bzl", "@bazel_tools//tools/bash/runfiles", ], tags = ["local"], ) shell_args_test_gen( name = "shell_spawn_e2e_test_src", ) sh_test( name = "shell_spawn_e2e_test", srcs = [":shell_spawn_e2e_test_src"], ) bazel-skylib-1.9.1/tests/analysis_test_test.sh000077500000000000000000000110451517445036200215440ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # End to end tests for analysis_test.bzl. # # End to end tests of analysis_test.bzl cover verification that # analysis_test tests fail when their underlying test targets fail analysis. # --- begin runfiles.bash initialization --- set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function create_pkg() { local -r pkg="$1" mkdir -p "$pkg" cd "$pkg" cat > WORKSPACE < MODULE.bazel < rules/BUILD < lib/BUILD < lib/types.bzl < fakerules/rules.bzl < fakerules/BUILD < testdir/dummy.cc < testdir/BUILD <"$TEST_log" 2>&1 || fail "Expected test to pass" expect_log "PASSED" } function test_direct_target_fails() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:direct_target_fails --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log "This rule should never work" } function test_transitive_target_fails() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:transitive_target_fails --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log "This rule should never work" } cd "$TEST_TMPDIR" run_suite "analysis_test test suite" bazel-skylib-1.9.1/tests/build_test_tests.bzl000066400000000000000000000026761517445036200213670ustar00rootroot00000000000000# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for build_test.bzl.""" load("@rules_cc//cc:cc_library.bzl", "cc_library") load("//rules:build_test.bzl", "build_test") # buildifier: disable=unnamed-macro def build_test_test_suite(): # Since the rules doesn't do anything really, it just makes some targets # to get Bazel to build other targets via a `bazel test`, just make some # targets to exercise the rule. # Make a source file native.genrule( name = "build_test__make_src", outs = ["build_test__src.cc"], cmd = "echo 'int dummy() { return 0; }' > $@", ) # Use it in a non-test target cc_library( name = "build_test__build_target", srcs = [":build_test__make_src"], ) # Wrap a build test around the target. build_test( name = "build_test__test", targets = [":build_test__build_target"], ) bazel-skylib-1.9.1/tests/bzl_library/000077500000000000000000000000001517445036200175765ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/bzl_library/BUILD000066400000000000000000000012451517445036200203620ustar00rootroot00000000000000load("//:bzl_library.bzl", "bzl_library") load(":bzl_library_test.bzl", "bzl_library_test") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) filegroup( name = "a", srcs = ["testdata/a.bzl"], ) bzl_library( name = "b", srcs = ["testdata/b.bzl"], ) bzl_library( name = "c", srcs = ["testdata/c.bzl"], deps = [ ":a", ":b", ], ) bzl_library_test( name = "bzl_library_test", expected_srcs = ["testdata/c.bzl"], expected_transitive_srcs = [ "testdata/a.bzl", "testdata/b.bzl", "testdata/c.bzl", ], target_under_test = ":c", ) bazel-skylib-1.9.1/tests/bzl_library/bzl_library_test.bzl000066400000000000000000000045331517445036200236660ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for bzl_library""" load("//:bzl_library.bzl", "StarlarkLibraryInfo") load("//lib:sets.bzl", "sets") load("//lib:unittest.bzl", "analysistest", "asserts") def _assert_same_files(env, expected_file_targets, actual_files): """Assertion that a list of expected file targets and an actual list or depset of files contain the same files""" expected_files = [] for target in expected_file_targets: target_files = target[DefaultInfo].files.to_list() asserts.true(env, len(target_files) == 1, "expected_file_targets must contain only file targets") expected_files.append(target_files[0]) if type(actual_files) == "depset": actual_files = actual_files.to_list() asserts.set_equals(env = env, expected = sets.make(expected_files), actual = sets.make(actual_files)) def _bzl_library_test_impl(ctx): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) _assert_same_files(env, ctx.attr.expected_srcs, target_under_test[StarlarkLibraryInfo].srcs) _assert_same_files(env, ctx.attr.expected_transitive_srcs, target_under_test[StarlarkLibraryInfo].transitive_srcs) _assert_same_files(env, ctx.attr.expected_transitive_srcs, target_under_test[DefaultInfo].files) return analysistest.end(env) bzl_library_test = analysistest.make( impl = _bzl_library_test_impl, attrs = { "expected_srcs": attr.label_list( mandatory = True, allow_files = True, doc = "Expected direct srcs in target_under_test's providers", ), "expected_transitive_srcs": attr.label_list( mandatory = True, allow_files = True, doc = "Expected transitive srcs in target_under_test's providers", ), }, ) bazel-skylib-1.9.1/tests/bzl_library/testdata/000077500000000000000000000000001517445036200214075ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/bzl_library/testdata/a.bzl000066400000000000000000000000521517445036200223350ustar00rootroot00000000000000"""a.bzl, livin' its best life""" A = 30 bazel-skylib-1.9.1/tests/bzl_library/testdata/b.bzl000066400000000000000000000000511517445036200223350ustar00rootroot00000000000000"""b.bzl, havin' a grand time""" B = 70 bazel-skylib-1.9.1/tests/bzl_library/testdata/c.bzl000066400000000000000000000001661517445036200223450ustar00rootroot00000000000000"""c.bzl, standin' on the shoulder of giants""" load(":testdata/a.bzl", "A") load(":testdata/b.bzl", "B") C = A + B bazel-skylib-1.9.1/tests/collections_tests.bzl000066400000000000000000000061531517445036200215410ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for collections.bzl.""" load("//lib:collections.bzl", "collections") load("//lib:unittest.bzl", "asserts", "unittest") def _after_each_test(ctx): """Unit tests for collections.after_each.""" env = unittest.begin(ctx) asserts.equals(env, [], collections.after_each("1", [])) asserts.equals(env, ["a", "1"], collections.after_each("1", ["a"])) asserts.equals( env, ["a", "1", "b", "1"], collections.after_each("1", ["a", "b"]), ) # We don't care what type the separator is, we just put it there; so None # should be just as valid as anything else. asserts.equals( env, ["a", None, "b", None], collections.after_each(None, ["a", "b"]), ) return unittest.end(env) after_each_test = unittest.make(_after_each_test) def _before_each_test(ctx): """Unit tests for collections.before_each.""" env = unittest.begin(ctx) asserts.equals(env, [], collections.before_each("1", [])) asserts.equals(env, ["1", "a"], collections.before_each("1", ["a"])) asserts.equals( env, ["1", "a", "1", "b"], collections.before_each("1", ["a", "b"]), ) # We don't care what type the separator is, we just put it there; so None # should be just as valid as anything else. asserts.equals( env, [None, "a", None, "b"], collections.before_each(None, ["a", "b"]), ) return unittest.end(env) before_each_test = unittest.make(_before_each_test) def _uniq_test(ctx): env = unittest.begin(ctx) asserts.equals(env, collections.uniq([0, 1, 2, 3]), [0, 1, 2, 3]) asserts.equals(env, collections.uniq([]), []) asserts.equals(env, collections.uniq([1, 1, 1, 1, 1]), [1]) asserts.equals( env, collections.uniq([ True, 5, "foo", 5, False, struct(a = 1), True, struct(b = 2), "bar", (1,), "foo", struct(a = 1), (1,), ]), [ True, 5, "foo", False, struct(a = 1), struct(b = 2), "bar", (1,), ], ) return unittest.end(env) uniq_test = unittest.make(_uniq_test) def collections_test_suite(): """Creates the test targets and test suite for collections.bzl tests.""" unittest.suite( "collections_tests", after_each_test, before_each_test, uniq_test, ) bazel-skylib-1.9.1/tests/common_settings/000077500000000000000000000000001517445036200204735ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/common_settings/BUILD000066400000000000000000000012761517445036200212630ustar00rootroot00000000000000load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//rules:common_settings.bzl", "int_flag", "string_flag") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) int_flag( name = "my_int_flag", build_setting_default = 42, make_variable = "MY_INT_FLAG", ) string_flag( name = "my_string_flag", build_setting_default = "foo", make_variable = "MY_STRING_FLAG", ) sh_test( name = "make_variable_test", srcs = ["make_variable_test.sh"], env = { "MESSAGE": "Hello, $(MY_STRING_FLAG)! My name is $(MY_INT_FLAG).", }, toolchains = [ ":my_int_flag", ":my_string_flag", ], ) bazel-skylib-1.9.1/tests/common_settings/make_variable_test.sh000077500000000000000000000012411517445036200246510ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2023 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. [[ "$MESSAGE" == "Hello, foo! My name is 42." ]] bazel-skylib-1.9.1/tests/common_settings_test.sh000077500000000000000000000111471517445036200220750ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # End to end tests for common_settings.bzl # --- begin runfiles.bash initialization --- set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function create_volcano_pkg() { local -r pkg="$1" mkdir -p "$pkg" cd "$pkg" cat > WORKSPACE < rules/BUILD < volcano/rules.bzl < volcano/BUILD <"$TEST_log" 2>&1 || fail "Expected test to pass" expect_log "active = False" expect_log "height = 8366" expect_log "namer = \"puyallup-tribe\"" expect_log "nicknames = \[\"volcano-mc-volcanoface\"\]" } function test_cannot_set_settings() { local -r pkg="${FUNCNAME[0]}" create_volcano_pkg "$pkg" bazel build volcano:mt-st-helens --//volcano:height-setting=8366 \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log "Unrecognized option: //volcano:height-setting" } function test_not_allowed_value() { local -r pkg="${FUNCNAME[0]}" create_volcano_pkg "$pkg" bazel build volcano:mt-st-helens --//volcano:namer-flag=me \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log "Error setting //volcano:namer-flag: invalid value 'me'. Allowed values are" } cd "$TEST_TMPDIR" run_suite "common_settings test suite" bazel-skylib-1.9.1/tests/common_settings_tests.bzl000066400000000000000000000116101517445036200224250ustar00rootroot00000000000000# Copyright 2023 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Analysis tests for common_settings.bzl.""" load("//lib:unittest.bzl", "analysistest", "asserts") load("//rules:common_settings.bzl", "int_flag", "int_setting", "string_flag", "string_setting") def _template_variable_info_contents_test_impl(ctx): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) if ctx.attr.expected: asserts.equals( env, expected = ctx.attr.expected, actual = target_under_test[platform_common.TemplateVariableInfo].variables, ) else: asserts.false(env, platform_common.TemplateVariableInfo in target_under_test) return analysistest.end(env) _template_variable_info_contents_test = analysistest.make( _template_variable_info_contents_test_impl, attrs = { "expected": attr.string_dict(), }, ) def _test_template_variable_info_contents(): int_flag( name = "my_int_flag", build_setting_default = 42, make_variable = "MY_INT_1", ) _template_variable_info_contents_test( name = "my_int_flag_test", target_under_test = ":my_int_flag", expected = { "MY_INT_1": "42", }, ) int_setting( name = "my_int_setting", build_setting_default = 21, make_variable = "MY_INT_2", ) _template_variable_info_contents_test( name = "my_int_setting_test", target_under_test = ":my_int_setting", expected = { "MY_INT_2": "21", }, ) string_flag( name = "my_string_flag", build_setting_default = "foo", make_variable = "MY_STRING_1", ) _template_variable_info_contents_test( name = "my_string_flag_test", target_under_test = ":my_string_flag", expected = { "MY_STRING_1": "foo", }, ) string_setting( name = "my_string_setting", build_setting_default = "bar", make_variable = "MY_STRING_2", ) _template_variable_info_contents_test( name = "my_string_setting_test", target_under_test = ":my_string_setting", expected = { "MY_STRING_2": "bar", }, ) string_flag( name = "my_string_flag_without_make_variable", build_setting_default = "foo", ) _template_variable_info_contents_test( name = "my_string_flag_without_make_variable_test", target_under_test = ":my_string_flag_without_make_variable", expected = {}, ) def _failure_test_impl(ctx): env = analysistest.begin(ctx) asserts.expect_failure(env, ctx.attr.expected_failure) return analysistest.end(env) _failure_test = analysistest.make( _failure_test_impl, attrs = { "expected_failure": attr.string(), }, expect_failure = True, ) def _test_make_variable_name_failures(): int_flag( name = "my_failing_int_flag", build_setting_default = 42, make_variable = "my_int_1", tags = ["manual"], ) _failure_test( name = "my_failing_int_flag_test", target_under_test = ":my_failing_int_flag", expected_failure = "Error setting //tests:my_failing_int_flag: invalid make variable name 'my_int_1'. Make variable names may only contain uppercase letters, digits, and underscores.", ) string_flag( name = "my_failing_string_flag", build_setting_default = "foo", make_variable = "MY STRING", tags = ["manual"], ) _failure_test( name = "my_failing_string_flag_test", target_under_test = ":my_failing_string_flag", expected_failure = "Error setting //tests:my_failing_string_flag: invalid make variable name 'MY STRING'. Make variable names may only contain uppercase letters, digits, and underscores.", ) def common_settings_test_suite(name = "common_settings_test_suite"): _test_template_variable_info_contents() _test_make_variable_name_failures() native.test_suite( name = "common_settings_test_suite", tests = [ "my_int_flag_test", "my_int_setting_test", "my_string_flag_test", "my_string_setting_test", "my_string_flag_without_make_variable_test", "my_failing_int_flag_test", "my_failing_string_flag_test", ], ) bazel-skylib-1.9.1/tests/copy_directory/000077500000000000000000000000001517445036200203215ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/copy_directory/BUILD.bazel000066400000000000000000000020441517445036200221770ustar00rootroot00000000000000# This package aids testing the 'copy_directory' rule. load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//rules:copy_directory.bzl", "copy_directory") load(":empty_directory.bzl", "empty_directory") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) # Copy of directory containing files a and b, and a subdir containing c copy_directory( name = "copy_of_dir_with_subdir", src = "dir_with_subdir", out = "dir_copy", ) empty_directory( name = "empty_dir", ) copy_directory( name = "copy_of_empty_dir", src = "empty_dir", out = "empty_dir_copy", ) copy_directory( name = "copy_of_dir_with_symlink", src = "dir_with_symlink", out = "dir_with_symlink_copy", ) sh_test( name = "copy_directory_tests", srcs = ["copy_directory_tests.sh"], data = [ ":copy_of_dir_with_subdir", ":copy_of_dir_with_symlink", ":copy_of_empty_dir", "//tests:unittest.bash", ], deps = ["@bazel_tools//tools/bash/runfiles"], ) bazel-skylib-1.9.1/tests/copy_directory/copy_directory_tests.sh000077500000000000000000000062171517445036200251460ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --- begin runfiles.bash initialization --- # Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function test_copy_dir_with_subdir__copies_a() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_copy)/a" >"$TEST_log" expect_log '^foo$' } function test_copy_dir_with_subdir__copies_b() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_copy)/b" >"$TEST_log" expect_log '^bar$' } function test_copy_dir_with_subdir__copies_c() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_copy)/subdir/c" >"$TEST_log" expect_log '^moocow$' } function test_copy_dir_with_subdir__correct_filecounts() { local -r dir_filecount=$(ls "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_copy)" | wc -l) assert_equals $dir_filecount 3 local -r subdir_filecount=$(ls "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_copy)/subdir" | wc -l) assert_equals $subdir_filecount 1 } function test_copy_empty_dir() { local -r filecount=$(ls "$(rlocation $TEST_WORKSPACE/tests/copy_directory/empty_dir_copy)" | wc -l) assert_equals $filecount 0 } function test_copy_dir_with_symlink__copies_file() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_with_symlink_copy)/file" >"$TEST_log" expect_log '^foo$' } function test_copy_dir_with_symlink__copies_symlink() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_directory/dir_with_symlink_copy)/symlink" >"$TEST_log" expect_log '^foo$' } run_suite "copy_directory test suite" bazel-skylib-1.9.1/tests/copy_directory/dir_with_subdir/000077500000000000000000000000001517445036200235025ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/copy_directory/dir_with_subdir/a000066400000000000000000000000031517445036200236360ustar00rootroot00000000000000foobazel-skylib-1.9.1/tests/copy_directory/dir_with_subdir/b000066400000000000000000000000031517445036200236370ustar00rootroot00000000000000barbazel-skylib-1.9.1/tests/copy_directory/dir_with_subdir/subdir/000077500000000000000000000000001517445036200247725ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/copy_directory/dir_with_subdir/subdir/c000066400000000000000000000000061517445036200251330ustar00rootroot00000000000000moocowbazel-skylib-1.9.1/tests/copy_directory/dir_with_symlink/000077500000000000000000000000001517445036200237005ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/copy_directory/dir_with_symlink/file000066400000000000000000000000031517445036200245330ustar00rootroot00000000000000foobazel-skylib-1.9.1/tests/copy_directory/dir_with_symlink/symlink000077700000000000000000000000001517445036200263032./fileustar00rootroot00000000000000bazel-skylib-1.9.1/tests/copy_directory/empty_directory.bzl000066400000000000000000000024541517445036200242610ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Creates an empty directory.""" def _empty_directory_impl(ctx): out = ctx.actions.declare_directory(ctx.attr.name) ctx.actions.run_shell( outputs = [out], command = "mkdir -p $@", arguments = [out.path], mnemonic = "EmptyDirectory", progress_message = "Creating empty directory %s" % out.path, use_default_shell_env = True, execution_requirements = {"no-remote": "1"}, # see rules/private/copy_directory_private.bzl ) return [DefaultInfo(files = depset(direct = [out]))] empty_directory = rule( implementation = _empty_directory_impl, provides = [DefaultInfo], doc = "Creates an empty directory with the same name as the target", ) bazel-skylib-1.9.1/tests/copy_file/000077500000000000000000000000001517445036200172345ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/copy_file/BUILD000066400000000000000000000114331517445036200200200ustar00rootroot00000000000000# This package aids testing the 'copy_file' rule. # # The package contains 4 copy_file rules: # - 'copy_src' and 'copy_gen' copy a source file and a generated file # respectively # - 'copy_xsrc' and 'copy_xgen' copy a source file and a generated file # respectively (both are shell scripts), and mark their output as executable # # The generated file is the output of the 'gen' genrule. # # The 'bin_src' and 'bin_gen' rules are sh_binary rules. They use the # 'copy_xsrc' and 'copy_xgen' rules respectively. The sh_binary rule requires # its source to be executable, so building these two rules successfully means # that 'copy_file' managed to make its output executable. # # The 'run_executables' genrule runs the 'bin_src' and 'bin_gen' binaries, # partly to ensure they can be run, and partly so we can observe their output # and assert the contents in the 'copy_file_tests' test. # # The 'file_deps' filegroup depends on 'copy_src'. The filegroup rule uses the # DefaultInfo.files field from its dependencies. When we data-depend on the # filegroup from 'copy_file_tests', we transitively data-depend on the # DefaultInfo.files of the 'copy_src' rule. # # The 'copy_file_tests' test is the actual integration test. It data-depends # on: # - the 'run_executables' rule, to get the outputs of 'bin_src' and 'bin_gen' # - the 'file_deps' rule, and by nature of using a filegroup, we get the files # from the DefaultInfo.files of the 'copy_file' rule, and thereby assert that # that field contains the output file of the rule # - the 'copy_nonempty_text' rule, and thereby on the DefaultInfo.runfiles field # of it, so we assert that that field contains the output file of the rule load("@rules_shell//shell:sh_binary.bzl", "sh_binary") load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//rules:copy_file.bzl", "copy_file") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) sh_test( name = "copy_file_tests", srcs = ["copy_file_tests.sh"], data = [ ":run_executables", # Use DefaultInfo.files from 'copy_src' (via 'file_deps'). ":file_deps", # Use DefaultInfo.runfiles from 'copy_gen'. ":copy_gen", ":copy_gen_symlink", "//tests:unittest.bash", ], deps = ["@bazel_tools//tools/bash/runfiles"], ) filegroup( name = "file_deps", # Use DefaultInfo.files from 'copy_src'. srcs = [ ":copy_src", ":copy_src_symlink", ], ) # If 'run_executables' is built, then 'bin_gen' and 'bin_src' are # executable, asserting that copy_file makes the output executable. genrule( name = "run_executables", outs = [ "xsrc-out-symlink.txt", "xgen-out-symlink.txt", "xsrc-out.txt", "xgen-out.txt", ], cmd = " && ".join([ "$(location :bin_src_symlink) > $(location xsrc-out-symlink.txt)", "$(location :bin_gen_symlink) > $(location xgen-out-symlink.txt)", "$(location :bin_src) > $(location xsrc-out.txt)", "$(location :bin_gen) > $(location xgen-out.txt)", ]), output_to_bindir = 1, tools = [ ":bin_gen", ":bin_gen_symlink", ":bin_src", ":bin_src_symlink", ], ) # If 'bin_src' is built, then 'copy_xsrc' made its output executable. sh_binary( name = "bin_src", srcs = [":copy_xsrc"], ) # If 'bin_src' is built, then 'copy_xsrc' made its output executable. sh_binary( name = "bin_src_symlink", srcs = [":copy_xsrc_symlink"], ) # If 'bin_gen' is built, then 'copy_xgen' made its output executable. sh_binary( name = "bin_gen", srcs = [":copy_xgen"], ) # If 'bin_gen' is built, then 'copy_xgen' made its output executable. sh_binary( name = "bin_gen_symlink", srcs = [":copy_xgen_symlink"], ) copy_file( name = "copy_src", src = "a.txt", out = "out/a-out.txt", ) copy_file( name = "copy_src_symlink", src = "a.txt", out = "out/a-out-symlink.txt", allow_symlink = True, ) copy_file( name = "copy_gen", src = ":gen", out = "out/gen-out.txt", allow_symlink = True, ) copy_file( name = "copy_gen_symlink", src = ":gen", out = "out/gen-out-symlink.txt", ) copy_file( name = "copy_xsrc", src = "a.txt", out = "xout/a-out.sh", is_executable = True, ) copy_file( name = "copy_xsrc_symlink", src = "a_with_exec_bit.txt", out = "xout/a-out-symlink.sh", allow_symlink = True, is_executable = True, ) copy_file( name = "copy_xgen", src = ":gen", out = "xout/gen-out.sh", is_executable = True, ) copy_file( name = "copy_xgen_symlink", src = ":gen", out = "xout/gen-out-symlink.sh", allow_symlink = True, is_executable = True, ) genrule( name = "gen", outs = ["b.txt"], cmd = "echo -e '#!/usr/bin/env bash\necho potato' > $@", ) bazel-skylib-1.9.1/tests/copy_file/a.txt000066400000000000000000000000351517445036200202130ustar00rootroot00000000000000#!/usr/bin/env bash echo aaa bazel-skylib-1.9.1/tests/copy_file/a_with_exec_bit.txt000077500000000000000000000000351517445036200231130ustar00rootroot00000000000000#!/usr/bin/env bash echo aaa bazel-skylib-1.9.1/tests/copy_file/copy_file_tests.sh000077500000000000000000000061441517445036200227730ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --- begin runfiles.bash initialization --- # Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function test_copy_src() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/out/a-out.txt)" >"$TEST_log" expect_log '^#!/usr/bin/env bash$' expect_log '^echo aaa$' } function test_copy_src_symlink() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/out/a-out-symlink.txt)" >"$TEST_log" expect_log '^#!/usr/bin/env bash$' expect_log '^echo aaa$' } function test_copy_gen() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/out/gen-out.txt)" >"$TEST_log" expect_log '^#!/usr/bin/env bash$' expect_log '^echo potato$' } function test_copy_gen_symlink() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/out/gen-out-symlink.txt)" >"$TEST_log" expect_log '^#!/usr/bin/env bash$' expect_log '^echo potato$' } function test_copy_xsrc() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/xsrc-out.txt)" >"$TEST_log" expect_log '^aaa$' } function test_copy_xsrc_symlink() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/xsrc-out-symlink.txt)" >"$TEST_log" expect_log '^aaa$' } function test_copy_xgen() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/xgen-out.txt)" >"$TEST_log" expect_log '^potato$' } function test_copy_xgen_symlink() { cat "$(rlocation $TEST_WORKSPACE/tests/copy_file/xgen-out-symlink.txt)" >"$TEST_log" expect_log '^potato$' } run_suite "copy_file_tests test suite" bazel-skylib-1.9.1/tests/dicts_tests.bzl000066400000000000000000000125501517445036200203270ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for dicts.bzl.""" load("//lib:dicts.bzl", "dicts") load("//lib:unittest.bzl", "asserts", "unittest") def _add_test(ctx): """Unit tests for dicts.add.""" env = unittest.begin(ctx) # Test zero- and one-argument behavior. asserts.equals(env, {}, dicts.add()) asserts.equals(env, {"a": 1}, dicts.add({"a": 1})) asserts.equals(env, {"a": 1}, dicts.add(a = 1)) asserts.equals(env, {"a": 1, "b": 2}, dicts.add({"a": 1}, b = 2)) # Test simple two-argument behavior. asserts.equals(env, {"a": 1, "b": 2}, dicts.add({"a": 1}, {"b": 2})) asserts.equals(env, {"a": 1, "b": 2, "c": 3}, dicts.add({"a": 1}, {"b": 2}, c = 3)) # Test simple more-than-two-argument behavior. asserts.equals( env, {"a": 1, "b": 2, "c": 3, "d": 4}, dicts.add({"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}), ) asserts.equals( env, {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, dicts.add({"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}, e = 5), ) # Test same-key overriding. asserts.equals(env, {"a": 100}, dicts.add({"a": 1}, {"a": 100})) asserts.equals(env, {"a": 100}, dicts.add({"a": 1}, a = 100)) asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {"a": 100}, {"a": 10})) asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {"a": 100}, a = 10)) asserts.equals( env, {"a": 100, "b": 10}, dicts.add({"a": 1}, {"a": 100}, {"b": 10}), ) asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {}, {"a": 10})) asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {}, a = 10)) asserts.equals( env, {"a": 10, "b": 5}, dicts.add({"a": 1}, {"a": 10, "b": 5}), ) asserts.equals( env, {"a": 10, "b": 5}, dicts.add({"a": 1}, a = 10, b = 5), ) # Test some other boundary cases. asserts.equals(env, {"a": 1}, dicts.add({"a": 1}, {})) # Since dictionaries are passed around by reference, make sure that the # result of dicts.add is always a *copy* by modifying it afterwards and # ensuring that the original argument doesn't also reflect the change. We do # this to protect against someone who might attempt to optimize the function # by returning the argument itself in the one-argument case. original = {"a": 1} result = dicts.add(original) result["a"] = 2 asserts.equals(env, 1, original["a"]) return unittest.end(env) add_test = unittest.make(_add_test) def _omit_test(ctx): """Unit tests for dicts.omit.""" env = unittest.begin(ctx) # Test empty dict, empty list. asserts.equals(env, {}, dicts.omit({}, [])) # Test empty dict, nonempty list. asserts.equals(env, {}, dicts.omit({}, ["a"])) # Test nonempty dict, empty list. asserts.equals(env, {"a": 1}, dicts.omit({"a": 1}, [])) # Test key in dict. asserts.equals(env, {}, dicts.omit({"a": 1}, ["a"])) # Test key not in dict. asserts.equals(env, {"a": 1}, dicts.omit({"a": 1}, ["b"])) # Since dictionaries are passed around by reference, make sure that the # result of dicts.omit is always a *copy* by modifying it afterwards and # ensuring that the original argument doesn't also reflect the change. We do # this to protect against someone who might attempt to optimize the function # by returning the argument itself in the empty list case. original = {"a": 1} result = dicts.omit(original, []) result["a"] = 2 asserts.equals(env, 1, original["a"]) return unittest.end(env) omit_test = unittest.make(_omit_test) def _pick_test(ctx): """Unit tests for dicts.pick.""" env = unittest.begin(ctx) # Test empty dict, empty list. asserts.equals(env, {}, dicts.pick({}, [])) # Test empty dict, nonempty list. asserts.equals(env, {}, dicts.pick({}, ["a"])) # Test nonempty dict, empty list. asserts.equals(env, {}, dicts.pick({"a": 1}, [])) # Test key in dict. asserts.equals(env, {"a": 1}, dicts.pick({"a": 1}, ["a"])) # Test key not in dict. asserts.equals(env, {}, dicts.pick({"a": 1}, ["b"])) # Since dictionaries are passed around by reference, make sure that the # result of dicts.pick is always a *copy* by modifying it afterwards and # ensuring that the original argument doesn't also reflect the change. We do # this to protect against someone who might attempt to optimize the function # by returning the argument itself. original = {"a": 1} result = dicts.pick(original, ["a"]) result["a"] = 2 asserts.equals(env, 1, original["a"]) return unittest.end(env) pick_test = unittest.make(_pick_test) def dicts_test_suite(): """Creates the test targets and test suite for dicts.bzl tests.""" unittest.suite( "dicts_tests", add_test, omit_test, pick_test, ) bazel-skylib-1.9.1/tests/diff_test/000077500000000000000000000000001517445036200172325ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/diff_test/BUILD000066400000000000000000000017341517445036200200210ustar00rootroot00000000000000# This package aids testing the 'diff_test' rule. load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//rules:diff_test.bzl", "diff_test") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) sh_test( name = "diff_test_tests", srcs = ["diff_test_tests.sh"], data = [ "//rules:diff_test", "//tests:unittest.bash", ], # Test marked local because it uses bazel. tags = ["local"], deps = ["@bazel_tools//tools/bash/runfiles"], ) diff_test( name = "same_src_src", file1 = "a.txt", file2 = "aa.txt", ) diff_test( name = "same_src_gen", file1 = "a.txt", file2 = "a-gen.txt", ) diff_test( name = "same_gen_gen", file1 = "a-gen.txt", file2 = "aa-gen.txt", ) genrule( name = "gen", outs = [ "a-gen.txt", "aa-gen.txt", ], cmd = "echo -n 'potato' > $(location a-gen.txt) && echo -n 'potato' > $(location aa-gen.txt)", ) bazel-skylib-1.9.1/tests/diff_test/a.txt000066400000000000000000000000061517445036200202070ustar00rootroot00000000000000potatobazel-skylib-1.9.1/tests/diff_test/aa.txt000066400000000000000000000000061517445036200203500ustar00rootroot00000000000000potatobazel-skylib-1.9.1/tests/diff_test/b.txt000066400000000000000000000000031517445036200202050ustar00rootroot00000000000000foobazel-skylib-1.9.1/tests/diff_test/diff_test_tests.sh000077500000000000000000000215261517445036200227700ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --- begin runfiles.bash initialization --- # Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function import_diff_test() { local -r repo="$1" mkdir -p "${repo}/rules" mkdir -p "${repo}/lib" touch "${repo}/lib/BUILD" touch "${repo}/WORKSPACE" ln -sf "$(rlocation $TEST_WORKSPACE/rules/diff_test.bzl)" \ "${repo}/rules/diff_test.bzl" ln -sf "$(rlocation $TEST_WORKSPACE/lib/shell.bzl)" \ "${repo}/lib/shell.bzl" echo "exports_files(['diff_test.bzl'])" > "${repo}/rules/BUILD" } function assert_simple_diff_test() { local -r flags="$1" local -r ws="${TEST_TMPDIR}/$2" local -r subdir="$3" import_diff_test "$ws" touch "$ws/WORKSPACE" cat >"$ws/MODULE.bazel" <<'eof' bazel_dep(name = "platforms", version = "0.0.10") eof mkdir -p "$ws/$subdir" cat >"$ws/${subdir}BUILD" <<'eof' load("//rules:diff_test.bzl", "diff_test") diff_test( name = "same", file1 = "a.txt", file2 = "a.txt", ) diff_test( name = "different", file1 = "a.txt", file2 = "b.txt", ) eof echo foo > "$ws/$subdir/a.txt" echo bar > "$ws/$subdir/b.txt" (cd "$ws" && \ bazel test ${flags} "//${subdir%/}:same" --test_output=errors 1>"$TEST_log" 2>&1 \ || fail "expected success") (cd "$ws" && \ bazel test ${flags} "//${subdir%/}:different" --test_output=errors 1>"$TEST_log" 2>&1 \ && fail "expected failure" || true) expect_log "FAIL: files \"${subdir}a.txt\" and \"${subdir}b.txt\" differ" } function assert_from_ext_repo() { local -r flags="$1" local -r ws="${TEST_TMPDIR}/$2" # Import the rule to an external repository. import_diff_test "$ws/bzl" mkdir -p "$ws/ext1/foo" "$ws/main/ext1/foo" "$ws/ext2/foo" "$ws/main/ext2/foo" cat >"$ws/main/WORKSPACE" <<'eof' local_repository( name = "bzl", path = "../bzl", ) local_repository( name = "ext1", path = "../ext1", ) local_repository( name = "ext2", path = "../ext2", ) eof cat >"$ws/main/MODULE.bazel" <<'eof' bazel_dep(name = "platforms", version = "0.0.10") local_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:local.bzl", "local_repository") local_repository( name = "bzl", path = "../bzl", ) local_repository( name = "ext1", path = "../ext1", ) local_repository( name = "ext2", path = "../ext2", ) eof # @ext1 has source files touch "$ws/ext1/WORKSPACE" echo 'exports_files(["foo.txt"])' >"$ws/ext1/foo/BUILD" echo 'foo' > "$ws/ext1/foo/foo.txt" # @//ext1/foo has different files than @ext1//foo echo 'exports_files(["foo.txt"])' >"$ws/main/ext1/foo/BUILD" echo 'not foo' > "$ws/main/ext1/foo/foo.txt" # @ext2 has generated files touch "$ws/ext2/WORKSPACE" cat >"$ws/ext2/foo/BUILD" <<'eof' genrule( name = "gen", outs = [ "foo.txt", "bar.txt", ], cmd = "echo 'foo' > $(location foo.txt) && echo 'bar' > $(location bar.txt)", visibility = ["//visibility:public"], ) eof # @//ext2/foo has different files than @ext2//foo cat >"$ws/main/ext2/foo/BUILD" <<'eof' genrule( name = "gen", outs = ["foo.txt"], cmd = "echo 'not foo' > $@", visibility = ["//visibility:public"], ) eof cat >"$ws/main/BUILD" <<'eof' load("@bzl//rules:diff_test.bzl", "diff_test") diff_test( name = "same", file1 = "@ext1//foo:foo.txt", file2 = "@ext2//foo:foo.txt", ) diff_test( name = "different1", file1 = "@ext1//foo:foo.txt", file2 = "@ext2//foo:bar.txt", ) diff_test( name = "different2", file1 = "@ext1//foo:foo.txt", file2 = "//ext1/foo:foo.txt", ) diff_test( name = "different3", file1 = "//ext2/foo:foo.txt", file2 = "@ext2//foo:foo.txt", ) eof (cd "$ws/main" && \ bazel test ${flags} //:same --test_output=errors 1>"$TEST_log" 2>&1 \ || fail "expected success") (cd "$ws/main" && \ bazel test ${flags} //:different1 --test_output=errors 1>"$TEST_log" 2>&1 \ && fail "expected failure" || true) expect_log 'FAIL: files "external/.*ext1/foo/foo.txt" and "external/.*ext2/foo/bar.txt" differ' (cd "$ws/main" && \ bazel test ${flags} //:different2 --test_output=errors 1>"$TEST_log" 2>&1 \ && fail "expected failure" || true) expect_log 'FAIL: files "external/.*ext1/foo/foo.txt" and "ext1/foo/foo.txt" differ' (cd "$ws/main" && \ bazel test ${flags} //:different3 --test_output=errors 1>"$TEST_log" 2>&1 \ && fail "expected failure" || true) expect_log 'FAIL: files "ext2/foo/foo.txt" and "external/.*ext2/foo/foo.txt" differ' } function test_simple_diff_test_with_legacy_external_runfiles() { assert_simple_diff_test "--enable_runfiles --legacy_external_runfiles" "${FUNCNAME[0]}" "" } function test_simple_diff_test_without_legacy_external_runfiles() { assert_simple_diff_test "--enable_runfiles --nolegacy_external_runfiles" "${FUNCNAME[0]}" "" } function test_simple_diff_test_with_manifest() { assert_simple_diff_test "--noenable_runfiles" "${FUNCNAME[0]}" "" } function test_directory_named_external_with_legacy_external_runfiles() { assert_simple_diff_test "--enable_runfiles --legacy_external_runfiles" "${FUNCNAME[0]}" "path/to/directory/external/in/name/" } function test_directory_named_external_without_legacy_external_runfiles() { assert_simple_diff_test "--enable_runfiles --nolegacy_external_runfiles" "${FUNCNAME[0]}" "path/to/directory/external/in/name/" } function test_directory_named_external_with_manifest() { assert_simple_diff_test "--noenable_runfiles" "${FUNCNAME[0]}" "path/to/directory/external/in/name/" } function test_from_ext_repo_with_legacy_external_runfiles() { assert_from_ext_repo "--enable_runfiles --legacy_external_runfiles" "${FUNCNAME[0]}" } function test_from_ext_repo_without_legacy_external_runfiles() { assert_from_ext_repo "--enable_runfiles --nolegacy_external_runfiles" "${FUNCNAME[0]}" } function test_from_ext_repo_with_manifest() { assert_from_ext_repo "--noenable_runfiles" "${FUNCNAME[0]}" } function test_failure_message() { local -r ws="${TEST_TMPDIR}/${FUNCNAME[0]}" import_diff_test "$ws" touch "$ws/WORKSPACE" cat >"$ws/MODULE.bazel" <<'eof' bazel_dep(name = "platforms", version = "0.0.10") eof cat >"$ws/BUILD" <<'eof' load("//rules:diff_test.bzl", "diff_test") diff_test( name = "different_with_message", failure_message = "This is an `$error`", # TODO(arostovtsev): also test Windows cmd.exe escapes when https://github.com/bazelbuild/bazel-skylib/pull/363 is merged file1 = "a.txt", file2 = "b.txt", ) diff_test( name = "different_without_message", file1 = "c.txt", file2 = "d.txt", ) eof echo foo > "$ws/a.txt" echo bar > "$ws/b.txt" echo foo > "$ws/c.txt" echo bar > "$ws/d.txt" (cd "$ws" && \ bazel test //:different_with_message --test_output=errors 1>"$TEST_log" 2>&1 \ && fail "expected failure" || true) # TODO(arostovtsev): also test Windows cmd.exe escapes when https://github.com/bazelbuild/bazel-skylib/pull/363 is merged expect_log "FAIL: files \"a.txt\" and \"b.txt\" differ. This is an \`\$error\`" (cd "$ws" && \ bazel test //:different_without_message --test_output=errors 1>"$TEST_log" 2>&1 \ && fail "expected failure" || true) expect_log "FAIL: files \"c.txt\" and \"d.txt\" differ. $" } cd "$TEST_TMPDIR" run_suite "diff_test_tests test suite" bazel-skylib-1.9.1/tests/directory/000077500000000000000000000000001517445036200172675ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/directory/BUILD000066400000000000000000000014521517445036200200530ustar00rootroot00000000000000load("@bazel_skylib//rules:copy_file.bzl", "copy_file") load("@bazel_skylib//rules/directory:directory.bzl", "directory") load(":directory_test.bzl", "directory_test_suite") load(":glob_test.bzl", "glob_test_suite") load(":subdirectory_test.bzl", "subdirectory_test_suite") package(default_applicable_licenses = ["@bazel_skylib//:license"]) directory( name = "root", srcs = glob(["testdata/**"]), ) filegroup( name = "f1_filegroup", srcs = ["testdata/f1"], ) filegroup( name = "f2_filegroup", srcs = ["testdata/subdir/f2"], ) copy_file( name = "generated_file", src = "testdata/f1", out = "dir/generated", ) directory_test_suite( name = "directory_tests", ) glob_test_suite( name = "glob_tests", ) subdirectory_test_suite( name = "subdirectory_tests", ) bazel-skylib-1.9.1/tests/directory/directory_test.bzl000066400000000000000000000123461517445036200230510ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for the directory rule.""" load("@bazel_skylib//rules/directory:directory.bzl", "directory") load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo") load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") load("@rules_testing//lib:truth.bzl", "matching") load(":utils.bzl", "directory_subject", "failure_matching", "failure_test") def _source_root_test(name): analysis_test( name = name, impl = _source_root_test_impl, targets = { "root": ":root", "f1": ":f1_filegroup", "f2": ":f2_filegroup", }, ) def _source_root_test_impl(env, targets): f1 = targets.f1[DefaultInfo].files.to_list()[0] f2 = targets.f2[DefaultInfo].files.to_list()[0] env.expect.that_collection(targets.root[DefaultInfo].files.to_list()).contains_exactly( [f1, f2], ) human_readable = str(targets.root.label) root = directory_subject(env, targets.root[DirectoryInfo]) root.entries().keys().contains_exactly(["testdata"]) root.transitive_files().contains_exactly([f1, f2]).in_order() root.human_readable().equals(human_readable) env.expect.that_str(root.actual.path + "/testdata/f1").equals(f1.path) testdata = directory_subject(env, root.actual.entries["testdata"]) testdata.entries().keys().contains_exactly(["f1", "subdir"]) testdata.human_readable().equals(human_readable + "/testdata") subdir = directory_subject(env, testdata.actual.entries["subdir"]) subdir.entries().contains_exactly({"f2": f2}) subdir.transitive_files().contains_exactly([f2]) env.expect.that_str(subdir.actual.path + "/f2").equals(f2.path) def _generated_root_test(name): subject_name = "_%s_subject" % name directory( name = subject_name, srcs = [":generated_file"], ) analysis_test( name = name, impl = _generated_root_test_impl, targets = { "root": subject_name, "generated": ":generated_file", }, ) def _generated_root_test_impl(env, targets): generated = targets.generated[DefaultInfo].files.to_list()[0] env.expect.that_collection(targets.root[DefaultInfo].files.to_list()).contains_exactly( [generated], ) human_readable = str(targets.root.label) root = directory_subject(env, targets.root[DirectoryInfo]) root.entries().keys().contains_exactly(["dir"]) root.transitive_files().contains_exactly([generated]).in_order() root.human_readable().equals(human_readable) env.expect.that_str(root.actual.path + "/dir/generated").equals(generated.path) dir = directory_subject(env, root.actual.entries["dir"]) dir.human_readable().equals(human_readable + "/dir") dir.entries().contains_exactly({"generated": generated}) dir.transitive_files().contains_exactly([generated]) env.expect.that_str(dir.actual.path + "/generated").equals(generated.path) def _no_srcs_test(name): subject_name = "_%s_subject" % name directory( name = subject_name, ) analysis_test( name = name, impl = _no_srcs_test_impl, targets = { "root": subject_name, "f1": ":f1_filegroup", }, ) def _no_srcs_test_impl(env, targets): f1 = targets.f1[DefaultInfo].files.to_list()[0] env.expect.that_collection(targets.root[DefaultInfo].files.to_list()).contains_exactly([]) d = directory_subject(env, targets.root[DirectoryInfo]) d.entries().contains_exactly({}) env.expect.that_str(d.actual.path + "/testdata/f1").equals(f1.path) def _directory_with_self_srcs_test(name): failure_test( name = name, impl = failure_matching(matching.contains("tests/directory to start with")), rule = directory, srcs = ["."], ) def _outside_testdata_test(name): failure_test( name = name, impl = failure_matching(matching.contains("lib/paths.bzl to start with")), rule = directory, srcs = ["@bazel_skylib//lib:paths"], ) def _source_and_generated_root_test(name): failure_test( name = name, impl = failure_matching(matching.contains( "Having both source and generated files in a single directory is unsupported", )), rule = directory, srcs = ["f1", ":generated_file"], ) # buildifier: disable=function-docstring def directory_test_suite(name): test_suite( name = name, tests = [ _source_root_test, _generated_root_test, _no_srcs_test, _directory_with_self_srcs_test, _outside_testdata_test, _source_and_generated_root_test, ], ) bazel-skylib-1.9.1/tests/directory/external_directory_tests.bzl000066400000000000000000000037261517445036200251400ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Generates tests for the directory rules from outside the repository.""" _ROOT_BUILD_FILE_CONTENTS = """ load("@bazel_skylib//rules/directory:directory.bzl", "directory") directory( name = "root", srcs = ["BUILD"], ) """ def _external_directory_tests_impl(repo_ctx): for f in repo_ctx.attr.files: repo_ctx.symlink(repo_ctx.path(f), f.package + "/" + f.name) repo_ctx.file("BUILD", _ROOT_BUILD_FILE_CONTENTS) # Directory paths work differently while inside and outside the repository. # To properly test this, we copy all our test code to an external # repository. external_directory_tests = repository_rule( implementation = _external_directory_tests_impl, attrs = { "files": attr.label_list(default = [ "//tests/directory:BUILD", "//tests/directory:directory_test.bzl", "//tests/directory:glob_test.bzl", "//tests/directory:subdirectory_test.bzl", "//tests/directory:testdata/f1", "//tests/directory:testdata/subdir/f2", "//tests/directory:utils.bzl", ]), }, ) def _external_directory_tests_ext_impl(_module_ctx): external_directory_tests(name = "external_directory_tests") # use_repo_rule would be preferred, but it isn't supported in bazel 6. external_directory_tests_ext = module_extension( implementation = _external_directory_tests_ext_impl, ) bazel-skylib-1.9.1/tests/directory/glob_test.bzl000066400000000000000000000134671517445036200217750ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for the directory_glob rule.""" load("@bazel_skylib//rules/directory:glob.bzl", "directory_glob") load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo") # buildifier: disable=bzl-visibility load("@bazel_skylib//rules/directory/private:glob.bzl", "directory_glob_chunk", "transitive_entries") load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") load("@rules_testing//lib:truth.bzl", "matching") load(":utils.bzl", "failure_matching", "failure_test") def _expect_glob_chunk(env, directory, chunk): return env.expect.that_collection( directory_glob_chunk(directory, chunk), expr = "directory_glob_chunk({}, {})".format(directory.human_readable, repr(chunk)), ) def _expect_glob(env, directory, include, allow_empty = False): return env.expect.that_collection( directory.glob(include, allow_empty = allow_empty), expr = "directory_glob({}, {}, allow_empty={})".format(directory.human_readable, include, allow_empty), ) def _with_children(children): return DirectoryInfo( entries = {k: k for k in children}, human_readable = repr(children), ) def _glob_test(name): simple_name = "_simple_%s" % name exclude_name = "_exclude_%s" % name directory_glob( name = simple_name, srcs = ["testdata/f1"], data = ["testdata/subdir/f2"], directory = ":root", ) directory_glob( name = exclude_name, srcs = [ "testdata/f1", "nonexistent", ], allow_empty = True, data = ["**"], directory = ":root", exclude = ["testdata/f1"], ) analysis_test( name = name, impl = _glob_test_impl, targets = { "root": ":root", "f1": ":f1_filegroup", "f2": ":f2_filegroup", "simple_glob": simple_name, "glob_with_exclude": exclude_name, }, ) def _glob_test_impl(env, targets): f1 = targets.f1[DefaultInfo].files.to_list()[0] f2 = targets.f2[DefaultInfo].files.to_list()[0] root = targets.root[DirectoryInfo] testdata = root.entries["testdata"] subdir = testdata.entries["subdir"] env.expect.that_collection(transitive_entries(root)).contains_exactly([ root, testdata, subdir, f1, f2, ]) _expect_glob_chunk(env, testdata, "f1").contains_exactly([f1]) _expect_glob_chunk(env, root, "nonexistent").contains_exactly([]) _expect_glob_chunk(env, testdata, "f2").contains_exactly([]) _expect_glob_chunk(env, root, "testdata").contains_exactly([testdata]) _expect_glob_chunk(env, testdata, "*").contains_exactly( [f1, subdir], ) _expect_glob_chunk( env, _with_children(["a", "d", "abc", "abbc", "ab.bc", ".abbc", "abbc."]), "ab*bc", ).contains_exactly([ "abbc", "ab.bc", ]) _expect_glob_chunk( env, _with_children(["abbc", "abbbc", "ab.b.bc"]), "ab*b*bc", ).contains_exactly([ "abbbc", "ab.b.bc", ]) _expect_glob_chunk( env, _with_children(["a", "ab", "ba"]), "a*", ).contains_exactly([ "a", "ab", ]) _expect_glob_chunk( env, _with_children(["a", "ab", "a.b.", "ba."]), "a*b*", ).contains_exactly([ "ab", "a.b.", ]) _expect_glob(env, root, ["testdata/f1"]).contains_exactly([f1]) _expect_glob(env, root, ["testdata/subdir/f2"]).contains_exactly([f2]) _expect_glob(env, root, ["**"]).contains_exactly([f1, f2]) _expect_glob(env, root, ["**/f1"]).contains_exactly([f1]) _expect_glob(env, root, ["**/**/f1"]).contains_exactly([f1]) _expect_glob(env, root, ["testdata/*/f1"], allow_empty = True).contains_exactly([]) simple_glob = env.expect.that_target(targets.simple_glob) with_exclude = env.expect.that_target(targets.glob_with_exclude) env.expect.that_collection( simple_glob.actual[DefaultInfo].files.to_list(), expr = "simple_glob's files", ).contains_exactly([f1]) env.expect.that_collection( with_exclude.actual[DefaultInfo].files.to_list(), expr = "with_exclude's files", ).contains_exactly([]) # target.runfiles().contains_exactly() doesn't do what we want - it converts # it to a string corresponding to the runfiles import path. env.expect.that_collection( simple_glob.runfiles().actual.files.to_list(), expr = "simple_glob's runfiles", ).contains_exactly([f1, f2]) env.expect.that_collection( with_exclude.runfiles().actual.files.to_list(), expr = "with_exclude's runfiles", ).contains_exactly([f2]) def _glob_with_no_match_test(name): failure_test( name = name, impl = failure_matching(matching.contains('"nonexistent" failed to match any files in')), rule = directory_glob, srcs = [ "testdata/f1", "nonexistent", ], data = ["testdata/f1"], directory = ":root", ) # buildifier: disable=function-docstring def glob_test_suite(name): test_suite( name = name, tests = [ _glob_test, _glob_with_no_match_test, ], ) bazel-skylib-1.9.1/tests/directory/subdirectory_test.bzl000066400000000000000000000070271517445036200235630ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for subdirectory rules.""" load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo") load("@bazel_skylib//rules/directory:subdirectory.bzl", "subdirectory") load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") load("@rules_testing//lib:truth.bzl", "matching") load(":utils.bzl", "failure_matching", "failure_test") _NONEXISTENT_SUBDIRECTORY_ERR = """directory:root/testdata does not contain an entry named "nonexistent". Instead, it contains the following entries: f1 subdir """ def _subdirectory_test(name): testdata_name = "_%s_dir" % name subdir_name = "_%s_subdir" % name subdirectory( name = testdata_name, parent = ":root", path = "testdata", ) subdirectory( name = subdir_name, parent = ":root", path = "testdata/subdir", ) analysis_test( name = name, impl = _subdirectory_test_impl, targets = { "root": ":root", "testdata": testdata_name, "subdir": subdir_name, "f1": ":f1_filegroup", "f2": ":f2_filegroup", }, ) def _subdirectory_test_impl(env, targets): f1 = targets.f1[DefaultInfo].files.to_list()[0] f2 = targets.f2[DefaultInfo].files.to_list()[0] root = targets.root[DirectoryInfo] want_dir = root.entries["testdata"] want_subdir = want_dir.entries["subdir"] # Use that_str because it supports equality checks. They're not strings. env.expect.that_str(targets.testdata[DirectoryInfo]).equals(want_dir) env.expect.that_str(targets.subdir[DirectoryInfo]).equals(want_subdir) env.expect.that_collection( targets.testdata[DefaultInfo].files.to_list(), ).contains_exactly([f1, f2]) env.expect.that_collection( targets.subdir[DefaultInfo].files.to_list(), ).contains_exactly([f2]) def _nonexistent_subdirectory_test(name): failure_test( name = name, impl = failure_matching(matching.contains(_NONEXISTENT_SUBDIRECTORY_ERR)), rule = subdirectory, parent = ":root", path = "testdata/nonexistent", ) def _subdirectory_of_file_test(name): failure_test( name = name, impl = failure_matching(matching.contains("testdata/f1 to have type Directory, but got File")), rule = subdirectory, parent = ":root", path = "testdata/f1/foo", ) def _subdirectory_as_file_test(name): failure_test( name = name, impl = failure_matching(matching.contains("testdata/f1 to have type Directory, but got File")), rule = subdirectory, parent = ":root", path = "testdata/f1", ) # buildifier: disable=function-docstring def subdirectory_test_suite(name): test_suite( name = name, tests = [ _subdirectory_test, _nonexistent_subdirectory_test, _subdirectory_as_file_test, _subdirectory_of_file_test, ], ) bazel-skylib-1.9.1/tests/directory/testdata/000077500000000000000000000000001517445036200211005ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/directory/testdata/f1000066400000000000000000000000001517445036200213170ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/directory/testdata/subdir/000077500000000000000000000000001517445036200223705ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/directory/testdata/subdir/f2000066400000000000000000000000001517445036200226100ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/directory/utils.bzl000066400000000000000000000035721517445036200211470ustar00rootroot00000000000000# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helper functions for testing directory rules.""" load("@rules_testing//lib:analysis_test.bzl", "analysis_test") load("@rules_testing//lib:truth.bzl", "subjects") load("@rules_testing//lib:util.bzl", "util") _depset_as_list_subject = lambda value, *, meta: subjects.collection( value.to_list(), meta = meta, ) directory_info_subject = lambda value, *, meta: subjects.struct( value, meta = meta, attrs = dict( entries = subjects.dict, transitive_files = _depset_as_list_subject, path = subjects.str, human_readable = subjects.str, ), ) def failure_matching(matcher): def test(env, target): env.expect.that_target(target).failures().contains_exactly_predicates([ matcher, ]) return test def directory_subject(env, directory_info): return env.expect.that_value( value = directory_info, expr = "DirectoryInfo(%r)" % directory_info.path, factory = directory_info_subject, ) def failure_test(*, name, impl, rule, **kwargs): subject_name = "_%s_subject" % name util.helper_target( rule, name = subject_name, **kwargs ) analysis_test( name = name, expect_failure = True, impl = impl, target = subject_name, ) bazel-skylib-1.9.1/tests/expand_template/000077500000000000000000000000001517445036200204355ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/expand_template/BUILD000066400000000000000000000030501517445036200212150ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This package aids testing the 'diff_test' rule. load("@rules_cc//cc:cc_test.bzl", "cc_test") load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//rules:expand_template.bzl", "expand_template") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) expand_template( name = "filled_template", out = "foo/test.yaml", substitutions = { "@name@": "test", "@version@": "1.1.1", }, template = "test.tpl.yaml", ) sh_test( name = "template_test", srcs = ["template_test.sh"], data = [ "foo/test.yaml", ":filled_template", "//tests:unittest.bash", ], deps = [ "@bazel_tools//tools/bash/runfiles", ], ) expand_template( name = "version", out = "version.h", substitutions = { "@VERSION@": "2.3.4", }, template = "version.h.in", ) cc_test( name = "test", srcs = [ "test.cc", ":version", ], ) bazel-skylib-1.9.1/tests/expand_template/template_test.sh000077500000000000000000000031671517445036200236550ustar00rootroot00000000000000#!/usr/bin/env bash # Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --- begin runfiles.bash initialization v2 --- # Copy-pasted from the Bazel Bash runfiles library v2. set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ source "$0.runfiles/$f" 2>/dev/null || \ source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e # --- end runfiles.bash initialization v2 --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function test_expand_template() { cat "$(rlocation $TEST_WORKSPACE/tests/expand_template/foo/test.yaml)" >"$TEST_log" expect_log 'name: test' expect_log 'version: 1.1.1' } run_suite "expand_template_tests test suite"bazel-skylib-1.9.1/tests/expand_template/test.cc000066400000000000000000000015241517445036200217250ustar00rootroot00000000000000// Copyright 2022 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "tests/expand_template/version.h" #include int main(int argc, char **argv) { // VERSION should be "2.3.4" if(strcmp(VERSION, "2.3.4") == 0) { return 0; // success } else { return 1; // failure } } bazel-skylib-1.9.1/tests/expand_template/test.tpl.yaml000066400000000000000000000000401517445036200230700ustar00rootroot00000000000000name: @name@ version: @version@ bazel-skylib-1.9.1/tests/expand_template/version.h.in000066400000000000000000000000331517445036200226740ustar00rootroot00000000000000#define VERSION "@VERSION@"bazel-skylib-1.9.1/tests/modules_test.bzl000066400000000000000000000041511517445036200205040ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test usage of modules.bzl.""" load("//lib:modules.bzl", "modules") load("//rules:build_test.bzl", "build_test") def _repo_rule_impl(repository_ctx): repository_ctx.file("WORKSPACE") repository_ctx.file("BUILD", """exports_files(["hello"])""") repository_ctx.file("hello", "Hello, Bzlmod!") _repo_rule = repository_rule(_repo_rule_impl) def _workspace_macro(register_toolchains = False): _repo_rule(name = "foo") _repo_rule(name = "bar") if register_toolchains: native.register_toolchains() as_extension_test_ext = modules.as_extension( _workspace_macro, doc = "Only used for testing modules.as_extension().", ) def _use_all_repos_ext_impl(module_ctx): _repo_rule(name = "baz") _repo_rule(name = "qux") return modules.use_all_repos(module_ctx) use_all_repos_test_ext = module_extension( _use_all_repos_ext_impl, doc = "Only used for testing modules.use_all_repos().", ) # buildifier: disable=unnamed-macro def modules_test_suite(): """Creates the tests for modules.bzl if Bzlmod is enabled.""" # buildifier: disable=canonical-repository is_bzlmod_enabled = str(Label("//tests:module_tests.bzl")).startswith("@@") if not is_bzlmod_enabled: return build_test( name = "modules_as_extension_test", targets = [ "@foo//:hello", "@bar//:hello", ], ) build_test( name = "modules_use_all_repos_test", targets = [ "@baz//:hello", "@qux//:hello", ], ) bazel-skylib-1.9.1/tests/native_binary/000077500000000000000000000000001517445036200201155ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/native_binary/BUILD000066400000000000000000000114211517445036200206760ustar00rootroot00000000000000load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("//rules:copy_file.bzl", "copy_file") load("//rules:native_binary.bzl", "native_binary", "native_test") package( default_applicable_licenses = ["//:license"], default_testonly = 1, default_visibility = ["//visibility:private"], ) cc_binary( name = "assertarg", srcs = ["assertarg.cc"], ) cc_binary( name = "assertdata", srcs = ["assertdata.cc"], deps = ["@bazel_tools//tools/cpp/runfiles"], # Depends on the runfiles library but doesn't have data-dependencies, on # purpose. We supplement the runfiles in the native_binary / native_test # rule. ) cc_binary( name = "assertdata_with_runfiles", srcs = ["assertdata.cc"], # This version depends on runfiles directly, to ensure runfiles from the # binary are picked up by native_test/native_binary data = ["testdata.txt"], deps = ["@bazel_tools//tools/cpp/runfiles"], ) # A rule that copies "assertarg"'s output as an opaque executable, simulating a # binary that's not built from source and needs to be wrapped in native_binary. copy_file( name = "copy_assertarg_exe", src = ":assertarg", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "assertarg_copy.exe", is_executable = True, ) # A rule that copies "assertdata"'s output as an opaque executable, simulating a # binary that's not built from source and needs to be wrapped in native_binary. copy_file( name = "copy_assertdata_exe", src = ":assertdata", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "assertdata_copy.exe", is_executable = True, ) cc_binary( name = "assertenv", srcs = ["assertenv.cc"], ) # A rule that copies "assertenv"'s output as an opaque executable, simulating a # binary that's not built from source and needs to be wrapped in native_binary. copy_file( name = "copy_assertenv_exe", src = ":assertenv", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "assertenv_copy.exe", is_executable = True, ) _ARGS = [ "'a b'", "c\\ d", "$(location testdata.txt) $$(location testdata.txt) $(location testdata.txt)", "'$(location testdata.txt) $$(location testdata.txt) $(location testdata.txt)'", "$$TEST_SRCDIR", "$${TEST_SRCDIR}", ] native_binary( name = "args_bin", src = ":copy_assertarg_exe", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "args_bin.exe", args = _ARGS, # We only need the data-dependency for $(location) expansion. data = ["testdata.txt"], ) native_test( name = "args_test", src = ":copy_assertarg_exe", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "args_test.exe", args = _ARGS, # We only need the data-dependency for $(location) expansion. data = ["testdata.txt"], ) native_binary( name = "data_bin", src = ":copy_assertdata_exe", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "data_bin.exe", data = ["testdata.txt"], ) native_binary( name = "no_out_bin", src = ":copy_assertdata_exe", data = ["testdata.txt"], ) native_test( name = "data_test", src = ":copy_assertdata_exe", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "data_test.exe", data = ["testdata.txt"], ) native_test( name = "data_from_binary_test", src = ":assertdata_with_runfiles", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "data_from_binary_test.exe", ) native_binary( name = "env_bin", src = ":copy_assertenv_exe", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "env_bin.exe", env = {"TEST_ENV_VAR": "ENV_VALUE"}, ) native_test( name = "env_test", src = ":copy_assertenv_exe", # On Windows we need the ".exe" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".exe" on every platform. out = "env_test.exe", env = {"TEST_ENV_VAR": "ENV_VALUE"}, ) bazel-skylib-1.9.1/tests/native_binary/assertarg.cc000066400000000000000000000027031517445036200224210ustar00rootroot00000000000000// Copyright 2019 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include int main(int argc, char** argv) { static const char* kExpected[] = { "a b", "c d", "tests/native_binary/testdata.txt", "$(location", "testdata.txt)", "tests/native_binary/testdata.txt", "tests/native_binary/testdata.txt $(location testdata.txt) tests/native_binary/testdata.txt", "$TEST_SRCDIR", "${TEST_SRCDIR}", "", }; for (int i = 1; i < argc; ++i) { if (!kExpected[i - 1][0]) { fprintf(stderr, "too many arguments, expected only %d\n", i); return 1; } if (argc < i) { fprintf(stderr, "expected more than %d arguments\n", i); return 1; } if (strcmp(argv[i], kExpected[i - 1]) != 0) { fprintf(stderr, "argv[%d]=(%s), expected (%s)\n", i, argv[i], kExpected[i - 1]); return 1; } } return 0; } bazel-skylib-1.9.1/tests/native_binary/assertdata.cc000066400000000000000000000035321517445036200225620ustar00rootroot00000000000000// Copyright 2019 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "tools/cpp/runfiles/runfiles.h" using bazel::tools::cpp::runfiles::Runfiles; int main(int argc, char **argv) { std::string error; std::unique_ptr runfiles(Runfiles::Create(argv[0], &error)); if (runfiles == nullptr) { fprintf(stderr, "ERROR(" __FILE__ ":%d): Could not init runfiles\n", __LINE__); return 1; } char* workspace = getenv("TEST_WORKSPACE"); if (workspace == nullptr) { fprintf(stderr, "ERROR(" __FILE__ ":%d): envvar TEST_WORKSPACE is undefined\n", __LINE__); return 1; } // This should have runfiles, either from the binary itself or from the // native_test. std::string path = runfiles->Rlocation(std::string(workspace) + "/tests/native_binary/testdata.txt"); FILE *f = fopen(path.c_str(), "rt"); if (!f) { fprintf(stderr, "ERROR(" __FILE__ ":%d): Could not find runfile '%s'\n", __LINE__, path.c_str()); } char buf[6]; size_t s = fread(buf, 1, 5, f); fclose(f); buf[5] = 0; if (s != 5 || std::string("hello") != std::string(buf, 5)) { fprintf(stderr, "ERROR(" __FILE__ ":%d): bad runfile contents (%s)\n", __LINE__, buf); return 1; } return 0; } bazel-skylib-1.9.1/tests/native_binary/assertenv.cc000066400000000000000000000022511517445036200224360ustar00rootroot00000000000000// Copyright 2019 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include int main(int argc, char** argv) { static const std::pair kExpected[] = { {"TEST_ENV_VAR", "ENV_VALUE"}}; for (auto expected : kExpected) { const char* key = expected.first; const char* value = expected.second; if (strcmp(getenv(key), value)) { fprintf(stderr, "Expected %s to be %s, but it was %s\n", key, value, getenv(key)); return 1; } else { printf("key[%s]=(%s) OK\n", key, value); } } return 0; } bazel-skylib-1.9.1/tests/native_binary/testdata.txt000066400000000000000000000000061517445036200224630ustar00rootroot00000000000000hello bazel-skylib-1.9.1/tests/new_sets_tests.bzl000066400000000000000000000234271517445036200210550ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for new_sets.bzl.""" load("//lib:new_sets.bzl", "sets") load("//lib:unittest.bzl", "asserts", "unittest") def _is_equal_test(ctx): """Unit tests for sets.is_equal.""" # Note that if this test fails, the results for the other `sets` tests will # be inconclusive because they use `asserts.new_set_equals`, which in turn # calls `sets.is_equal`. env = unittest.begin(ctx) asserts.true(env, sets.is_equal(sets.make(), sets.make())) asserts.false(env, sets.is_equal(sets.make(), sets.make([1]))) asserts.false(env, sets.is_equal(sets.make([1]), sets.make())) asserts.true(env, sets.is_equal(sets.make([1]), sets.make([1]))) asserts.false(env, sets.is_equal(sets.make([1]), sets.make([1, 2]))) asserts.false(env, sets.is_equal(sets.make([1]), sets.make([2]))) asserts.false(env, sets.is_equal(sets.make([1]), sets.make([1, 2]))) # If passing a list, verify that duplicate elements are ignored. asserts.true(env, sets.is_equal(sets.make([1, 1]), sets.make([1]))) return unittest.end(env) is_equal_test = unittest.make(_is_equal_test) def _is_subset_test(ctx): """Unit tests for sets.is_subset.""" env = unittest.begin(ctx) asserts.true(env, sets.is_subset(sets.make(), sets.make())) asserts.true(env, sets.is_subset(sets.make(), sets.make([1]))) asserts.false(env, sets.is_subset(sets.make([1]), sets.make())) asserts.true(env, sets.is_subset(sets.make([1]), sets.make([1]))) asserts.true(env, sets.is_subset(sets.make([1]), sets.make([1, 2]))) asserts.false(env, sets.is_subset(sets.make([1]), sets.make([2]))) # If passing a list, verify that duplicate elements are ignored. asserts.true(env, sets.is_subset(sets.make([1, 1]), sets.make([1, 2]))) return unittest.end(env) is_subset_test = unittest.make(_is_subset_test) def _disjoint_test(ctx): """Unit tests for sets.disjoint.""" env = unittest.begin(ctx) asserts.true(env, sets.disjoint(sets.make(), sets.make())) asserts.true(env, sets.disjoint(sets.make(), sets.make([1]))) asserts.true(env, sets.disjoint(sets.make([1]), sets.make())) asserts.false(env, sets.disjoint(sets.make([1]), sets.make([1]))) asserts.false(env, sets.disjoint(sets.make([1]), sets.make([1, 2]))) asserts.true(env, sets.disjoint(sets.make([1]), sets.make([2]))) # If passing a list, verify that duplicate elements are ignored. asserts.false(env, sets.disjoint(sets.make([1, 1]), sets.make([1, 2]))) return unittest.end(env) disjoint_test = unittest.make(_disjoint_test) def _intersection_test(ctx): """Unit tests for sets.intersection.""" env = unittest.begin(ctx) asserts.new_set_equals(env, sets.make(), sets.intersection(sets.make(), sets.make())) asserts.new_set_equals(env, sets.make(), sets.intersection(sets.make(), sets.make([1]))) asserts.new_set_equals(env, sets.make(), sets.intersection(sets.make([1]), sets.make())) asserts.new_set_equals(env, sets.make([1]), sets.intersection(sets.make([1]), sets.make([1]))) asserts.new_set_equals(env, sets.make([1]), sets.intersection(sets.make([1]), sets.make([1, 2]))) asserts.new_set_equals(env, sets.make(), sets.intersection(sets.make([1]), sets.make([2]))) # If passing a list, verify that duplicate elements are ignored. asserts.new_set_equals(env, sets.make([1]), sets.intersection(sets.make([1, 1]), sets.make([1, 2]))) return unittest.end(env) intersection_test = unittest.make(_intersection_test) def _union_test(ctx): """Unit tests for sets.union.""" env = unittest.begin(ctx) asserts.new_set_equals(env, sets.make(), sets.union()) asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make([1]))) asserts.new_set_equals(env, sets.make(), sets.union(sets.make(), sets.make())) asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make(), sets.make([1]))) asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make([1]), sets.make())) asserts.new_set_equals(env, sets.make([1]), sets.union(sets.make([1]), sets.make([1]))) asserts.new_set_equals(env, sets.make([1, 2]), sets.union(sets.make([1]), sets.make([1, 2]))) asserts.new_set_equals(env, sets.make([1, 2]), sets.union(sets.make([1]), sets.make([2]))) # If passing a list, verify that duplicate elements are ignored. asserts.new_set_equals(env, sets.make([1, 2]), sets.union(sets.make([1, 1]), sets.make([1, 2]))) return unittest.end(env) union_test = unittest.make(_union_test) def _difference_test(ctx): """Unit tests for sets.difference.""" env = unittest.begin(ctx) asserts.new_set_equals(env, sets.make(), sets.difference(sets.make(), sets.make())) asserts.new_set_equals(env, sets.make(), sets.difference(sets.make(), sets.make([1]))) asserts.new_set_equals(env, sets.make([1]), sets.difference(sets.make([1]), sets.make())) asserts.new_set_equals(env, sets.make(), sets.difference(sets.make([1]), sets.make([1]))) asserts.new_set_equals(env, sets.make(), sets.difference(sets.make([1]), sets.make([1, 2]))) asserts.new_set_equals(env, sets.make([1]), sets.difference(sets.make([1]), sets.make([2]))) # If passing a list, verify that duplicate elements are ignored. asserts.new_set_equals(env, sets.make([2]), sets.difference(sets.make([1, 2]), sets.make([1, 1]))) return unittest.end(env) difference_test = unittest.make(_difference_test) def _to_list_test(ctx): """Unit tests for sets.to_list.""" env = unittest.begin(ctx) asserts.equals(env, [], sets.to_list(sets.make())) asserts.equals(env, [1], sets.to_list(sets.make([1, 1, 1]))) asserts.equals(env, [1, 2, 3], sets.to_list(sets.make([1, 2, 3]))) return unittest.end(env) to_list_test = unittest.make(_to_list_test) def _make_test(ctx): """Unit tests for sets.make.""" env = unittest.begin(ctx) asserts.equals(env, {}, sets.make()._values) asserts.equals(env, {x: None for x in [1, 2, 3]}, sets.make([1, 1, 2, 2, 3, 3])._values) return unittest.end(env) make_test = unittest.make(_make_test) def _copy_test(ctx): """Unit tests for sets.copy.""" env = unittest.begin(ctx) asserts.new_set_equals(env, sets.copy(sets.make()), sets.make()) asserts.new_set_equals(env, sets.copy(sets.make([1, 2, 3])), sets.make([1, 2, 3])) # Ensure mutating the copy does not mutate the original original = sets.make([1, 2, 3]) copy = sets.copy(original) copy._values[5] = None asserts.false(env, sets.is_equal(original, copy)) return unittest.end(env) copy_test = unittest.make(_copy_test) def _insert_test(ctx): """Unit tests for sets.insert.""" env = unittest.begin(ctx) asserts.new_set_equals(env, sets.make([1, 2, 3]), sets.insert(sets.make([1, 2]), 3)) # Ensure mutating the inserted set does mutate the original set. original = sets.make([1, 2, 3]) after_insert = sets.insert(original, 4) asserts.new_set_equals( env, original, after_insert, msg = "Insert creates a new set which is an O(n) operation, insert should be O(1).", ) return unittest.end(env) insert_test = unittest.make(_insert_test) def _contains_test(ctx): """Unit tests for sets.contains.""" env = unittest.begin(ctx) asserts.false(env, sets.contains(sets.make(), 1)) asserts.true(env, sets.contains(sets.make([1]), 1)) asserts.true(env, sets.contains(sets.make([1, 2]), 1)) asserts.false(env, sets.contains(sets.make([2, 3]), 1)) return unittest.end(env) contains_test = unittest.make(_contains_test) def _length_test(ctx): """Unit test for sets.length.""" env = unittest.begin(ctx) asserts.equals(env, 0, sets.length(sets.make())) asserts.equals(env, 1, sets.length(sets.make([1]))) asserts.equals(env, 2, sets.length(sets.make([1, 2]))) return unittest.end(env) length_test = unittest.make(_length_test) def _remove_test(ctx): """Unit test for sets.remove.""" env = unittest.begin(ctx) asserts.new_set_equals(env, sets.make([1, 2]), sets.remove(sets.make([1, 2, 3]), 3)) # Ensure mutating the inserted set does mutate the original set. original = sets.make([1, 2, 3]) after_removal = sets.remove(original, 3) asserts.new_set_equals(env, original, after_removal) return unittest.end(env) remove_test = unittest.make(_remove_test) def _repr_str_test(ctx): """Unit test for sets.repr and sets.str.""" env = unittest.begin(ctx) asserts.equals(env, "[]", sets.repr(sets.make())) asserts.equals(env, "[1]", sets.repr(sets.make([1]))) asserts.equals(env, "[1, 2]", sets.repr(sets.make([1, 2]))) asserts.equals(env, "[]", sets.str(sets.make())) asserts.equals(env, "[1]", sets.str(sets.make([1]))) asserts.equals(env, "[1, 2]", sets.str(sets.make([1, 2]))) return unittest.end(env) repr_str_test = unittest.make(_repr_str_test) def new_sets_test_suite(): """Creates the test targets and test suite for new_sets.bzl tests.""" unittest.suite( "new_sets_tests", disjoint_test, intersection_test, is_equal_test, is_subset_test, difference_test, union_test, to_list_test, make_test, copy_test, insert_test, contains_test, length_test, remove_test, repr_str_test, ) bazel-skylib-1.9.1/tests/partial_tests.bzl000066400000000000000000000074701517445036200206620ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for partial.bzl.""" load("//lib:partial.bzl", "partial") load("//lib:unittest.bzl", "asserts", "unittest") def _make_noargs_nokwargs(): """Test utility for no args no kwargs case""" return 1 def _make_args_nokwargs(arg1, arg2, arg3): """Test utility for args no kwargs case""" return arg1 + arg2 + arg3 def _make_args_kwargs(arg1, arg2, arg3, **kwargs): """Test utility for args and kwargs case""" return arg1 + arg2 + arg3 + kwargs["x"] + kwargs["y"] def _call_noargs_nokwargs(call_arg1): """Test utility no args no kwargs case where values passed from call site""" return call_arg1 def _call_args_nokwargs(func_arg1, call_arg1): """Test utility for args no kwargs case where values passed from call site""" return func_arg1 + call_arg1 def _call_args_kwargs(func_arg1, call_arg1, func_mult, call_mult): """Test utility for args and kwargs case where values passed from call site""" return (func_arg1 + call_arg1) * func_mult * call_mult def _make_call_test(ctx): """Unit tests for partial.make and partial.call.""" env = unittest.begin(ctx) # Test cases where there are no args (or kwargs) at the make site, only # at the call site. foo = partial.make(_make_noargs_nokwargs) asserts.equals(env, 1, partial.call(foo)) foo = partial.make(_make_args_nokwargs) asserts.equals(env, 6, partial.call(foo, 1, 2, 3)) foo = partial.make(_make_args_kwargs) asserts.equals(env, 15, partial.call(foo, 1, 2, 3, x = 4, y = 5)) # Test cases where there are args (and/or kwargs) at the make site and the # call site. foo = partial.make(_call_noargs_nokwargs, 100) asserts.equals(env, 100, partial.call(foo)) foo = partial.make(_call_args_nokwargs, 100) asserts.equals(env, 112, partial.call(foo, 12)) foo = partial.make(_call_args_kwargs, 100, func_mult = 10) asserts.equals(env, 2240, partial.call(foo, 12, call_mult = 2)) # Test case where there are args and kwargs ath the make site, and the call # site overrides some make site args. foo = partial.make(_call_args_kwargs, 100, func_mult = 10) asserts.equals(env, 1120, partial.call(foo, 12, func_mult = 5, call_mult = 2)) return unittest.end(env) make_call_test = unittest.make(_make_call_test) def _is_instance_test(ctx): """Unit test for partial.is_instance.""" env = unittest.begin(ctx) # We happen to use make_call_test here, but it could be any valid test rule. asserts.true(env, partial.is_instance(partial.make(make_call_test))) asserts.true(env, partial.is_instance(partial.make(make_call_test, timeout = "short"))) asserts.true(env, partial.is_instance(partial.make(make_call_test, timeout = "short", tags = ["foo"]))) asserts.false(env, partial.is_instance(None)) asserts.false(env, partial.is_instance({})) asserts.false(env, partial.is_instance(struct(foo = 1))) asserts.false(env, partial.is_instance(struct(function = "not really function"))) return unittest.end(env) is_instance_test = unittest.make(_is_instance_test) def partial_test_suite(): """Creates the test targets and test suite for partial.bzl tests.""" unittest.suite( "partial_tests", make_call_test, is_instance_test, ) bazel-skylib-1.9.1/tests/paths_tests.bzl000066400000000000000000000341351517445036200203430ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for paths.bzl.""" load("//lib:paths.bzl", "paths") load("//lib:unittest.bzl", "asserts", "unittest") def _basename_test(ctx): """Unit tests for paths.basename.""" env = unittest.begin(ctx) # Verify some degenerate cases. asserts.equals(env, "", paths.basename("")) asserts.equals(env, "", paths.basename("/")) asserts.equals(env, "bar", paths.basename("foo///bar")) # Verify some realistic cases. asserts.equals(env, "foo", paths.basename("foo")) asserts.equals(env, "foo", paths.basename("/foo")) asserts.equals(env, "foo", paths.basename("bar/foo")) asserts.equals(env, "foo", paths.basename("/bar/foo")) # Verify that we correctly duplicate Python's os.path.basename behavior, # where a trailing slash means the basename is empty. asserts.equals(env, "", paths.basename("foo/")) asserts.equals(env, "", paths.basename("/foo/")) return unittest.end(env) basename_test = unittest.make(_basename_test) def _dirname_test(ctx): """Unit tests for paths.dirname.""" env = unittest.begin(ctx) # Verify some degenerate cases. asserts.equals(env, "", paths.dirname("")) asserts.equals(env, "/", paths.dirname("/")) asserts.equals(env, "foo", paths.dirname("foo///bar")) # Verify some realistic cases. asserts.equals(env, "", paths.dirname("foo")) asserts.equals(env, "/", paths.dirname("/foo")) asserts.equals(env, "bar", paths.dirname("bar/foo")) asserts.equals(env, "/bar", paths.dirname("/bar/foo")) # Verify that we correctly duplicate Python's os.path.dirname behavior, # where a trailing slash means the dirname is the same as the original # path (without the trailing slash). asserts.equals(env, "foo", paths.dirname("foo/")) asserts.equals(env, "/foo", paths.dirname("/foo/")) return unittest.end(env) dirname_test = unittest.make(_dirname_test) def _is_absolute_test(ctx): """Unit tests for paths.is_absolute.""" env = unittest.begin(ctx) # Try a degenerate case. asserts.false(env, paths.is_absolute("")) # Try some relative paths. asserts.false(env, paths.is_absolute("foo")) asserts.false(env, paths.is_absolute("foo/")) asserts.false(env, paths.is_absolute("foo/bar")) # Try some Linux absolute paths. asserts.true(env, paths.is_absolute("/")) asserts.true(env, paths.is_absolute("/foo")) asserts.true(env, paths.is_absolute("/foo/")) asserts.true(env, paths.is_absolute("/foo/bar")) # Try some Windows absolute paths. asserts.true(env, paths.is_absolute("D:\\")) asserts.true(env, paths.is_absolute("C:\\")) asserts.true(env, paths.is_absolute("C:\\foo")) asserts.true(env, paths.is_absolute("C:\\foo\\bar")) return unittest.end(env) is_absolute_test = unittest.make(_is_absolute_test) def _join_test(ctx): """Unit tests for paths.join.""" env = unittest.begin(ctx) # Try a degenerate case. asserts.equals(env, "", paths.join("")) # Try some basic paths. asserts.equals(env, "foo", paths.join("foo")) asserts.equals(env, "foo/bar", paths.join("foo", "bar")) asserts.equals(env, "foo/bar/baz", paths.join("foo", "bar", "baz")) # Make sure an initially absolute path stays absolute. asserts.equals(env, "/foo", paths.join("/foo")) asserts.equals(env, "/foo/bar", paths.join("/foo", "bar")) # Make sure an absolute path later in the list resets the result. asserts.equals(env, "/baz", paths.join("foo", "bar", "/baz")) asserts.equals(env, "/baz", paths.join("foo", "/bar", "/baz")) asserts.equals(env, "/bar/baz", paths.join("foo", "/bar", "baz")) asserts.equals(env, "/bar", paths.join("/foo", "/bar")) # Make sure a leading empty segment doesn't make it absolute. asserts.equals(env, "foo", paths.join("", "foo")) # Try some trailing slash scenarios. asserts.equals(env, "foo/", paths.join("foo", "")) asserts.equals(env, "foo/", paths.join("foo/")) asserts.equals(env, "foo/", paths.join("foo/", "")) asserts.equals(env, "foo//", paths.join("foo//", "")) asserts.equals(env, "foo//", paths.join("foo//")) asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz", "")) asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz/")) asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz/", "")) # Make sure that adjacent empty segments don't add extra path separators. asserts.equals(env, "foo/", paths.join("foo", "", "")) asserts.equals(env, "foo", paths.join("", "", "foo")) asserts.equals(env, "foo/bar", paths.join("foo", "", "", "bar")) return unittest.end(env) join_test = unittest.make(_join_test) def _normalize_test(ctx): """Unit tests for paths.normalize.""" env = unittest.begin(ctx) # Try the most basic case. asserts.equals(env, ".", paths.normalize("")) # Try some basic adjacent-slash removal. asserts.equals(env, "foo/bar", paths.normalize("foo//bar")) asserts.equals(env, "foo/bar", paths.normalize("foo////bar")) # Try some "." removal. asserts.equals(env, "foo/bar", paths.normalize("foo/./bar")) asserts.equals(env, "foo/bar", paths.normalize("./foo/bar")) asserts.equals(env, "foo/bar", paths.normalize("foo/bar/.")) asserts.equals(env, "/", paths.normalize("/.")) # Try some ".." removal. asserts.equals(env, "bar", paths.normalize("foo/../bar")) asserts.equals(env, "foo", paths.normalize("foo/bar/..")) asserts.equals(env, ".", paths.normalize("foo/..")) asserts.equals(env, ".", paths.normalize("foo/bar/../..")) asserts.equals(env, "..", paths.normalize("foo/../..")) asserts.equals(env, "/", paths.normalize("/foo/../..")) asserts.equals(env, "../../c", paths.normalize("a/b/../../../../c/d/..")) # Make sure one or two initial slashes are preserved, but three or more are # collapsed to a single slash. asserts.equals(env, "/foo", paths.normalize("/foo")) asserts.equals(env, "//foo", paths.normalize("//foo")) asserts.equals(env, "/foo", paths.normalize("///foo")) # Trailing slashes should be removed unless the entire path is a trailing # slash. asserts.equals(env, "/", paths.normalize("/")) asserts.equals(env, "foo", paths.normalize("foo/")) asserts.equals(env, "foo/bar", paths.normalize("foo/bar/")) return unittest.end(env) normalize_test = unittest.make(_normalize_test) def _is_normalized_test(ctx): """Unit tests for paths.is_normalized.""" env = unittest.begin(ctx) # Try the most basic cases. asserts.true(env, paths.is_normalized("")) asserts.false(env, paths.is_normalized(".")) asserts.true(env, paths.is_normalized("/")) asserts.true(env, paths.is_normalized("/tmp")) asserts.true(env, paths.is_normalized("tmp")) asserts.true(env, paths.is_normalized("c:/")) asserts.false(env, paths.is_normalized("../a")) asserts.false(env, paths.is_normalized("a/..")) # Try some basic adjacent-slash removal. asserts.true(env, paths.is_normalized("foo//bar")) asserts.true(env, paths.is_normalized("foo////bar")) # Try some "." removal. asserts.false(env, paths.is_normalized("foo/./bar")) asserts.false(env, paths.is_normalized("./foo/bar")) asserts.false(env, paths.is_normalized("foo/bar/.")) asserts.false(env, paths.is_normalized("/.")) # Try some ".." removal. asserts.false(env, paths.is_normalized("foo/../bar")) asserts.false(env, paths.is_normalized("foo/bar/..")) asserts.false(env, paths.is_normalized("foo/..")) asserts.false(env, paths.is_normalized("foo/bar/../..")) asserts.false(env, paths.is_normalized("foo/../..")) asserts.false(env, paths.is_normalized("/foo/../..")) asserts.false(env, paths.is_normalized("a/b/../../../../c/d/..")) # Make sure one or two initial slashes are preserved, but three or more are # collapsed to a single slash. asserts.true(env, paths.is_normalized("/foo")) asserts.true(env, paths.is_normalized("//foo")) asserts.true(env, paths.is_normalized("///foo")) # Trailing slashes should be removed unless the entire path is a trailing # slash. asserts.true(env, paths.is_normalized("/")) asserts.true(env, paths.is_normalized("foo/")) asserts.true(env, paths.is_normalized("foo/bar/")) return unittest.end(env) is_normalized_test = unittest.make(_is_normalized_test) def _relativize_test(ctx): """Unit tests for paths.relativize.""" env = unittest.begin(ctx) # Make sure that relative-to-current-directory works in all forms. asserts.equals(env, "foo", paths.relativize("foo", "")) asserts.equals(env, "foo", paths.relativize("foo", ".")) # Try some regular cases. asserts.equals(env, "bar", paths.relativize("foo/bar", "foo")) asserts.equals(env, "baz", paths.relativize("foo/bar/baz", "foo/bar")) asserts.equals(env, "bar/baz", paths.relativize("foo/bar/baz", "foo")) # Try a case where a parent directory is normalized away. asserts.equals(env, "baz", paths.relativize("foo/bar/../baz", "foo")) # Relative paths work, as long as they share a common start. asserts.equals(env, "file", paths.relativize("../foo/bar/baz/file", "../foo/bar/baz")) asserts.equals(env, "baz/file", paths.relativize("../foo/bar/baz/file", "../foo/bar")) # TODO(allevato): Test failure cases, once that is possible. return unittest.end(env) relativize_test = unittest.make(_relativize_test) def _replace_extension_test(ctx): """Unit tests for paths.replace_extension.""" env = unittest.begin(ctx) # Try some degenerate cases. asserts.equals(env, ".foo", paths.replace_extension("", ".foo")) asserts.equals(env, "/.foo", paths.replace_extension("/", ".foo")) asserts.equals(env, "foo.bar", paths.replace_extension("foo", ".bar")) # Try a directory with an extension and basename that doesn't have one. asserts.equals( env, "foo.bar/baz.quux", paths.replace_extension("foo.bar/baz", ".quux"), ) # Now try some things with legit extensions. asserts.equals(env, "a.z", paths.replace_extension("a.b", ".z")) asserts.equals(env, "a.b.z", paths.replace_extension("a.b.c", ".z")) asserts.equals(env, "a/b.z", paths.replace_extension("a/b.c", ".z")) asserts.equals(env, "a.b/c.z", paths.replace_extension("a.b/c.d", ".z")) asserts.equals(env, ".a/b.z", paths.replace_extension(".a/b.c", ".z")) asserts.equals(env, ".a.z", paths.replace_extension(".a.b", ".z")) # Verify that we don't insert a period on the extension if none is provided. asserts.equals(env, "foobaz", paths.replace_extension("foo.bar", "baz")) return unittest.end(env) replace_extension_test = unittest.make(_replace_extension_test) def _split_extension_test(ctx): """Unit tests for paths.split_extension.""" env = unittest.begin(ctx) # Try some degenerate cases. asserts.equals(env, ("", ""), paths.split_extension("")) asserts.equals(env, ("/", ""), paths.split_extension("/")) asserts.equals(env, ("foo", ""), paths.split_extension("foo")) # Try some paths whose basenames start with ".". asserts.equals(env, (".", ""), paths.split_extension(".")) asserts.equals(env, (".bashrc", ""), paths.split_extension(".bashrc")) asserts.equals(env, ("foo/.bashrc", ""), paths.split_extension("foo/.bashrc")) asserts.equals( env, (".foo/.bashrc", ""), paths.split_extension(".foo/.bashrc"), ) # Try some directories with extensions with basenames that don't have one. asserts.equals(env, ("foo.bar/baz", ""), paths.split_extension("foo.bar/baz")) asserts.equals( env, ("foo.bar/.bashrc", ""), paths.split_extension("foo.bar/.bashrc"), ) # Now try some things that will actually get split. asserts.equals(env, ("a", ".b"), paths.split_extension("a.b")) asserts.equals(env, ("a.b", ".c"), paths.split_extension("a.b.c")) asserts.equals(env, ("a/b", ".c"), paths.split_extension("a/b.c")) asserts.equals(env, ("a.b/c", ".d"), paths.split_extension("a.b/c.d")) asserts.equals(env, (".a/b", ".c"), paths.split_extension(".a/b.c")) asserts.equals(env, (".a", ".b"), paths.split_extension(".a.b")) return unittest.end(env) split_extension_test = unittest.make(_split_extension_test) def _starts_with_test(ctx): """Unit tests for paths.starts_with.""" env = unittest.begin(ctx) # Make sure that relative-to-current-directory works in all forms. asserts.true(env, paths.starts_with("foo", "")) asserts.false(env, paths.starts_with("foo", ".")) # Try some regular cases. asserts.true(env, paths.starts_with("foo/bar", "foo")) asserts.false(env, paths.starts_with("foo/bar", "fo")) asserts.true(env, paths.starts_with("foo/bar/baz", "foo/bar")) asserts.true(env, paths.starts_with("foo/bar/baz", "foo")) # Try a case where a parent directory is normalized away. asserts.true(env, paths.starts_with("foo/bar/../baz", "foo")) # Relative paths work, as long as they share a common start. asserts.true(env, paths.starts_with("../foo/bar/baz/file", "../foo/bar/baz")) asserts.true(env, paths.starts_with("../foo/bar/baz/file", "../foo/bar")) return unittest.end(env) starts_with_test = unittest.make(_starts_with_test) def paths_test_suite(): """Creates the test targets and test suite for paths.bzl tests.""" unittest.suite( "paths_tests", basename_test, dirname_test, is_absolute_test, join_test, normalize_test, is_normalized_test, relativize_test, replace_extension_test, split_extension_test, starts_with_test, ) bazel-skylib-1.9.1/tests/run_binary/000077500000000000000000000000001517445036200174335ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/run_binary/BUILD000066400000000000000000000136521517445036200202240ustar00rootroot00000000000000load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("//rules:diff_test.bzl", "diff_test") load("//rules:run_binary.bzl", "run_binary") load("//rules:write_file.bzl", "write_file") package( default_applicable_licenses = ["//:license"], default_testonly = 1, default_visibility = ["//visibility:private"], ) diff_test( name = "run_script_test", file1 = ":run_script.out", file2 = ":run_script_expected", ) # Generate this file with write_file instead of checking it in to the source # tree. This ensures line endings are consistent across "run_script.expected" # and "run_script.out". write_file( name = "run_script_expected", out = "run_script.expected", content = [ "arg1=(foo)", "arg2=(bar)", "ENV_LOCATION=(a tests/run_binary/BUILD)", "ENV_LOCATIONS=(b\\ tests/run_binary/BUILD tests/run_binary/printargs.cc)", "ENV_EXECPATH=(a tests/run_binary/BUILD)", "ENV_EXECPATHS=(b\\ tests/run_binary/BUILD tests/run_binary/printargs.cc)", "ENV_COMPLEX=(xx/yy \\\"zz)", "ENV_PATH_BASH=($PATH)", "ENV_PATH_CMD=(%PATH%)", # Can't prevent "echo" from adding a newline on Windows, so let's add # one to the expected output too. "", ], ) run_binary( name = "run_script", srcs = [ "BUILD", ":dummy_srcs", ], outs = ["run_script.out"], # Not testing any complex arguments here, because Windows .bat file argument # escaping is different from most MSVC-built Windows binaries. We test # argument escaping in "run_bin". args = [ "foo", "bar", ], # Test complex environment variables. They are location-expanded but not # Bash-tokenized, and should appear the same for Windows .bat files and Bash # .sh scripts. env = { "ENV_COMPLEX": "xx/yy \\\"zz", "ENV_EXECPATH": "a $(execpath BUILD)", "ENV_EXECPATHS": "b\\ $(execpaths :dummy_srcs)", # Testing $(location) expansion only on source files so the result is # predictable. The path of generated files depends on the target # platform. "ENV_LOCATION": "a $(location BUILD)", "ENV_LOCATIONS": "b\\ $(locations :dummy_srcs)", "ENV_PATH_BASH": "$PATH", "ENV_PATH_CMD": "%PATH%", "OUT": "$(location run_script.out)", }, tool = ":script", ) write_file( name = "script", # On Windows we need the ".bat" extension. # On other platforms the extension doesn't matter. # Therefore we can use ".bat" on every platform. out = "script.bat", content = select({ "@platforms//os:windows": [ "@echo>%OUT% arg1=(%1)", "@echo>>%OUT% arg2=(%2)", "@echo>>%OUT% ENV_LOCATION=(%ENV_LOCATION%)", "@echo>>%OUT% ENV_LOCATIONS=(%ENV_LOCATIONS%)", "@echo>>%OUT% ENV_EXECPATH=(%ENV_EXECPATH%)", "@echo>>%OUT% ENV_EXECPATHS=(%ENV_EXECPATHS%)", "@echo>>%OUT% ENV_COMPLEX=(%ENV_COMPLEX%)", "@echo>>%OUT% ENV_PATH_BASH=(%ENV_PATH_BASH%)", "@echo>>%OUT% ENV_PATH_CMD=(%ENV_PATH_CMD%)", ], "//conditions:default": [ "#!/usr/bin/env bash", "echo > \"$OUT\" \"arg1=($1)\"", "echo >> \"$OUT\" \"arg2=($2)\"", "echo >> \"$OUT\" \"ENV_LOCATION=($ENV_LOCATION)\"", "echo >> \"$OUT\" \"ENV_LOCATIONS=($ENV_LOCATIONS)\"", "echo >> \"$OUT\" \"ENV_EXECPATH=($ENV_EXECPATH)\"", "echo >> \"$OUT\" \"ENV_EXECPATHS=($ENV_EXECPATHS)\"", "echo >> \"$OUT\" \"ENV_COMPLEX=($ENV_COMPLEX)\"", "echo >> \"$OUT\" \"ENV_PATH_BASH=($ENV_PATH_BASH)\"", "echo >> \"$OUT\" \"ENV_PATH_CMD=($ENV_PATH_CMD)\"", ], }), is_executable = True, ) diff_test( name = "run_bin_test", file1 = ":run_bin.out", file2 = ":run_bin_expected", ) # Generate this file with write_file instead of checking it in to the source # tree. This ensures line endings are consistent across "run_bin.expected" # and "run_bin.out". write_file( name = "run_bin_expected", out = "run_bin.expected", content = [ "arg1=(a b)", "arg2=(\"c d\")", "arg3=(e\\ f)", "arg4=(xx/yy\\ \\\"zz)", "arg5=(tests/run_binary/BUILD)", "arg6=(tests/run_binary/BUILD tests/run_binary/printargs.cc)", "arg7=('tests/run_binary/BUILD $tests/run_binary/BUILD')", "arg8=(tests/run_binary/BUILD)", "arg9=(tests/run_binary/BUILD tests/run_binary/printargs.cc)", "arg10=('tests/run_binary/BUILD $tests/run_binary/BUILD')", "arg11=($PATH)", "arg12=($$PATH)", "arg13=(${PATH})", "arg14=($(echo hello))", # Add trailing newline, as printed by printargs. "", ], ) run_binary( name = "run_bin", srcs = [ "BUILD", ":dummy_srcs", ], outs = ["run_bin.out"], # Test complex arguments here. They are location-expanded but not # Bash-tokenized, and should appear the same on every platform. args = [ "a b", "\"c d\"", "e\\ f", "xx/yy\\ \\\"zz", # Testing $(execpath) expansion only on source files so the result is # predictable. The path of generated files depends on the target # platform. "$(execpath BUILD)", "$(execpaths :dummy_srcs)", "'$(execpath BUILD) $$(execpath BUILD)'", # Test the legacy 'location' expansions "$(location BUILD)", "$(locations :dummy_srcs)", "'$(location BUILD) $$(location BUILD)'", "$PATH", "$$PATH", "${PATH}", "$(echo hello)", ], # Not testing any complex envvars here, because we already did in # "run_script". env = {"OUT": "$(location run_bin.out)"}, tool = ":printargs", ) filegroup( name = "dummy_srcs", srcs = [ "BUILD", "printargs.cc", ], ) cc_binary( name = "printargs", srcs = ["printargs.cc"], ) bazel-skylib-1.9.1/tests/run_binary/printargs.cc000066400000000000000000000022101517445036200217460ustar00rootroot00000000000000// Copyright 2019 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include int main(int argc, char** argv) { char* out_path = getenv("OUT"); if (!out_path || !*out_path) { fprintf(stderr, "ERROR(" __FILE__ ":%d): envvar OUT is undefined\n", __LINE__); return 1; } FILE* f = fopen(out_path, "wt"); if (!f) { fprintf(stderr, "ERROR(" __FILE__ ":%d): could not open output file '%s'\n", __LINE__, out_path); return 1; } for (int i = 1; i < argc; ++i) { fprintf(f, "arg%d=(%s)\n", i, argv[i]); } fclose(f); return 0; } bazel-skylib-1.9.1/tests/select_file/000077500000000000000000000000001517445036200175415ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/select_file/BUILD000066400000000000000000000012611517445036200203230ustar00rootroot00000000000000load("//rules:diff_test.bzl", "diff_test") load("//rules:select_file.bzl", "select_file") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) filegroup( name = "fg", srcs = [ "subdir/inner.txt", ":select_me.txt", ], ) select_file( name = "select_me", srcs = ":fg", subpath = "select_me.txt", ) select_file( name = "select_inner", srcs = ":fg", subpath = "subdir/inner.txt", ) diff_test( name = "selected_me", file1 = ":select_me", file2 = ":select_me.txt", ) diff_test( name = "selected_inner", file1 = ":select_inner", file2 = "subdir/inner.txt", ) bazel-skylib-1.9.1/tests/select_file/select_me.txt000066400000000000000000000000061517445036200222360ustar00rootroot00000000000000Outer bazel-skylib-1.9.1/tests/select_file/subdir/000077500000000000000000000000001517445036200210315ustar00rootroot00000000000000bazel-skylib-1.9.1/tests/select_file/subdir/inner.txt000066400000000000000000000000061517445036200227010ustar00rootroot00000000000000Inner bazel-skylib-1.9.1/tests/selects_tests.bzl000066400000000000000000000544271517445036200206740ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for selects.bzl.""" load("//lib:selects.bzl", "selects") load("//lib:unittest.bzl", "analysistest", "asserts", "unittest") ################################################### # with_or_test ################################################### def _with_or_test(ctx): """Unit tests for with_or.""" env = unittest.begin(ctx) # We actually test on with_or_dict because Starlark can't get the # dictionary from a select(). # Test select()-compatible input syntax. input_dict = {":foo": ":d1", "//conditions:default": ":d1"} asserts.equals(env, input_dict, selects.with_or_dict(input_dict)) # Test OR syntax. or_dict = {(":foo", ":bar"): ":d1"} asserts.equals( env, {":bar": ":d1", ":foo": ":d1"}, selects.with_or_dict(or_dict), ) # Test mixed syntax. mixed_dict = { ":foo": ":d1", (":bar", ":baz"): ":d2", "//conditions:default": ":d3", } asserts.equals( env, { ":bar": ":d2", ":baz": ":d2", ":foo": ":d1", "//conditions:default": ":d3", }, selects.with_or_dict(mixed_dict), ) return unittest.end(env) with_or_test = unittest.make(_with_or_test) ################################################### # BUILD declarations for config_setting_group tests ################################################### # TODO: redefine these config_settings with Starlark build flags when # they're available non-experimentally. def _create_config_settings(): native.config_setting( name = "condition1", values = {"stamp": "1"}, ) native.config_setting( name = "condition2", values = {"compilation_mode": "opt"}, ) native.config_setting( name = "condition3", values = {"features": "myfeature"}, ) def _create_config_setting_groups(): selects.config_setting_group( name = "1_and_2_and_3", match_all = [":condition1", ":condition2", ":condition3"], ) selects.config_setting_group( name = "1_and_nothing_else", match_all = [":condition1"], ) selects.config_setting_group( name = "1_or_2_or_3", match_any = [":condition1", ":condition2", ":condition3"], ) selects.config_setting_group( name = "1_or_nothing_else", match_any = [":condition1"], ) ################################################### # Support code for config_setting_group tests ################################################### def _set_conditions(condition_list): """Returns an argument for config_settings that sets specific options. Args: condition_list: a list of three booleans Returns: a dictionary parameter for config_settings such that ":conditionN" is True iff condition_list[N + 1] is True """ if len(condition_list) != 3: fail("condition_list must be a list of 3 booleans") ans = {} if condition_list[0]: ans["//command_line_option:stamp"] = "1" else: ans["//command_line_option:stamp"] = "0" if condition_list[1]: ans["//command_line_option:compilation_mode"] = "opt" else: ans["//command_line_option:compilation_mode"] = "dbg" if condition_list[2]: ans["//command_line_option:features"] = ["myfeature"] else: ans["//command_line_option:features"] = ["notmyfeature"] return ans _BooleanInfo = provider( doc = "value for boolean tests", fields = ["value"], ) def _boolean_attr_impl(ctx): return [_BooleanInfo(value = ctx.attr.myboolean)] boolean_attr_rule = rule( implementation = _boolean_attr_impl, attrs = {"myboolean": attr.bool()}, ) def _expect_matches(ctx): """Generic test implementation expecting myboolean == True.""" env = analysistest.begin(ctx) attrval = analysistest.target_under_test(env)[_BooleanInfo].value asserts.equals(env, True, attrval) return analysistest.end(env) def _expect_doesnt_match(ctx): """Generic test implementation expecting myboolean == False.""" env = analysistest.begin(ctx) attrval = analysistest.target_under_test(env)[_BooleanInfo].value asserts.equals(env, False, attrval) return analysistest.end(env) ################################################### # and_config_setting_group_matches_test ################################################### and_config_setting_group_matches_test = analysistest.make( _expect_matches, config_settings = _set_conditions([True, True, True]), ) def _and_config_setting_group_matches_test(): """Test verifying match on an ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_matches_rule", myboolean = select( { ":1_and_2_and_3": True, "//conditions:default": False, }, ), ) and_config_setting_group_matches_test( name = "and_config_setting_group_matches_test", target_under_test = ":and_config_setting_group_matches_rule", ) ################################################### # and_config_setting_group_first_match_fails_test ################################################### and_config_setting_group_first_match_fails_test = analysistest.make( _expect_doesnt_match, config_settings = _set_conditions([False, True, True]), ) def _and_config_setting_group_first_match_fails_test(): """Test verifying first condition mismatch on an ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_first_match_fails_rule", myboolean = select( { ":1_and_2_and_3": True, "//conditions:default": False, }, ), ) and_config_setting_group_first_match_fails_test( name = "and_config_setting_group_first_match_fails_test", target_under_test = ":and_config_setting_group_first_match_fails_rule", ) ################################################### # and_config_setting_group_middle_match_fails_test ################################################### and_config_setting_group_middle_match_fails_test = analysistest.make( _expect_doesnt_match, config_settings = _set_conditions([True, False, True]), ) def _and_config_setting_group_middle_match_fails_test(): """Test verifying middle condition mismatch on an ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_middle_match_fails_rule", myboolean = select( { ":1_and_2_and_3": True, "//conditions:default": False, }, ), ) and_config_setting_group_middle_match_fails_test( name = "and_config_setting_group_middle_match_fails_test", target_under_test = ":and_config_setting_group_middle_match_fails_rule", ) ################################################### # and_config_setting_group_last_match_fails_test ################################################### and_config_setting_group_last_match_fails_test = analysistest.make( _expect_doesnt_match, config_settings = _set_conditions([True, True, False]), ) def _and_config_setting_group_last_match_fails_test(): """Test verifying last condition mismatch on an ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_last_match_fails_rule", myboolean = select( { ":1_and_2_and_3": True, "//conditions:default": False, }, ), ) and_config_setting_group_last_match_fails_test( name = "and_config_setting_group_last_match_fails_test", target_under_test = ":and_config_setting_group_last_match_fails_rule", ) ################################################### # and_config_setting_group_multiple_matches_fail_test ################################################### and_config_setting_group_multiple_matches_fail_test = analysistest.make( _expect_doesnt_match, config_settings = _set_conditions([True, False, False]), ) def _and_config_setting_group_multiple_matches_fail_test(): """Test verifying multiple conditions mismatch on an ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_multiple_matches_fail_rule", myboolean = select( { ":1_and_2_and_3": True, "//conditions:default": False, }, ), ) and_config_setting_group_multiple_matches_fail_test( name = "and_config_setting_group_multiple_matches_fail_test", target_under_test = ":and_config_setting_group_multiple_matches_fail_rule", ) ################################################### # and_config_setting_group_all_matches_fail_test ################################################### and_config_setting_group_all_matches_fail_test = analysistest.make( _expect_doesnt_match, config_settings = _set_conditions([False, False, False]), ) def _and_config_setting_group_all_matches_fail_test(): """Test verifying all conditions mismatch on an ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_all_matches_fail_rule", myboolean = select( { ":1_and_2_and_3": True, "//conditions:default": False, }, ), ) and_config_setting_group_all_matches_fail_test( name = "and_config_setting_group_all_matches_fail_test", target_under_test = ":and_config_setting_group_all_matches_fail_rule", ) ################################################### # and_config_setting_group_single_setting_matches_test ################################################### and_config_setting_group_single_setting_matches_test = analysistest.make( _expect_matches, config_settings = {"//command_line_option:stamp": "1"}, ) def _and_config_setting_group_single_setting_matches_test(): """Test verifying match on single-entry ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_single_setting_matches_rule", myboolean = select( { ":1_and_nothing_else": True, "//conditions:default": False, }, ), ) and_config_setting_group_single_setting_matches_test( name = "and_config_setting_group_single_setting_matches_test", target_under_test = ":and_config_setting_group_single_setting_matches_rule", ) ################################################### # and_config_setting_group_single_setting_fails_test ################################################### and_config_setting_group_single_setting_fails_test = analysistest.make( _expect_doesnt_match, config_settings = {"//command_line_option:stamp": "0"}, ) def _and_config_setting_group_single_setting_fails_test(): """Test verifying no match on single-entry ANDing config_setting_group.""" boolean_attr_rule( name = "and_config_setting_group_single_setting_fails_rule", myboolean = select( { ":1_and_nothing_else": True, "//conditions:default": False, }, ), ) and_config_setting_group_single_setting_fails_test( name = "and_config_setting_group_single_setting_fails_test", target_under_test = ":and_config_setting_group_single_setting_fails_rule", ) ################################################### # or_config_setting_group_no_match_test ################################################### or_config_setting_group_no_matches_test = analysistest.make( _expect_doesnt_match, config_settings = _set_conditions([False, False, False]), ) def _or_config_setting_group_no_matches_test(): """Test verifying no matches on an ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_no_matches_rule", myboolean = select( { ":1_or_2_or_3": True, "//conditions:default": False, }, ), ) or_config_setting_group_no_matches_test( name = "or_config_setting_group_no_matches_test", target_under_test = ":or_config_setting_group_no_matches_rule", ) ################################################### # or_config_setting_group_first_cond_matches_test ################################################### or_config_setting_group_first_cond_matches_test = analysistest.make( _expect_matches, config_settings = _set_conditions([True, False, False]), ) def _or_config_setting_group_first_cond_matches_test(): """Test verifying first condition matching on an ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_first_cond_matches_rule", myboolean = select( { ":1_or_2_or_3": True, "//conditions:default": False, }, ), ) or_config_setting_group_first_cond_matches_test( name = "or_config_setting_group_first_cond_matches_test", target_under_test = ":or_config_setting_group_first_cond_matches_rule", ) ################################################### # or_config_setting_group_middle_cond_matches_test ################################################### or_config_setting_group_middle_cond_matches_test = analysistest.make( _expect_matches, config_settings = _set_conditions([False, True, False]), ) def _or_config_setting_group_middle_cond_matches_test(): """Test verifying middle condition matching on an ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_middle_cond_matches_rule", myboolean = select( { ":1_or_2_or_3": True, "//conditions:default": False, }, ), ) or_config_setting_group_middle_cond_matches_test( name = "or_config_setting_group_middle_cond_matches_test", target_under_test = ":or_config_setting_group_middle_cond_matches_rule", ) ################################################### # or_config_setting_group_last_cond_matches_test ################################################### or_config_setting_group_last_cond_matches_test = analysistest.make( _expect_matches, config_settings = _set_conditions([False, False, True]), ) def _or_config_setting_group_last_cond_matches_test(): """Test verifying last condition matching on an ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_last_cond_matches_rule", myboolean = select( { ":1_or_2_or_3": True, "//conditions:default": False, }, ), ) or_config_setting_group_last_cond_matches_test( name = "or_config_setting_group_last_cond_matches_test", target_under_test = ":or_config_setting_group_last_cond_matches_rule", ) ################################################### # or_config_setting_group_multiple_conds_match_test ################################################### or_config_setting_group_multiple_conds_match_test = analysistest.make( _expect_matches, config_settings = _set_conditions([False, True, True]), ) def _or_config_setting_group_multiple_conds_match_test(): """Test verifying multiple conditions matching on an ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_multiple_conds_match_rule", myboolean = select( { ":1_or_2_or_3": True, "//conditions:default": False, }, ), ) or_config_setting_group_multiple_conds_match_test( name = "or_config_setting_group_multiple_conds_match_test", target_under_test = ":or_config_setting_group_multiple_conds_match_rule", ) ################################################### # or_config_setting_group_all_conds_match_test ################################################### or_config_setting_group_all_conds_match_test = analysistest.make( _expect_matches, config_settings = _set_conditions([False, True, True]), ) def _or_config_setting_group_all_conds_match_test(): """Test verifying all conditions matching on an ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_all_conds_match_rule", myboolean = select( { ":1_or_2_or_3": True, "//conditions:default": False, }, ), ) or_config_setting_group_all_conds_match_test( name = "or_config_setting_group_all_conds_match_test", target_under_test = ":or_config_setting_group_all_conds_match_rule", ) ################################################### # or_config_setting_group_single_setting_matches_test ################################################### or_config_setting_group_single_setting_matches_test = analysistest.make( _expect_matches, config_settings = {"//command_line_option:stamp": "1"}, ) def _or_config_setting_group_single_setting_matches_test(): """Test verifying match on single-entry ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_single_setting_matches_rule", myboolean = select( { ":1_or_nothing_else": True, "//conditions:default": False, }, ), ) or_config_setting_group_single_setting_matches_test( name = "or_config_setting_group_single_setting_matches_test", target_under_test = ":or_config_setting_group_single_setting_matches_rule", ) ################################################### # or_config_setting_group_single_setting_fails_test ################################################### or_config_setting_group_single_setting_fails_test = analysistest.make( _expect_doesnt_match, config_settings = {"//command_line_option:stamp": "0"}, ) def _or_config_setting_group_single_setting_fails_test(): """Test verifying no match on single-entry ORing config_setting_group.""" boolean_attr_rule( name = "or_config_setting_group_single_setting_fails_rule", myboolean = select( { ":1_or_nothing_else": True, "//conditions:default": False, }, ), ) or_config_setting_group_single_setting_fails_test( name = "or_config_setting_group_single_setting_fails_test", target_under_test = ":or_config_setting_group_single_setting_fails_rule", ) ################################################### # always_true_match_all_test ################################################### always_true_match_all_test = analysistest.make(_expect_matches) def _always_true_match_all_test(): """Tests that "match_all=['//conditions:default']" always matches.""" selects.config_setting_group( name = "all_always_match", match_all = ["//conditions:default"], ) boolean_attr_rule( name = "match_always_true_rule", myboolean = select( { ":all_always_match": True, }, ), ) always_true_match_all_test( name = "always_true_match_all_test", target_under_test = ":match_always_true_rule", ) ################################################### # always_true_match_any_test ################################################### always_true_match_any_test = analysistest.make(_expect_matches) def _always_true_match_any_test(): """Tests that "match_any=['//conditions:default']" always matches.""" selects.config_setting_group( name = "any_always_match", match_any = ["//conditions:default"], ) boolean_attr_rule( name = "match_any_always_true_rule", myboolean = select( { ":any_always_match": True, }, ), ) always_true_match_any_test( name = "always_true_match_any_test", target_under_test = ":match_any_always_true_rule", ) ################################################### # empty_config_setting_group_not_allowed_test ################################################### # config_setting_group with no parameters triggers a failure. # TODO: how do we test this? This requires catching macro # evaluation failure. ################################################### # and_and_or_not_allowed_together_test ################################################### # config_setting_group: setting both match_any and match_or # triggers a failure. # TODO: how do we test this? This requires catching macro # evaluation failure. ################################################### # buildifier: disable=unnamed-macro def selects_test_suite(): """Creates the test targets and test suite for selects.bzl tests.""" unittest.suite( "selects_tests", with_or_test, ) _create_config_settings() _create_config_setting_groups() _and_config_setting_group_matches_test() _and_config_setting_group_first_match_fails_test() _and_config_setting_group_middle_match_fails_test() _and_config_setting_group_last_match_fails_test() _and_config_setting_group_multiple_matches_fail_test() _and_config_setting_group_all_matches_fail_test() _and_config_setting_group_single_setting_matches_test() _and_config_setting_group_single_setting_fails_test() _or_config_setting_group_no_matches_test() _or_config_setting_group_first_cond_matches_test() _or_config_setting_group_middle_cond_matches_test() _or_config_setting_group_last_cond_matches_test() _or_config_setting_group_multiple_conds_match_test() _or_config_setting_group_all_conds_match_test() _or_config_setting_group_single_setting_matches_test() _or_config_setting_group_single_setting_fails_test() _always_true_match_all_test() _always_true_match_any_test() # _empty_config_setting_group_not_allowed_test() # _and_and_or_not_allowed_together_test() bazel-skylib-1.9.1/tests/shell_tests.bzl000066400000000000000000000075011517445036200203300ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for shell.bzl.""" load("//lib:shell.bzl", "shell") load("//lib:unittest.bzl", "asserts", "unittest") def _shell_array_literal_test(ctx): """Unit tests for shell.array_literal.""" env = unittest.begin(ctx) asserts.equals(env, "()", shell.array_literal([])) asserts.equals(env, "('1')", shell.array_literal([1])) asserts.equals(env, "('1' '2' '3')", shell.array_literal([1, 2, 3])) asserts.equals(env, "('$foo')", shell.array_literal(["$foo"])) asserts.equals(env, "('qu\"o\"te')", shell.array_literal(['qu"o"te'])) return unittest.end(env) shell_array_literal_test = unittest.make(_shell_array_literal_test) def _shell_quote_test(ctx): """Unit tests for shell.quote.""" env = unittest.begin(ctx) asserts.equals(env, "'foo'", shell.quote("foo")) asserts.equals(env, "'foo bar'", shell.quote("foo bar")) asserts.equals(env, "'three spaces'", shell.quote("three spaces")) asserts.equals(env, "' leading'", shell.quote(" leading")) asserts.equals(env, "'trailing '", shell.quote("trailing ")) asserts.equals(env, "'new\nline'", shell.quote("new\nline")) asserts.equals(env, "'tab\tcharacter'", shell.quote("tab\tcharacter")) asserts.equals(env, "'$foo'", shell.quote("$foo")) asserts.equals(env, "'qu\"o\"te'", shell.quote('qu"o"te')) asserts.equals(env, "'it'\\''s'", shell.quote("it's")) asserts.equals(env, "'foo\\bar'", shell.quote("foo\\bar")) asserts.equals(env, "'back`echo q`uote'", shell.quote("back`echo q`uote")) return unittest.end(env) shell_quote_test = unittest.make(_shell_quote_test) def _shell_args_test_gen_impl(ctx): """Test argument escaping: this rule writes a script for a sh_test.""" args = [ "foo", "foo bar", "three spaces", " leading", "trailing ", "new\nline", "tab\tcharacter", "$foo", 'qu"o"te', "it's", "foo\\bar", "back`echo q`uote", ] script_content = "\n".join([ "#!/usr/bin/env bash", "myarray=" + shell.array_literal(args), 'output=$(echo "${myarray[@]}")', # For logging: 'echo "DEBUG: output=[${output}]" >&2', # The following is a shell representation of what the echo of the quoted # array will look like. It looks a bit confusing considering it's shell # quoted into Python. Shell using single quotes to minimize shell # escaping, so only the single quote needs to be escaped as '\'', all # others are essentially kept literally. "expected='foo foo bar three spaces leading trailing new", "line tab\tcharacter $foo qu\"o\"te it'\\''s foo\\bar back`echo q`uote'", '[[ "${output}" == "${expected}" ]]', ]) out = ctx.actions.declare_file(ctx.label.name + ".sh") ctx.actions.write( output = out, content = script_content, is_executable = True, ) return [DefaultInfo(files = depset([out]))] shell_args_test_gen = rule( implementation = _shell_args_test_gen_impl, ) def shell_test_suite(): """Creates the test targets and test suite for shell.bzl tests.""" unittest.suite( "shell_tests", shell_array_literal_test, shell_quote_test, ) bazel-skylib-1.9.1/tests/structs_tests.bzl000066400000000000000000000032751517445036200207340ustar00rootroot00000000000000# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for structs.bzl.""" load("//lib:structs.bzl", "structs") load("//lib:unittest.bzl", "asserts", "unittest") def _add_test(ctx): """Unit tests for dicts.add.""" env = unittest.begin(ctx) # Test zero- and one-argument behavior. asserts.equals(env, {}, structs.to_dict(struct())) asserts.equals(env, {"a": 1}, structs.to_dict(struct(a = 1))) # Test simple two-argument behavior. asserts.equals(env, {"a": 1, "b": 2}, structs.to_dict(struct(a = 1, b = 2))) # Test simple more-than-two-argument behavior. asserts.equals( env, {"a": 1, "b": 2, "c": 3, "d": 4}, structs.to_dict(struct(a = 1, b = 2, c = 3, d = 4)), ) # Test transformation is not applied transitively. asserts.equals( env, {"a": 1, "b": struct(bb = 1)}, structs.to_dict(struct(a = 1, b = struct(bb = 1))), ) return unittest.end(env) add_test = unittest.make(_add_test) def structs_test_suite(): """Creates the test targets and test suite for structs.bzl tests.""" unittest.suite( "structs_tests", add_test, ) bazel-skylib-1.9.1/tests/subpackages_tests.bzl000066400000000000000000000050511517445036200215070ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for subpackages.bzl.""" load("//lib:subpackages.bzl", "subpackages") load("//lib:unittest.bzl", "loadingtest") def _all_test(env): """Unit tests for subpackages.all.""" all_pkgs = [ "bzl_library", "common_settings", "copy_directory", "copy_file", "diff_test", "directory", "expand_template", "select_file", "write_file", ] # Not all pkgs exist in all test environments. if subpackages.exists("run_binary"): all_pkgs.append("run_binary") if subpackages.exists("native_binary"): all_pkgs.append("native_binary") # These exist in all cases filtered_pkgs = [ "bzl_library", "common_settings", "copy_directory", "copy_file", "directory", "expand_template", "select_file", "write_file", ] # subpackages is always in sorted order: all_pkgs = sorted(all_pkgs) # test defaults loadingtest.equals( env, "all", ["//tests/" + pkg for pkg in all_pkgs], subpackages.all(), ) # test non-fully-qualified output loadingtest.equals( env, "all_not_fully_qualified", all_pkgs, subpackages.all(fully_qualified = False), ) # test exclusion loadingtest.equals( env, "all_w_exclude", filtered_pkgs, subpackages.all(exclude = ["diff_test", "run_binary", "native_binary"], fully_qualified = False), ) def _exists_test(env): """Unit tests for subpackages.exists.""" loadingtest.equals(env, "exists_yes", True, subpackages.exists("copy_file")) loadingtest.equals(env, "exists_no", False, subpackages.exists("never_existed")) def subpackages_test_suite(): """Creates the test targets and test suite for subpackages.bzl tests.""" if subpackages.supported(): env = loadingtest.make("subpackages") _all_test(env) _exists_test(env) bazel-skylib-1.9.1/tests/types_tests.bzl000066400000000000000000000165771517445036200204020ustar00rootroot00000000000000# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for types.bzl.""" load("//lib:new_sets.bzl", "sets") load("//lib:types.bzl", "types") load("//lib:unittest.bzl", "asserts", "unittest") def _a_function(): """A dummy function for testing.""" pass def _is_string_test(ctx): """Unit tests for types.is_string.""" env = unittest.begin(ctx) asserts.true(env, types.is_string("")) asserts.true(env, types.is_string("string")) asserts.false(env, types.is_string(4)) asserts.false(env, types.is_string([1])) asserts.false(env, types.is_string({})) asserts.false(env, types.is_string(())) asserts.false(env, types.is_string(True)) asserts.false(env, types.is_string(None)) asserts.false(env, types.is_string(_a_function)) asserts.false(env, types.is_string(depset())) return unittest.end(env) is_string_test = unittest.make(_is_string_test) def _is_bool_test(ctx): """Unit tests for types.is_bool.""" env = unittest.begin(ctx) asserts.true(env, types.is_bool(True)) asserts.true(env, types.is_bool(False)) asserts.false(env, types.is_bool(4)) asserts.false(env, types.is_bool([1])) asserts.false(env, types.is_bool({})) asserts.false(env, types.is_bool(())) asserts.false(env, types.is_bool("")) asserts.false(env, types.is_bool(None)) asserts.false(env, types.is_bool(_a_function)) asserts.false(env, types.is_bool(depset())) return unittest.end(env) is_bool_test = unittest.make(_is_bool_test) def _is_list_test(ctx): """Unit tests for types.is_list.""" env = unittest.begin(ctx) asserts.true(env, types.is_list([])) asserts.true(env, types.is_list([1])) asserts.false(env, types.is_list(4)) asserts.false(env, types.is_list("s")) asserts.false(env, types.is_list({})) asserts.false(env, types.is_list(())) asserts.false(env, types.is_list(True)) asserts.false(env, types.is_list(None)) asserts.false(env, types.is_list(_a_function)) asserts.false(env, types.is_list(depset())) return unittest.end(env) is_list_test = unittest.make(_is_list_test) def _is_none_test(ctx): """Unit tests for types.is_none.""" env = unittest.begin(ctx) asserts.true(env, types.is_none(None)) asserts.false(env, types.is_none(4)) asserts.false(env, types.is_none("s")) asserts.false(env, types.is_none({})) asserts.false(env, types.is_none(())) asserts.false(env, types.is_none(True)) asserts.false(env, types.is_none([])) asserts.false(env, types.is_none([1])) asserts.false(env, types.is_none(_a_function)) asserts.false(env, types.is_none(depset())) return unittest.end(env) is_none_test = unittest.make(_is_none_test) def _is_int_test(ctx): """Unit tests for types.is_int.""" env = unittest.begin(ctx) asserts.true(env, types.is_int(1)) asserts.true(env, types.is_int(-1)) asserts.false(env, types.is_int("s")) asserts.false(env, types.is_int({})) asserts.false(env, types.is_int(())) asserts.false(env, types.is_int(True)) asserts.false(env, types.is_int([])) asserts.false(env, types.is_int([1])) asserts.false(env, types.is_int(None)) asserts.false(env, types.is_int(_a_function)) asserts.false(env, types.is_int(depset())) return unittest.end(env) is_int_test = unittest.make(_is_int_test) def _is_tuple_test(ctx): """Unit tests for types.is_tuple.""" env = unittest.begin(ctx) asserts.true(env, types.is_tuple(())) asserts.true(env, types.is_tuple((1,))) asserts.false(env, types.is_tuple(1)) asserts.false(env, types.is_tuple("s")) asserts.false(env, types.is_tuple({})) asserts.false(env, types.is_tuple(True)) asserts.false(env, types.is_tuple([])) asserts.false(env, types.is_tuple([1])) asserts.false(env, types.is_tuple(None)) asserts.false(env, types.is_tuple(_a_function)) asserts.false(env, types.is_tuple(depset())) return unittest.end(env) is_tuple_test = unittest.make(_is_tuple_test) def _is_dict_test(ctx): """Unit tests for types.is_dict.""" env = unittest.begin(ctx) asserts.true(env, types.is_dict({})) asserts.true(env, types.is_dict({"key": "value"})) asserts.false(env, types.is_dict(1)) asserts.false(env, types.is_dict("s")) asserts.false(env, types.is_dict(())) asserts.false(env, types.is_dict(True)) asserts.false(env, types.is_dict([])) asserts.false(env, types.is_dict([1])) asserts.false(env, types.is_dict(None)) asserts.false(env, types.is_dict(_a_function)) asserts.false(env, types.is_dict(depset())) return unittest.end(env) is_dict_test = unittest.make(_is_dict_test) def _is_function_test(ctx): """Unit tests for types.is_function.""" env = unittest.begin(ctx) asserts.true(env, types.is_function(_a_function)) asserts.false(env, types.is_function({})) asserts.false(env, types.is_function(1)) asserts.false(env, types.is_function("s")) asserts.false(env, types.is_function(())) asserts.false(env, types.is_function(True)) asserts.false(env, types.is_function([])) asserts.false(env, types.is_function([1])) asserts.false(env, types.is_function(None)) asserts.false(env, types.is_function(depset())) return unittest.end(env) is_function_test = unittest.make(_is_function_test) def _is_depset_test(ctx): """Unit tests for types.is_depset.""" env = unittest.begin(ctx) asserts.true(env, types.is_depset(depset())) asserts.true(env, types.is_depset(depset(["foo"]))) asserts.true(env, types.is_depset( depset(["foo"], transitive = [depset(["bar", "baz"])]), )) asserts.false(env, types.is_depset({})) asserts.false(env, types.is_depset(1)) asserts.false(env, types.is_depset("s")) asserts.false(env, types.is_depset(())) asserts.false(env, types.is_depset(True)) asserts.false(env, types.is_depset([])) asserts.false(env, types.is_depset([1])) asserts.false(env, types.is_depset(None)) return unittest.end(env) is_depset_test = unittest.make(_is_depset_test) def _is_set_test(ctx): """Unit test for types.is_set.""" env = unittest.begin(ctx) asserts.true(env, types.is_set(sets.make())) asserts.true(env, types.is_set(sets.make([1]))) asserts.false(env, types.is_set(None)) asserts.false(env, types.is_set({})) asserts.false(env, types.is_set(struct(foo = 1))) asserts.false(env, types.is_set(struct(_values = "not really values"))) return unittest.end(env) is_set_test = unittest.make(_is_set_test) def types_test_suite(): """Creates the test targets and test suite for types.bzl tests.""" unittest.suite( "types_tests", is_list_test, is_string_test, is_bool_test, is_none_test, is_int_test, is_tuple_test, is_dict_test, is_function_test, is_depset_test, is_set_test, ) bazel-skylib-1.9.1/tests/unittest.bash000077500000000000000000000616401517445036200200130ustar00rootroot00000000000000#!/usr/bin/env bash # # Copyright 2015 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Common utility file for Bazel shell tests # # unittest.bash: a unit test framework in Bash. # # A typical test suite looks like so: # # ------------------------------------------------------------------------ # #!/usr/bin/env bash # # source path/to/unittest.bash || exit 1 # # # Test that foo works. # function test_foo() { # foo >$TEST_log || fail "foo failed"; # expect_log "blah" "Expected to see 'blah' in output of 'foo'." # } # # # Test that bar works. # function test_bar() { # bar 2>$TEST_log || fail "bar failed"; # expect_not_log "ERROR" "Unexpected error from 'bar'." # ... # assert_equals $x $y # } # # run_suite "Test suite for blah" # ------------------------------------------------------------------------ # # Each test function is considered to pass iff fail() is not called # while it is active. fail() may be called directly, or indirectly # via other assertions such as expect_log(). run_suite must be called # at the very end. # # A test function may redefine functions "set_up" and/or "tear_down"; # these functions are executed before and after each test function, # respectively. Similarly, "cleanup" and "timeout" may be redefined, # and these function are called upon exit (of any kind) or a timeout. # # The user can pass --test_arg to bazel test to select specific tests # to run. Specifying --test_arg multiple times allows to select several # tests to be run in the given order. Additionally the user may define # TESTS=(test_foo test_bar ...) to specify a subset of test functions to # execute, for example, a working set during debugging. By default, all # functions called test_* will be executed. # # This file provides utilities for assertions over the output of a # command. The output of the command under test is directed to the # file $TEST_log, and then the expect_log* assertions can be used to # test for the presence of certain regular expressions in that file. # # The test framework is responsible for restoring the original working # directory before each test. # # The order in which test functions are run is not defined, so it is # important that tests clean up after themselves. # # Each test will be run in a new subshell. # # Functions named __* are not intended for use by clients. # # This framework implements the "test sharding protocol". # [ -n "$BASH_VERSION" ] || { echo "unittest.bash only works with bash!" >&2; exit 1; } DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) #### Configuration variables (may be overridden by testenv.sh or the suite): # This function may be called by testenv.sh or a test suite to enable errexit # in a way that enables us to print pretty stack traces when something fails. function enable_errexit() { set -o errtrace set -eu trap __test_terminated_err ERR } function disable_errexit() { set +o errtrace set +eu trap - ERR } #### Set up the test environment, branched from the old shell/testenv.sh # Enable errexit with pretty stack traces. enable_errexit # Print message in "$1" then exit with status "$2" die () { # second argument is optional, defaulting to 1 local status_code=${2:-1} # Stop capturing stdout/stderr, and dump captured output if [ "$CAPTURED_STD_ERR" -ne 0 -o "$CAPTURED_STD_OUT" -ne 0 ]; then restore_outputs if [ "$CAPTURED_STD_OUT" -ne 0 ]; then cat "${TEST_TMPDIR}/captured.out" CAPTURED_STD_OUT=0 fi if [ "$CAPTURED_STD_ERR" -ne 0 ]; then cat "${TEST_TMPDIR}/captured.err" 1>&2 CAPTURED_STD_ERR=0 fi fi if [ -n "${1-}" ] ; then echo "$1" 1>&2 fi if [ -n "${BASH-}" ]; then local caller_n=0 while [ $caller_n -lt 4 ] && caller_out=$(caller $caller_n 2>/dev/null); do test $caller_n -eq 0 && echo "CALLER stack (max 4):" echo " $caller_out" let caller_n=caller_n+1 done 1>&2 fi if [ x"$status_code" != x -a x"$status_code" != x"0" ]; then exit "$status_code" else exit 1 fi } # Print message in "$1" then record that a non-fatal error occurred in ERROR_COUNT ERROR_COUNT="${ERROR_COUNT:-0}" error () { if [ -n "$1" ] ; then echo "$1" 1>&2 fi ERROR_COUNT=$(($ERROR_COUNT + 1)) } # Die if "$1" != "$2", print $3 as death reason check_eq () { [ "$1" = "$2" ] || die "Check failed: '$1' == '$2' ${3:+ ($3)}" } # Die if "$1" == "$2", print $3 as death reason check_ne () { [ "$1" != "$2" ] || die "Check failed: '$1' != '$2' ${3:+ ($3)}" } # The structure of the following if statements is such that if '[' fails # (e.g., a non-number was passed in) then the check will fail. # Die if "$1" > "$2", print $3 as death reason check_le () { [ "$1" -gt "$2" ] || die "Check failed: '$1' <= '$2' ${3:+ ($3)}" } # Die if "$1" >= "$2", print $3 as death reason check_lt () { [ "$1" -lt "$2" ] || die "Check failed: '$1' < '$2' ${3:+ ($3)}" } # Die if "$1" < "$2", print $3 as death reason check_ge () { [ "$1" -ge "$2" ] || die "Check failed: '$1' >= '$2' ${3:+ ($3)}" } # Die if "$1" <= "$2", print $3 as death reason check_gt () { [ "$1" -gt "$2" ] || die "Check failed: '$1' > '$2' ${3:+ ($3)}" } # Die if $2 !~ $1; print $3 as death reason check_match () { expr match "$2" "$1" >/dev/null || \ die "Check failed: '$2' does not match regex '$1' ${3:+ ($3)}" } # Run command "$1" at exit. Like "trap" but multiple atexits don't # overwrite each other. Will break if someone does call trap # directly. So, don't do that. ATEXIT="${ATEXIT-}" atexit () { if [ -z "$ATEXIT" ]; then ATEXIT="$1" else ATEXIT="$1 ; $ATEXIT" fi trap "$ATEXIT" EXIT } ## TEST_TMPDIR if [ -z "${TEST_TMPDIR:-}" ]; then export TEST_TMPDIR="$(mktemp -d ${TMPDIR:-/tmp}/bazel-test.XXXXXXXX)" fi if [ ! -e "${TEST_TMPDIR}" ]; then mkdir -p -m 0700 "${TEST_TMPDIR}" # Clean TEST_TMPDIR on exit atexit "rm -fr ${TEST_TMPDIR}" fi # Functions to compare the actual output of a test to the expected # (golden) output. # # Usage: # capture_test_stdout # ... do something ... # diff_test_stdout "$TEST_SRCDIR/path/to/golden.out" # Redirect a file descriptor to a file. CAPTURED_STD_OUT="${CAPTURED_STD_OUT:-0}" CAPTURED_STD_ERR="${CAPTURED_STD_ERR:-0}" capture_test_stdout () { exec 3>&1 # Save stdout as fd 3 exec 4>"${TEST_TMPDIR}/captured.out" exec 1>&4 CAPTURED_STD_OUT=1 } capture_test_stderr () { exec 6>&2 # Save stderr as fd 6 exec 7>"${TEST_TMPDIR}/captured.err" exec 2>&7 CAPTURED_STD_ERR=1 } # Force XML_OUTPUT_FILE to an existing path if [ -z "${XML_OUTPUT_FILE:-}" ]; then XML_OUTPUT_FILE=${TEST_TMPDIR}/output.xml fi #### Global variables: TEST_name="" # The name of the current test. TEST_log=$TEST_TMPDIR/log # The log file over which the # expect_log* assertions work. Must # be absolute to be robust against # tests invoking 'cd'! TEST_passed="true" # The result of the current test; # failed assertions cause this to # become false. # These variables may be overridden by the test suite: TESTS=() # A subset or "working set" of test # functions that should be run. By # default, all tests called test_* are # run. if [ $# -gt 0 ]; then # Legacy behavior is to ignore missing regexp, but with errexit # the following line fails without || true. # TODO(dmarting): maybe we should revisit the way of selecting # test with that framework (use Bazel's environment variable instead). TESTS=($(for i in $@; do echo $i; done | grep ^test_ || true)) if (( ${#TESTS[@]} == 0 )); then echo "WARNING: Arguments do not specifies tests!" >&2 fi fi TEST_verbose="true" # Whether or not to be verbose. A # command; "true" or "false" are # acceptable. The default is: true. TEST_script="$(pwd)/$0" # Full path to test script #### Internal functions function __show_log() { echo "-- Test log: -----------------------------------------------------------" [[ -e $TEST_log ]] && cat $TEST_log || echo "(Log file did not exist.)" echo "------------------------------------------------------------------------" } # Usage: __pad <pad-char> # Print $title padded to 80 columns with $pad_char. function __pad() { local title=$1 local pad=$2 { echo -n "$pad$pad $title " printf "%80s" " " | tr ' ' "$pad" } | head -c 80 echo } #### Exported functions # Usage: init_test ... # Deprecated. Has no effect. function init_test() { : } # Usage: set_up # Called before every test function. May be redefined by the test suite. function set_up() { : } # Usage: tear_down # Called after every test function. May be redefined by the test suite. function tear_down() { : } # Usage: cleanup # Called upon eventual exit of the test suite. May be redefined by # the test suite. function cleanup() { : } # Usage: timeout # Called upon early exit from a test due to timeout. function timeout() { : } # Usage: fail <message> [<message> ...] # Print failure message with context information, and mark the test as # a failure. The context includes a stacktrace including the longest sequence # of calls outside this module. (We exclude the top and bottom portions of # the stack because they just add noise.) Also prints the contents of # $TEST_log. function fail() { __show_log >&2 echo "$TEST_name FAILED:" "$@" "." >&2 echo "$@" >$TEST_TMPDIR/__fail TEST_passed="false" __show_stack # Cleanup as we are leaving the subshell now tear_down exit 1 } # Usage: warn <message> # Print a test warning with context information. # The context includes a stacktrace including the longest sequence # of calls outside this module. (We exclude the top and bottom portions of # the stack because they just add noise.) function warn() { __show_log >&2 echo "$TEST_name WARNING: $1." >&2 __show_stack if [ -n "${TEST_WARNINGS_OUTPUT_FILE:-}" ]; then echo "$TEST_name WARNING: $1." >> "$TEST_WARNINGS_OUTPUT_FILE" fi } # Usage: show_stack # Prints the portion of the stack that does not belong to this module, # i.e. the user's code that called a failing assertion. Stack may not # be available if Bash is reading commands from stdin; an error is # printed in that case. __show_stack() { local i=0 local trace_found=0 # Skip over active calls within this module: while (( i < ${#FUNCNAME[@]} )) && [[ ${BASH_SOURCE[i]:-} == ${BASH_SOURCE[0]} ]]; do (( ++i )) done # Show all calls until the next one within this module (typically run_suite): while (( i < ${#FUNCNAME[@]} )) && [[ ${BASH_SOURCE[i]:-} != ${BASH_SOURCE[0]} ]]; do # Read online docs for BASH_LINENO to understand the strange offset. # Undefined can occur in the BASH_SOURCE stack apparently when one exits from a subshell echo "${BASH_SOURCE[i]:-"Unknown"}:${BASH_LINENO[i - 1]:-"Unknown"}: in call to ${FUNCNAME[i]:-"Unknown"}" >&2 (( ++i )) trace_found=1 done [ $trace_found = 1 ] || echo "[Stack trace not available]" >&2 } # Usage: expect_log <regexp> [error-message] # Asserts that $TEST_log matches regexp. Prints the contents of # $TEST_log and the specified (optional) error message otherwise, and # returns non-zero. function expect_log() { local pattern=$1 local message=${2:-Expected regexp "$pattern" not found} grep -sq -- "$pattern" $TEST_log && return 0 fail "$message" return 1 } # Usage: expect_log_warn <regexp> [error-message] # Warns if $TEST_log does not match regexp. Prints the contents of # $TEST_log and the specified (optional) error message on mismatch. function expect_log_warn() { local pattern=$1 local message=${2:-Expected regexp "$pattern" not found} grep -sq -- "$pattern" $TEST_log && return 0 warn "$message" return 1 } # Usage: expect_log_once <regexp> [error-message] # Asserts that $TEST_log contains one line matching <regexp>. # Prints the contents of $TEST_log and the specified (optional) # error message otherwise, and returns non-zero. function expect_log_once() { local pattern=$1 local message=${2:-Expected regexp "$pattern" not found exactly once} expect_log_n "$pattern" 1 "$message" } # Usage: expect_log_n <regexp> <count> [error-message] # Asserts that $TEST_log contains <count> lines matching <regexp>. # Prints the contents of $TEST_log and the specified (optional) # error message otherwise, and returns non-zero. function expect_log_n() { local pattern=$1 local expectednum=${2:-1} local message=${3:-Expected regexp "$pattern" not found exactly $expectednum times} local count=$(grep -sc -- "$pattern" $TEST_log) [[ $count = $expectednum ]] && return 0 fail "$message" return 1 } # Usage: expect_not_log <regexp> [error-message] # Asserts that $TEST_log does not match regexp. Prints the contents # of $TEST_log and the specified (optional) error message otherwise, and # returns non-zero. function expect_not_log() { local pattern=$1 local message=${2:-Unexpected regexp "$pattern" found} grep -sq -- "$pattern" $TEST_log || return 0 fail "$message" return 1 } # Usage: expect_log_with_timeout <regexp> <timeout> [error-message] # Waits for the given regexp in the $TEST_log for up to timeout seconds. # Prints the contents of $TEST_log and the specified (optional) # error message otherwise, and returns non-zero. function expect_log_with_timeout() { local pattern=$1 local timeout=$2 local message=${3:-Regexp "$pattern" not found in "$timeout" seconds} local count=0 while [ $count -lt $timeout ]; do grep -sq -- "$pattern" $TEST_log && return 0 let count=count+1 sleep 1 done grep -sq -- "$pattern" $TEST_log && return 0 fail "$message" return 1 } # Usage: expect_cmd_with_timeout <expected> <cmd> [timeout] # Repeats the command once a second for up to timeout seconds (10s by default), # until the output matches the expected value. Fails and returns 1 if # the command does not return the expected value in the end. function expect_cmd_with_timeout() { local expected="$1" local cmd="$2" local timeout=${3:-10} local count=0 while [ $count -lt $timeout ]; do local actual="$($cmd)" [ "$expected" = "$actual" ] && return 0 let count=count+1 sleep 1 done [ "$expected" = "$actual" ] && return 0 fail "Expected '$expected' within ${timeout}s, was '$actual'" return 1 } # Usage: assert_one_of <expected_list>... <actual> # Asserts that actual is one of the items in expected_list # Example: assert_one_of ( "foo", "bar", "baz" ) actualval function assert_one_of() { local args=("$@") local last_arg_index=$((${#args[@]} - 1)) local actual=${args[last_arg_index]} unset args[last_arg_index] for expected_item in "${args[@]}"; do [ "$expected_item" = "$actual" ] && return 0 done; fail "Expected one of '${args[@]}', was '$actual'" return 1 } # Usage: assert_equals <expected> <actual> # Asserts [ expected = actual ]. function assert_equals() { local expected=$1 actual=$2 [ "$expected" = "$actual" ] && return 0 fail "Expected '$expected', was '$actual'" return 1 } # Usage: assert_not_equals <unexpected> <actual> # Asserts [ unexpected != actual ]. function assert_not_equals() { local unexpected=$1 actual=$2 [ "$unexpected" != "$actual" ] && return 0; fail "Expected not '$unexpected', was '$actual'" return 1 } # Usage: assert_contains <regexp> <file> [error-message] # Asserts that file matches regexp. Prints the contents of # file and the specified (optional) error message otherwise, and # returns non-zero. function assert_contains() { local pattern=$1 local file=$2 local message=${3:-Expected regexp "$pattern" not found in "$file"} grep -sq -- "$pattern" "$file" && return 0 cat "$file" >&2 fail "$message" return 1 } # Usage: assert_not_contains <regexp> <file> [error-message] # Asserts that file does not match regexp. Prints the contents of # file and the specified (optional) error message otherwise, and # returns non-zero. function assert_not_contains() { local pattern=$1 local file=$2 local message=${3:-Expected regexp "$pattern" found in "$file"} grep -sq -- "$pattern" "$file" || return 0 cat "$file" >&2 fail "$message" return 1 } # Updates the global variables TESTS if # sharding is enabled, i.e. ($TEST_TOTAL_SHARDS > 0). function __update_shards() { [ -z "${TEST_TOTAL_SHARDS-}" ] && return 0 [ "$TEST_TOTAL_SHARDS" -gt 0 ] || { echo "Invalid total shards $TEST_TOTAL_SHARDS" >&2; exit 1; } [ "$TEST_SHARD_INDEX" -lt 0 -o "$TEST_SHARD_INDEX" -ge "$TEST_TOTAL_SHARDS" ] && { echo "Invalid shard $shard_index" >&2; exit 1; } TESTS=$(for test in "${TESTS[@]}"; do echo "$test"; done | awk "NR % $TEST_TOTAL_SHARDS == $TEST_SHARD_INDEX") [ -z "${TEST_SHARD_STATUS_FILE-}" ] || touch "$TEST_SHARD_STATUS_FILE" } # Usage: __test_terminated <signal-number> # Handler that is called when the test terminated unexpectedly function __test_terminated() { __show_log >&2 echo "$TEST_name FAILED: terminated by signal $1." >&2 TEST_passed="false" __show_stack timeout exit 1 } # Usage: __test_terminated_err # Handler that is called when the test terminated unexpectedly due to "errexit". function __test_terminated_err() { # When a subshell exits due to signal ERR, its parent shell also exits, # thus the signal handler is called recursively and we print out the # error message and stack trace multiple times. We're only interested # in the first one though, as it contains the most information, so ignore # all following. if [[ -f $TEST_TMPDIR/__err_handled ]]; then exit 1 fi __show_log >&2 if [[ ! -z "$TEST_name" ]]; then echo -n "$TEST_name " fi echo "FAILED: terminated because this command returned a non-zero status:" >&2 touch $TEST_TMPDIR/__err_handled TEST_passed="false" __show_stack # If $TEST_name is still empty, the test suite failed before we even started # to run tests, so we shouldn't call tear_down. if [[ ! -z "$TEST_name" ]]; then tear_down fi exit 1 } # Usage: __trap_with_arg <handler> <signals ...> # Helper to install a trap handler for several signals preserving the signal # number, so that the signal number is available to the trap handler. function __trap_with_arg() { func="$1" ; shift for sig ; do trap "$func $sig" "$sig" done } # Usage: <node> <block> # Adds the block to the given node in the report file. Quotes in the in # arguments need to be escaped. function __log_to_test_report() { local node="$1" local block="$2" if [[ ! -e "$XML_OUTPUT_FILE" ]]; then local xml_header='<?xml version="1.0" encoding="UTF-8"?>' echo "$xml_header<testsuites></testsuites>" > $XML_OUTPUT_FILE fi # replace match on node with block and match # replacement expression only needs escaping for quotes perl -e "\ \$input = @ARGV[0]; \ \$/=undef; \ open FILE, '+<$XML_OUTPUT_FILE'; \ \$content = <FILE>; \ if (\$content =~ /($node.*)\$/) { \ seek FILE, 0, 0; \ print FILE \$\` . \$input . \$1; \ }; \ close FILE" "$block" } # Usage: <total> <passed> # Adds the test summaries to the xml nodes. function __finish_test_report() { local total=$1 local passed=$2 local failed=$((total - passed)) cat $XML_OUTPUT_FILE | \ sed \ "s/<testsuites>/<testsuites tests=\"$total\" failures=\"0\" errors=\"$failed\">/" | \ sed \ "s/<testsuite>/<testsuite tests=\"$total\" failures=\"0\" errors=\"$failed\">/" \ > $XML_OUTPUT_FILE.bak rm -f $XML_OUTPUT_FILE mv $XML_OUTPUT_FILE.bak $XML_OUTPUT_FILE } # Multi-platform timestamp function UNAME=$(uname -s | tr 'A-Z' 'a-z') if [ "$UNAME" = "linux" ] || [[ "$UNAME" =~ msys_nt* ]]; then function timestamp() { echo $(($(date +%s%N)/1000000)) } else function timestamp() { # macOS and BSDs do not have %N, so Python is the best we can do. # LC_ALL=C works around python 3.8 and 3.9 crash on macOS when the # filesystem encoding is unspecified (e.g. when LANG=en_US). local PYTHON=python command -v python3 &> /dev/null && PYTHON=python3 LC_ALL=C "${PYTHON}" -c 'import time; print(int(round(time.time() * 1000)))' } fi function get_run_time() { local ts_start=$1 local ts_end=$2 run_time_ms=$((${ts_end}-${ts_start})) echo $(($run_time_ms/1000)).${run_time_ms: -3} } # Usage: run_tests <suite-comment> # Must be called from the end of the user's test suite. # Calls exit with zero on success, non-zero otherwise. function run_suite() { echo >&2 echo "$1" >&2 echo >&2 __log_to_test_report "<\/testsuites>" "<testsuite></testsuite>" local total=0 local passed=0 atexit "cleanup" # If the user didn't specify an explicit list of tests (e.g. a # working set), use them all. if [ ${#TESTS[@]} = 0 ]; then TESTS=$(declare -F | awk '{print $3}' | grep ^test_) elif [ -n "${TEST_WARNINGS_OUTPUT_FILE:-}" ]; then if grep -q "TESTS=" "$TEST_script" ; then echo "TESTS variable overridden in Bazel sh_test. Please remove before submitting" \ >> "$TEST_WARNINGS_OUTPUT_FILE" fi fi __update_shards for TEST_name in ${TESTS[@]}; do >$TEST_log # Reset the log. TEST_passed="true" total=$(($total + 1)) if [[ "$TEST_verbose" == "true" ]]; then __pad $TEST_name '*' >&2 fi local run_time="0.0" rm -f $TEST_TMPDIR/{__ts_start,__ts_end} if [ "$(type -t $TEST_name)" = function ]; then # Save exit handlers eventually set. local SAVED_ATEXIT="$ATEXIT"; ATEXIT= # Run test in a subshell. rm -f $TEST_TMPDIR/__err_handled __trap_with_arg __test_terminated INT KILL PIPE TERM ABRT FPE ILL QUIT SEGV ( timestamp >$TEST_TMPDIR/__ts_start set_up eval $TEST_name tear_down timestamp >$TEST_TMPDIR/__ts_end test $TEST_passed == "true" ) 2>&1 | tee $TEST_TMPDIR/__log # Note that tee will prevent the control flow continuing if the test # spawned any processes which are still running and have not closed # their stdout. test_subshell_status=${PIPESTATUS[0]} if [ "$test_subshell_status" != 0 ]; then TEST_passed="false" # Ensure that an end time is recorded in case the test subshell # terminated prematurely. [ -f $TEST_TMPDIR/__ts_end ] || timestamp >$TEST_TMPDIR/__ts_end fi # Calculate run time for the testcase. local ts_start=$(cat $TEST_TMPDIR/__ts_start) local ts_end=$(cat $TEST_TMPDIR/__ts_end) run_time=$(get_run_time $ts_start $ts_end) # Eventually restore exit handlers. if [ -n "$SAVED_ATEXIT" ]; then ATEXIT="$SAVED_ATEXIT" trap "$ATEXIT" EXIT fi else # Bad test explicitly specified in $TESTS. fail "Not a function: '$TEST_name'" fi local testcase_tag="" if [[ "$TEST_passed" == "true" ]]; then if [[ "$TEST_verbose" == "true" ]]; then echo "PASSED: $TEST_name" >&2 fi passed=$(($passed + 1)) testcase_tag="<testcase name=\"$TEST_name\" status=\"run\" time=\"$run_time\" classname=\"\"></testcase>" else echo "FAILED: $TEST_name" >&2 # end marker in CDATA cannot be escaped, we need to split the CDATA sections log=$(cat $TEST_TMPDIR/__log | sed 's/]]>/]]>]]><![CDATA[/g') fail_msg=$(cat $TEST_TMPDIR/__fail 2> /dev/null || echo "No failure message") testcase_tag="<testcase name=\"$TEST_name\" status=\"run\" time=\"$run_time\" classname=\"\"><error message=\"$fail_msg\"><![CDATA[$log]]></error></testcase>" fi if [[ "$TEST_verbose" == "true" ]]; then echo >&2 fi __log_to_test_report "<\/testsuite>" "$testcase_tag" done __finish_test_report $total $passed __pad "$passed / $total tests passed." '*' >&2 [ $total = $passed ] || { __pad "There were errors." '*' exit 1 } >&2 exit 0 } ������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/tests/unittest_test.sh�����������������������������������������������������������0000775�0000000�0000000�00000014452�15174450362�0020546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # End to end tests for unittest.bzl. # # Specifically, end to end tests of unittest.bzl cover verification that # analysis-phase tests written with unittest.bzl appropriately # cause test failures in cases where violated assertions are made. # --- begin runfiles.bash initialization --- set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function create_pkg() { local -r pkg="$1" mkdir -p "$pkg" cd "$pkg" cat > WORKSPACE <<EOF workspace(name = 'bazel_skylib') load("//lib:unittest.bzl", "register_unittest_toolchains") register_unittest_toolchains() EOF touch WORKSPACE.bzlmod cat > MODULE.bazel <<EOF module(name="bazel_skylib_test", repo_name="bazel_skylib") bazel_dep(name = "platforms", version = "0.0.10") register_toolchains( "//toolchains/unittest:cmd_toolchain", "//toolchains/unittest:bash_toolchain", ) EOF # Copy relevant skylib sources into the current workspace. mkdir -p tests touch tests/BUILD cat > tests/BUILD <<EOF exports_files(["*.bzl"]) EOF ln -sf "$(rlocation $TEST_WORKSPACE/tests/unittest_tests.bzl)" tests/unittest_tests.bzl mkdir -p lib touch lib/BUILD cat > lib/BUILD <<EOF exports_files(["*.bzl"]) EOF ln -sf "$(rlocation $TEST_WORKSPACE/lib/dicts.bzl)" lib/dicts.bzl ln -sf "$(rlocation $TEST_WORKSPACE/lib/new_sets.bzl)" lib/new_sets.bzl ln -sf "$(rlocation $TEST_WORKSPACE/lib/partial.bzl)" lib/partial.bzl ln -sf "$(rlocation $TEST_WORKSPACE/lib/sets.bzl)" lib/sets.bzl ln -sf "$(rlocation $TEST_WORKSPACE/lib/types.bzl)" lib/types.bzl ln -sf "$(rlocation $TEST_WORKSPACE/lib/unittest.bzl)" lib/unittest.bzl mkdir -p toolchains/unittest # Remove `package(default_applicable_license = ...)` line to avoid depending on rules_license inside this test sed -e '/package(default_applicable_licenses = .*)/d' \ "$(rlocation $TEST_WORKSPACE/toolchains/unittest/BUILD)" \ > toolchains/unittest/BUILD # Create test files. mkdir -p testdir cat > testdir/BUILD <<'EOF' load("//tests:unittest_tests.bzl", "basic_passing_test", "basic_failing_test", "failure_message_test", "fail_unexpected_passing_test", "fail_unexpected_passing_fake_rule") basic_passing_test(name = "basic_passing_test") basic_failing_test(name = "basic_failing_test") failure_message_test( name = "shell_escape_failure_message_test", message = "Contains $FOO", ) failure_message_test( name = "cmd_escape_failure_message_test", message = "Contains %FOO%", ) failure_message_test( name = "eof_failure_message_test", message = "\nEOF\n more after EOF", ) fail_unexpected_passing_test( name = "fail_unexpected_passing_test", target_under_test = ":fail_unexpected_passing_fake_target", ) fail_unexpected_passing_fake_rule( name = "fail_unexpected_passing_fake_target", tags = ["manual"]) EOF } function test_basic_passing_test() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:basic_passing_test >"$TEST_log" 2>&1 || fail "Expected test to pass" expect_log "PASSED" } function test_basic_failing_test() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:basic_failing_test --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log "In test _basic_failing_test from //tests:unittest_tests.bzl: Expected \"1\", but got \"2\"" } function test_shell_escape_failure_message_test() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:shell_escape_failure_message_test --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log 'In test _failure_message_test from //tests:unittest_tests.bzl: Expected "", but got "Contains $FOO"' } function test_cmd_escape_failure_message_test() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:cmd_escape_failure_message_test --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log 'In test _failure_message_test from //tests:unittest_tests.bzl: Expected "", but got "Contains %FOO%"' } function test_eof_failure_message_test() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:eof_failure_message_test --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log '^ more after EOF' } function test_fail_unexpected_passing_test() { local -r pkg="${FUNCNAME[0]}" create_pkg "$pkg" bazel test testdir:fail_unexpected_passing_test --test_output=all --verbose_failures \ >"$TEST_log" 2>&1 && fail "Expected test to fail" || true expect_log "Expected failure of target_under_test, but found success" } cd "$TEST_TMPDIR" run_suite "unittest test suite" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/tests/unittest_tests.bzl���������������������������������������������������������0000664�0000000�0000000�00000027354�15174450362�0021110�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for unittest.bzl.""" load("//lib:partial.bzl", "partial") load("//lib:unittest.bzl", "analysistest", "asserts", "loadingtest", "unittest") ################################### ####### basic_failing_test ######## ################################### def _basic_failing_test(ctx): """Unit tests for a basic library verification test that fails.""" env = unittest.begin(ctx) asserts.equals(env, 1, 2) return unittest.end(env) basic_failing_test = unittest.make(_basic_failing_test) ################################### ####### failure_message_test ###### ################################### def _failure_message_test(ctx): """Failing unit test with arbitrary content in the message.""" env = unittest.begin(ctx) if not ctx.attr.message: unittest.fail(env, "Message must be non-empty.") asserts.equals(env, "", ctx.attr.message) return unittest.end(env) failure_message_test = unittest.make( _failure_message_test, attrs = { "message": attr.string(), }, ) ################################### ####### basic_passing_test ######## ################################### def _basic_passing_test(ctx): """Unit tests for a basic library verification test.""" env = unittest.begin(ctx) asserts.equals(env, 1, 1) return unittest.end(env) basic_passing_test = unittest.make(_basic_passing_test) ################################################# ####### basic_passing_short_timeout_test ######## ################################################# def _basic_passing_short_timeout_test(ctx): """Unit tests for a basic library verification test.""" env = unittest.begin(ctx) asserts.equals(env, ctx.attr.timeout, "short") return unittest.end(env) basic_passing_short_timeout_test = unittest.make(_basic_passing_short_timeout_test) ################################### ####### change_setting_test ####### ################################### def _change_setting_test(ctx): """Test to verify that an analysis test may change configuration.""" env = analysistest.begin(ctx) dep_min_os_version = analysistest.target_under_test(env)[_ChangeSettingInfo].min_os_version asserts.equals(env, "1234.5678", dep_min_os_version) return analysistest.end(env) _ChangeSettingInfo = provider( doc = "min_os_version for change_setting_test", fields = ["min_os_version"], ) def _change_setting_fake_rule(ctx): return [_ChangeSettingInfo(min_os_version = ctx.fragments.cpp.minimum_os_version())] change_setting_fake_rule = rule( implementation = _change_setting_fake_rule, fragments = ["cpp"], ) change_setting_test = analysistest.make( _change_setting_test, config_settings = { "//command_line_option:minimum_os_version": "1234.5678", }, ) #################################### ####### failure_testing_test ####### #################################### def _failure_testing_test(ctx): """Test to verify that an analysis test may verify a rule fails with fail().""" env = analysistest.begin(ctx) asserts.expect_failure(env, "This rule should never work") return analysistest.end(env) def _failure_testing_fake_rule(ctx): _ignore = [ctx] # @unused fail("This rule should never work") failure_testing_fake_rule = rule( implementation = _failure_testing_fake_rule, ) failure_testing_test = analysistest.make( _failure_testing_test, expect_failure = True, ) ############################################ ####### fail_unexpected_passing_test ####### ############################################ def _fail_unexpected_passing_test(ctx): """Test that fails by expecting an error that never occurs.""" env = analysistest.begin(ctx) asserts.expect_failure(env, "Oh no, going to fail") return analysistest.end(env) def _fail_unexpected_passing_fake_rule(ctx): _ignore = [ctx] # @unused return [] fail_unexpected_passing_fake_rule = rule( implementation = _fail_unexpected_passing_fake_rule, ) fail_unexpected_passing_test = analysistest.make( _fail_unexpected_passing_test, expect_failure = True, ) ################################################ ####### change_setting_with_failure_test ####### ################################################ def _change_setting_with_failure_test(ctx): """Test verifying failure while changing configuration.""" env = analysistest.begin(ctx) asserts.expect_failure(env, "unexpected minimum_os_version!!!") return analysistest.end(env) def _change_setting_with_failure_fake_rule(ctx): if ctx.fragments.cpp.minimum_os_version() == "error_error": fail("unexpected minimum_os_version!!!") return [] change_setting_with_failure_fake_rule = rule( implementation = _change_setting_with_failure_fake_rule, fragments = ["cpp"], ) change_setting_with_failure_test = analysistest.make( _change_setting_with_failure_test, expect_failure = True, config_settings = { "//command_line_option:minimum_os_version": "error_error", }, ) #################################### ####### inspect_actions_test ####### #################################### def _inspect_actions_test(ctx): """Test verifying actions registered by a target.""" env = analysistest.begin(ctx) actions = analysistest.target_actions(env) asserts.equals(env, 1, len(actions)) action_output = actions[0].outputs.to_list()[0] asserts.equals(env, "out.txt", action_output.basename) return analysistest.end(env) def _inspect_actions_fake_rule(ctx): out_file = ctx.actions.declare_file("out.txt") ctx.actions.run_shell( command = "echo 'hello' > %s" % out_file.basename, outputs = [out_file], ) return [DefaultInfo(files = depset([out_file]))] inspect_actions_fake_rule = rule( implementation = _inspect_actions_fake_rule, ) inspect_actions_test = analysistest.make( _inspect_actions_test, ) #################################### ####### inspect_aspect_test ####### #################################### _AddedByAspectInfo = provider( doc = "Example provider added by example aspect", fields = { "value": "(str)", }, ) def _example_aspect_impl(target, ctx): _ignore = [target, ctx] # @unused return [ _AddedByAspectInfo(value = "attached by aspect"), ] example_aspect = aspect( implementation = _example_aspect_impl, ) def _inspect_aspect_test(ctx): """Test verifying aspect run on a target.""" env = analysistest.begin(ctx) tut = env.ctx.attr.target_under_test asserts.equals(env, "attached by aspect", tut[_AddedByAspectInfo].value) return analysistest.end(env) def _inspect_aspect_fake_rule(ctx): out_file = ctx.actions.declare_file("out.txt") ctx.actions.run_shell( command = "echo 'hello' > %s" % out_file.basename, outputs = [out_file], ) return [DefaultInfo(files = depset([out_file]))] inspect_aspect_fake_rule = rule( implementation = _inspect_aspect_fake_rule, ) inspect_aspect_test = analysistest.make( _inspect_aspect_test, extra_target_under_test_aspects = [example_aspect], ) ######################################## ####### inspect_output_dirs_test ####### ######################################## _OutputDirInfo = provider( doc = "bin_path for inspect_output_dirs_test", fields = ["bin_path"], ) def _inspect_output_dirs_test(ctx): """Test verifying output directories used by a test.""" env = analysistest.begin(ctx) # Assert that the output bin dir observed by the aspect added by analysistest # is the same as those observed by the rule directly, even when that's # under a config transition and therefore not the same as the bin dir # used by the test rule. bin_path = analysistest.target_bin_dir_path(env) target_under_test = analysistest.target_under_test(env) asserts.false(env, not bin_path, "bin dir path not found.") asserts.false( env, bin_path == ctx.bin_dir.path, "test bin dir (%s) expected to differ with target_under_test bin dir (%s)." % (bin_path, ctx.bin_dir.path), ) asserts.equals(env, bin_path, target_under_test[_OutputDirInfo].bin_path) return analysistest.end(env) def _inspect_output_dirs_fake_rule(ctx): return [ _OutputDirInfo( bin_path = ctx.bin_dir.path, ), ] inspect_output_dirs_fake_rule = rule( implementation = _inspect_output_dirs_fake_rule, ) inspect_output_dirs_test = analysistest.make( _inspect_output_dirs_test, # The output directories differ between the test and target under test when # the target under test is under a config transition. config_settings = { "//command_line_option:minimum_os_version": "1234.5678", }, ) def _loading_phase_test(env): loadingtest.equals(env, "self_glob", ["unittest_tests.bzl"], native.glob(["unittest_tests.bzl"])) # now use our own calls to assert we created a test case rule and test_suite for it. loadingtest.equals(env, "test_exists", True, native.existing_rule(env.name + "_self_glob") != None) loadingtest.equals(env, "suite_exists", True, native.existing_rule(env.name + "_tests") != None) ######################################### # buildifier: disable=unnamed-macro def unittest_passing_tests_suite(): """Creates the test targets and test suite for passing unittest.bzl tests. Not all tests are included. Some unittest.bzl tests verify a test fails when assertions are not met. Such tests must be run in an e2e shell test. This suite only includes tests which verify success tests. """ unittest.suite( "unittest_tests", basic_passing_test, partial.make(basic_passing_short_timeout_test, timeout = "short"), ) change_setting_test( name = "change_setting_test", target_under_test = ":change_setting_fake_target", ) change_setting_fake_rule( name = "change_setting_fake_target", tags = ["manual"], ) failure_testing_test( name = "failure_testing_test", target_under_test = ":failure_testing_fake_target", ) failure_testing_fake_rule( name = "failure_testing_fake_target", tags = ["manual"], ) change_setting_with_failure_test( name = "change_setting_with_failure_test", target_under_test = ":change_setting_with_failure_fake_target", ) change_setting_with_failure_fake_rule( name = "change_setting_with_failure_fake_target", tags = ["manual"], ) inspect_actions_test( name = "inspect_actions_test", target_under_test = ":inspect_actions_fake_target", ) inspect_actions_fake_rule( name = "inspect_actions_fake_target", tags = ["manual"], ) inspect_aspect_test( name = "inspect_aspect_test", target_under_test = ":inspect_aspect_fake_target", ) inspect_aspect_fake_rule( name = "inspect_aspect_fake_target", tags = ["manual"], ) inspect_output_dirs_test( name = "inspect_output_dirs_test", target_under_test = ":inspect_output_dirs_fake_target", ) inspect_output_dirs_fake_rule( name = "inspect_output_dirs_fake_target", tags = ["manual"], ) loading_env = loadingtest.make("selftest") _loading_phase_test(loading_env) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/tests/versions_tests.bzl���������������������������������������������������������0000664�0000000�0000000�00000005567�15174450362�0021103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2018 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unit tests for versions.bzl.""" load("//lib:unittest.bzl", "asserts", "unittest") load("//lib:versions.bzl", "versions") def _parse_test(ctx): """Unit tests for versions.parse""" env = unittest.begin(ctx) asserts.equals(env, (0, 10, 0), versions.parse("0.10.0rc1 abcd123")) asserts.equals(env, (0, 4, 0), versions.parse("0.4.0 abcd123")) asserts.equals(env, (0, 4, 0), versions.parse("0.4.0")) asserts.equals(env, (0, 4, 0), versions.parse("0.4.0rc")) # Verify that this doesn't fail - it corresponds to a dev build of Bazel. versions.parse("") return unittest.end(env) def _version_comparison_test(ctx): """Unit tests for versions.is_at_least and is_at_most""" env = unittest.begin(ctx) asserts.false(env, versions.is_at_least("0.11.0 123abcd", "0.10.0rc1 abcd123")) asserts.true(env, versions.is_at_least("0.9.0", "0.10.0rc2")) asserts.true(env, versions.is_at_least("0.9.0", "0.9.0rc3")) asserts.true(env, versions.is_at_least("0.9.0", "1.2.3")) asserts.true(env, versions.is_at_least("0.9.0", "")) asserts.false(env, versions.is_at_most("0.4.0 123abcd", "0.10.0rc1 abcd123")) asserts.true(env, versions.is_at_most("0.4.0", "0.3.0rc2")) asserts.true(env, versions.is_at_most("0.4.0", "0.4.0rc3")) asserts.true(env, versions.is_at_most("1.4.0", "0.4.0rc3")) asserts.false(env, versions.is_at_most("1.4.0", "")) return unittest.end(env) def _check_test(ctx): """Unit tests for versions.check""" env = unittest.begin(ctx) asserts.equals(env, None, versions.check("0.4.5 abcdef", bazel_version = "0.10.0rc1 abcd123")) asserts.equals(env, None, versions.check("0.4.5", bazel_version = "0.4.5")) asserts.equals(env, None, versions.check("0.4.5", bazel_version = "0.10.0rc1 abcd123")) asserts.equals(env, None, versions.check("0.4.5", maximum_bazel_version = "1.0.0", bazel_version = "0.10.0rc1 abcd123")) return unittest.end(env) parse_test = unittest.make(_parse_test) version_comparison_test = unittest.make(_version_comparison_test) check_test = unittest.make(_check_test) def versions_test_suite(): """Creates the test targets and test suite for versions.bzl tests.""" unittest.suite( "versions_tests", parse_test, version_comparison_test, check_test, ) �����������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/tests/write_file/����������������������������������������������������������������0000775�0000000�0000000�00000000000�15174450362�0017414�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/tests/write_file/BUILD�����������������������������������������������������������0000664�0000000�0000000�00000011100�15174450362�0020167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This package aids testing the 'write_file' rule. # # The package contains 4 write_file rules: # - 'write_empty_text' and 'write_empty_bin' write an empty text and an empty # executable file respectively # - 'write_nonempty_text' and 'write_nonempty_bin' write a non-empty text and # a non-empty executable file (a shell script) respectively # # The 'bin_empty' and 'bin_nonempty' rules are sh_binary rules. They use # the 'write_empty_bin' and 'write_nonempty_bin' rules respectively. The # sh_binary rule requires its source to be executable, so building these two # rules successfully means that 'write_file' managed to make its output # executable. # # The 'run_executables' genrule runs the 'bin_empty' and 'bin_nonempty' # binaries, partly to ensure they can be run, and partly so we can observe their # output and assert the contents in the 'write_file_tests' test. # # The 'file_deps' filegroup depends on 'write_empty_text'. The filegroup rule # uses the DefaultInfo.files field from its dependencies. When we data-depend on # the filegroup from 'write_file_tests', we transitively data-depend on the # DefaultInfo.files of the 'write_empty_text' rule. # # The 'write_file_tests' test is the actual integration test. It data-depends # on: # - the 'run_executables' rule, to get the outputs of 'bin_empty' and # 'bin_nonempty' # - the 'file_deps' rule, and by nature of using a filegroup, we get the files # from the DefaultInfo.files of the 'write_file' rule, and thereby assert that # that field contains the output file of the rule # - the 'write_nonempty_text' rule, and thereby on the DefaultInfo.runfiles # field of it, so we assert that that field contains the output file of the # rule load("@rules_shell//shell:sh_binary.bzl", "sh_binary") load("@rules_shell//shell:sh_test.bzl", "sh_test") load("//rules:diff_test.bzl", "diff_test") load("//rules:write_file.bzl", "write_file") package( default_applicable_licenses = ["//:license"], default_testonly = 1, ) licenses(["notice"]) sh_test( name = "write_file_tests", srcs = ["write_file_tests.sh"], data = [ ":run_executables", # Use DefaultInfo.files from 'write_empty_text' (via 'file_deps'). ":file_deps", # Use DefaultInfo.runfiles from 'write_nonempty_text'. ":write_nonempty_text", "//tests:unittest.bash", ], deps = ["@bazel_tools//tools/bash/runfiles"], ) filegroup( name = "file_deps", # Use DefaultInfo.files from 'write_empty_text'. srcs = [":write_empty_text"], ) # If 'run_executables' is built, then 'bin_nonempty' and 'bin_empty' are # executable, asserting that write_file makes the output executable. genrule( name = "run_executables", outs = [ "empty-bin-out.txt", "nonempty-bin-out.txt", ], cmd = ("$(location :bin_empty) > $(location empty-bin-out.txt) && " + "$(location :bin_nonempty) > $(location nonempty-bin-out.txt)"), output_to_bindir = 1, tools = [ ":bin_empty", ":bin_nonempty", ], ) # If 'bin_empty' is built, then 'write_empty_bin' made its output executable. sh_binary( name = "bin_empty", srcs = [":write_empty_bin"], ) # If 'bin_nonempty' is built, then 'write_nonempty_bin' made its output # executable. sh_binary( name = "bin_nonempty", srcs = [":write_nonempty_bin"], ) write_file( name = "write_empty_text", out = "out/empty.txt", ) write_file( name = "write_nonempty_text", out = "out/nonempty.txt", content = [ "aaa", "bbb", ], ) write_file( name = "write_empty_bin", out = "out/empty.sh", is_executable = True, ) write_file( name = "write_nonempty_bin", out = "out/nonempty.sh", content = [ "#!/usr/bin/env bash", "echo potato", ], is_executable = True, ) write_file( name = "newline_unix_actual", out = "out/newline_unix_actual.txt", content = [ "ab", "cd", "ef", ], newline = "unix", ) write_file( name = "newline_unix_exp", out = "out/newline_unix_exp.txt", content = ["ab\ncd\nef"], ) diff_test( name = "unix_line_ending_test", file1 = ":newline_unix_actual", file2 = ":newline_unix_exp", ) write_file( name = "newline_win_actual", out = "out/newline_win_actual.txt", content = [ "ab", "cd", "ef", ], newline = "windows", ) write_file( name = "newline_win_exp", out = "out/newline_win_exp.txt", content = ["ab\r\ncd\r\nef"], ) diff_test( name = "win_line_ending_test", file1 = ":newline_win_actual", file2 = ":newline_win_exp", ) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/tests/write_file/write_file_tests.sh���������������������������������������������0000775�0000000�0000000�00000005070�15174450362�0023330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/env bash # Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --- begin runfiles.bash initialization --- # Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). set -euo pipefail if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then if [[ -f "$0.runfiles_manifest" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" elif [[ -f "$0.runfiles/MANIFEST" ]]; then export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then export RUNFILES_DIR="$0.runfiles" fi fi if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" else echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" exit 1 fi # --- end runfiles.bash initialization --- source "$(rlocation $TEST_WORKSPACE/tests/unittest.bash)" \ || { echo "Could not source bazel_skylib/tests/unittest.bash" >&2; exit 1; } function assert_empty_file() { local -r path="$1" # Not using 'du' to check the file is empty, because it doesn't work on CI. [[ "$(echo -n "($(cat "$path"))")" = "()" ]] } function test_write_empty_text() { assert_empty_file "$(rlocation $TEST_WORKSPACE/tests/write_file/out/empty.txt)" } function test_write_nonempty_text() { cat "$(rlocation $TEST_WORKSPACE/tests/write_file/out/nonempty.txt)" >"$TEST_log" expect_log '^aaa' expect_log '^bbb' } function test_write_empty_bin() { assert_empty_file "$(rlocation $TEST_WORKSPACE/tests/write_file/empty-bin-out.txt)" } function test_write_nonempty_bin() { cat "$(rlocation $TEST_WORKSPACE/tests/write_file/nonempty-bin-out.txt)" >"$TEST_log" expect_log '^potato' } run_suite "write_file_tests test suite" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/toolchains/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�15174450362�0016264�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/toolchains/unittest/�������������������������������������������������������������0000775�0000000�0000000�00000000000�15174450362�0020143�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/toolchains/unittest/BUILD��������������������������������������������������������0000664�0000000�0000000�00000002544�15174450362�0020732�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������load("//lib:unittest.bzl", "TOOLCHAIN_TYPE", "unittest_toolchain") package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) toolchain_type( name = "toolchain_type", visibility = ["//visibility:public"], ) unittest_toolchain( name = "cmd", escape_chars_with = {"%": "%"}, failure_templ = """@echo off echo %s exit /b 1 """, file_ext = ".bat", join_on = "\necho ", success_templ = "@exit /b 0", visibility = ["//visibility:public"], ) toolchain( name = "cmd_toolchain", exec_compatible_with = [ "@platforms//os:windows", ], toolchain = ":cmd", toolchain_type = TOOLCHAIN_TYPE, ) unittest_toolchain( name = "bash", escape_other_chars_with = "\\", failure_templ = """#!/bin/sh echo %s exit 1 """, file_ext = ".sh", join_on = "\necho ", success_templ = "#!/bin/sh\nexit 0", visibility = ["//visibility:public"], ) toolchain( name = "bash_toolchain", toolchain = ":bash", toolchain_type = TOOLCHAIN_TYPE, ) filegroup( name = "test_deps", testonly = True, srcs = [ "BUILD", ], visibility = ["//:__subpackages__"], # Needs skylib's root BUILD file for default_applicable_licenses ) # The files needed for distribution filegroup( name = "distribution", srcs = ["BUILD"], visibility = [ "//:__pkg__", ], ) ������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/version.bzl����������������������������������������������������������������������0000664�0000000�0000000�00000001341�15174450362�0016316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """The version of bazel-skylib.""" # Keep in sync with MODULE.bazel and @bazel_skylib_gazelle_plugin//:MODULE.bazel version = "1.9.1" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bazel-skylib-1.9.1/workspace.bzl��������������������������������������������������������������������0000664�0000000�0000000�00000002715�15174450362�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright 2019 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Dependency registration helpers for repositories which need to load bazel-skylib.""" load("@bazel_skylib//lib:unittest.bzl", "register_unittest_toolchains") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") def bazel_skylib_workspace(): """Registers toolchains and declares repository dependencies of the bazel_skylib repository.""" maybe( http_archive, name = "rules_license", sha256 = "4531deccb913639c30e5c7512a054d5d875698daeb75d8cf90f284375fe7c360", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz", "https://github.com/bazelbuild/rules_license/releases/download/0.0.7/rules_license-0.0.7.tar.gz", ], ) register_unittest_toolchains() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������