From abcea13ab38c717c9927cab390af706767db4033 Mon Sep 17 00:00:00 2001 From: Julio Merino Date: Wed, 1 Nov 2023 05:40:37 -0700 Subject: [PATCH] Add basic implementation of rules_shtk for Bazel This change brings a new implementation of shtk build rules for Bazel, namely rules_shtk. It does so by: adding a new bazel_rules subdirectory, which contains the code of the rules_shtk; adding a new bazel_examples subdirectory, which provides end-to-end examples for usage of rules_shtk; and adding a new integration test (inttest) that leverages the bazel_examples to verify that the rules work as expected. --- .github/workflows/bazel.yml | 27 ++++++ .github/workflows/install.sh | 35 +++++++ .github/workflows/lint.yml | 10 ++ README.md | 12 +++ bazel_examples/.bazelrc | 1 + bazel_examples/.bazelversion | 1 + bazel_examples/.gitignore | 3 + bazel_examples/BUILD.bazel | 27 ++++++ bazel_examples/MODULE.bazel | 38 ++++++++ bazel_examples/Makefile | 46 +++++++++ bazel_examples/README.md | 13 +++ bazel_examples/WORKSPACE.bazel | 36 +++++++ bazel_examples/binary/BUILD.bazel | 34 +++++++ bazel_examples/binary/hello.sh | 34 +++++++ bazel_examples/inttest.sh | 80 ++++++++++++++++ bazel_examples/test/BUILD.bazel | 40 ++++++++ bazel_examples/test/adder.c | 75 +++++++++++++++ bazel_examples/test/adder_test.sh | 89 ++++++++++++++++++ bazel_rules/.bazelrc | 1 + bazel_rules/.bazelversion | 1 + bazel_rules/.gitignore | 1 + bazel_rules/BUILD.bazel | 44 +++++++++ bazel_rules/MODULE.bazel | 34 +++++++ bazel_rules/README.md | 71 ++++++++++++++ bazel_rules/WORKSPACE.bazel | 27 ++++++ bazel_rules/repositories.bzl | 151 ++++++++++++++++++++++++++++++ bazel_rules/rules.bzl | 125 +++++++++++++++++++++++++ bazel_rules/toolchain.BUILD.tpl | 43 +++++++++ bazel_rules/toolchains.bzl | 54 +++++++++++ bazel_rules/versions.bzl | 46 +++++++++ 30 files changed, 1199 insertions(+) create mode 100644 .github/workflows/bazel.yml create mode 100755 .github/workflows/install.sh create mode 100644 bazel_examples/.bazelrc create mode 100644 bazel_examples/.bazelversion create mode 100644 bazel_examples/.gitignore create mode 100644 bazel_examples/BUILD.bazel create mode 100644 bazel_examples/MODULE.bazel create mode 100644 bazel_examples/Makefile create mode 100644 bazel_examples/README.md create mode 100644 bazel_examples/WORKSPACE.bazel create mode 100644 bazel_examples/binary/BUILD.bazel create mode 100644 bazel_examples/binary/hello.sh create mode 100644 bazel_examples/inttest.sh create mode 100644 bazel_examples/test/BUILD.bazel create mode 100644 bazel_examples/test/adder.c create mode 100644 bazel_examples/test/adder_test.sh create mode 100644 bazel_rules/.bazelrc create mode 100644 bazel_rules/.bazelversion create mode 100644 bazel_rules/.gitignore create mode 100644 bazel_rules/BUILD.bazel create mode 100644 bazel_rules/MODULE.bazel create mode 100644 bazel_rules/README.md create mode 100644 bazel_rules/WORKSPACE.bazel create mode 100644 bazel_rules/repositories.bzl create mode 100644 bazel_rules/rules.bzl create mode 100644 bazel_rules/toolchain.BUILD.tpl create mode 100644 bazel_rules/toolchains.bzl create mode 100644 bazel_rules/versions.bzl diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml new file mode 100644 index 0000000..0149e16 --- /dev/null +++ b/.github/workflows/bazel.yml @@ -0,0 +1,27 @@ +name: Bazel integration + +on: [push, pull_request] + +jobs: + build-rules: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v3 + with: + path: ~/.cache/bazelisk + key: ${{ runner.os }}--${{ hashFiles('**/.bazelversion') }} + - uses: bazelbuild/setup-bazelisk@v2 + - run: cd bazel_rules && bazel build //... + + test-examples: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v3 + with: + path: ~/.cache/bazelisk + key: ${{ runner.os }}--${{ hashFiles('**/.bazelversion') }} + - uses: bazelbuild/setup-bazelisk@v2 + - run: ./.github/workflows/install.sh + - run: make -C bazel_examples diff --git a/.github/workflows/install.sh b/.github/workflows/install.sh new file mode 100755 index 0000000..901fb8b --- /dev/null +++ b/.github/workflows/install.sh @@ -0,0 +1,35 @@ +#! /bin/sh +# Copyright 2023 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -e -x + +autoreconf -isv +./configure +make +sudo make install diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ca04c3e..0a5465e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,3 +9,13 @@ jobs: - uses: actions/checkout@v4 - run: sudo apt-get install pre-commit - run: pre-commit run -a + + buildifier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/cache@v3 + with: + path: ~/.cache/bazelisk + key: ${{ runner.os }}--${{ hashFiles('**/.bazelversion') }} + - run: ./.github/workflows/buildifier.sh diff --git a/README.md b/README.md index aa2806e..b8f000c 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,18 @@ this repository, follow the instructions in the [INSTALL.md file](INSTALL.md). +Bazel integration +----------------- + +The `bazel_rules` directory provides the implementation of `rules_shtk`, a +collection of build rules for the [Bazel build system](https://bazel.build/) +to build and run `shtk` scripts. See their [`README.md`](bazel_rules/README.md) +for more details on usage. + +The `bazel_examples` directory provides sample usage of the rules. See their +[`README.md`](bazel_examples/README.md) for more details about them. + + Documentation ------------- diff --git a/bazel_examples/.bazelrc b/bazel_examples/.bazelrc new file mode 100644 index 0000000..3ce91d2 --- /dev/null +++ b/bazel_examples/.bazelrc @@ -0,0 +1 @@ +common --enable_bzlmod diff --git a/bazel_examples/.bazelversion b/bazel_examples/.bazelversion new file mode 100644 index 0000000..19b860c --- /dev/null +++ b/bazel_examples/.bazelversion @@ -0,0 +1 @@ +6.4.0 diff --git a/bazel_examples/.gitignore b/bazel_examples/.gitignore new file mode 100644 index 0000000..fe9d788 --- /dev/null +++ b/bazel_examples/.gitignore @@ -0,0 +1,3 @@ +bazel-* +inttest +!Makefile diff --git a/bazel_examples/BUILD.bazel b/bazel_examples/BUILD.bazel new file mode 100644 index 0000000..4c24019 --- /dev/null +++ b/bazel_examples/BUILD.bazel @@ -0,0 +1,27 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bazel_examples/MODULE.bazel b/bazel_examples/MODULE.bazel new file mode 100644 index 0000000..2ea5478 --- /dev/null +++ b/bazel_examples/MODULE.bazel @@ -0,0 +1,38 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +module( + name = "shtk_examples", + version = "0.0.0", +) + +bazel_dep(name = "rules_shtk", version = "1.7.0") +local_path_override( + module_name = "rules_shtk", + path = "../bazel_rules", +) diff --git a/bazel_examples/Makefile b/bazel_examples/Makefile new file mode 100644 index 0000000..5b785de --- /dev/null +++ b/bazel_examples/Makefile @@ -0,0 +1,46 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# Rules to run the integration tests for the examples. +# +# We could use Bazel itself to run these tests, but doing so is difficult +# because we need to run Bazel within Bazel and that's always tricky. +# That said, while those issues are surmountable, the integration tests +# themselves would rely on the shtk rules being functional and we cannot +# trust that they are. +# + +.PHONY: check +check: inttest + @rm -rf tmp && mkdir tmp + cd tmp && REAL_HOME=$$HOME WORKSPACE=$$(pwd)/.. ../inttest + @rm -rf tmp + +inttest: inttest.sh + shtk build -m shtk_unittest_main -o $@ $< diff --git a/bazel_examples/README.md b/bazel_examples/README.md new file mode 100644 index 0000000..6a1dbfd --- /dev/null +++ b/bazel_examples/README.md @@ -0,0 +1,13 @@ +# rules_shtk: Examples of usage with Bazel + +This directory contains examples on how to use the +[rules_shtk rules](../bazel_rules) with Bazel. + +Each subdirectory contained here provides one specific example scenario. +They all share the same `WORKSPACE.bazel` from this directory though. + +The examples are the following in order of "complexity": + +* `binary`: Simple usage of `shtk_binary`. +* `test`: Simple usage of `shtk_test` to perform end-to-end testing of + a binary written in C. diff --git a/bazel_examples/WORKSPACE.bazel b/bazel_examples/WORKSPACE.bazel new file mode 100644 index 0000000..8773bde --- /dev/null +++ b/bazel_examples/WORKSPACE.bazel @@ -0,0 +1,36 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +load("@rules_shtk//:repositories.bzl", "shtk_dist", "shtk_system") + +# Auto-discover an shtk that is at least the minimum version that our +# scripts need. +shtk_system(min_version = "1.6") + +# Fetch the shtk that corresponds to these rules. +shtk_dist() diff --git a/bazel_examples/binary/BUILD.bazel b/bazel_examples/binary/BUILD.bazel new file mode 100644 index 0000000..a8c7a48 --- /dev/null +++ b/bazel_examples/binary/BUILD.bazel @@ -0,0 +1,34 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +load("@rules_shtk//:rules.bzl", "shtk_binary") + +shtk_binary( + name = "simple", + src = "hello.sh", +) diff --git a/bazel_examples/binary/hello.sh b/bazel_examples/binary/hello.sh new file mode 100644 index 0000000..1b59eeb --- /dev/null +++ b/bazel_examples/binary/hello.sh @@ -0,0 +1,34 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +shtk_import cli + + +main() { + shtk_cli_info "Hello, world!" +} diff --git a/bazel_examples/inttest.sh b/bazel_examples/inttest.sh new file mode 100644 index 0000000..8702023 --- /dev/null +++ b/bazel_examples/inttest.sh @@ -0,0 +1,80 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +shtk_import cli +shtk_import unittest + + +one_time_setup() { + # REAL_HOME provides access to the Bazel and Bazelisk caches from within this + # test program. While not strictly necessary, this makes these tests much + # faster than they would otherwise and minimizes network traffic. + [ "${REAL_HOME-unset}" != unset ] \ + || shtk_cli_error "REAL_HOME must point to the user's home directory" + + # WORKSPACE points to the root of the bazel_examples directory so that we can + # run Bazel on it. + [ "${WORKSPACE-unset}" != unset ] \ + || shtk_cli_error "WORKSPACE must point to the bazel_examples directory" + + # Create a fake Bazel binary that is aware of our configuration variables + # above. We do this so that we can invoke this wrapper via assert_command. + local real_bazel="$(which bazel)" + cat >run_bazel < +#include +#include +#include +#include + +int16_t parse_int_arg(char* arg_name, char* arg_value) { + char *endptr; + errno = 0; + long val = strtol(arg_value, &endptr, 10); + + if (errno != 0) { + err(EXIT_FAILURE, "Invalid %s", arg_name); + } + + if (endptr == arg_value || *endptr != '\0') { + errx(EXIT_FAILURE, "Invalid %s: bad digits", arg_name); + } + + if (val > INT16_MAX || val < INT16_MIN) { + errx(EXIT_FAILURE, "Invalid %s: out of range", arg_name); + } + + return (int16_t) val; +} + +int main(int argc, char** argv) { + if (argc != 3) { + errx(EXIT_FAILURE, "Requires two integer arguments"); + } + int16_t x1 = parse_int_arg("first operand", argv[1]); + int16_t x2 = parse_int_arg("second operand", argv[2]); + + printf("The sum of %d and %d is %d\n", x1, x2, x1 + x2); + + return EXIT_SUCCESS; +} diff --git a/bazel_examples/test/adder_test.sh b/bazel_examples/test/adder_test.sh new file mode 100644 index 0000000..525bef6 --- /dev/null +++ b/bazel_examples/test/adder_test.sh @@ -0,0 +1,89 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +shtk_import unittest + + +shtk_unittest_add_test addition_works +addition_works_test() { + expect_command \ + -o inline:"The sum of 2 and 3 is 5\n" \ + ../test/adder 2 3 + + expect_command \ + -o inline:"The sum of -12345 and 12345 is 0\n" \ + ../test/adder -12345 12345 +} + + +shtk_unittest_add_test bad_first_operand +bad_first_operand_test() { + expect_command \ + -s 1 \ + -e inline:"adder: Invalid first operand: out of range\n" \ + ../test/adder 123456789 0 + + expect_command \ + -s 1 \ + -e inline:"adder: Invalid first operand: bad digits\n" \ + ../test/adder "" 0 + + expect_command \ + -s 1 \ + -e inline:"adder: Invalid first operand: bad digits\n" \ + ../test/adder 123x 0 + + expect_command \ + -s 1 \ + -e inline:"adder: Invalid first operand: out of range\n" \ + ../test/adder -123456789 0 +} + + +shtk_unittest_add_test bad_second_operand +bad_second_operand_test() { + expect_command \ + -s 1 \ + -e inline:"adder: Invalid second operand: out of range\n" \ + ../test/adder 0 123456789 + + expect_command \ + -s 1 \ + -e inline:"adder: Invalid second operand: bad digits\n" \ + ../test/adder 0 "" + + expect_command \ + -s 1 \ + -e inline:"adder: Invalid second operand: bad digits\n" \ + ../test/adder 0 123x + + expect_command \ + -s 1 \ + -e inline:"adder: Invalid second operand: out of range\n" \ + ../test/adder 0 -123456789 +} diff --git a/bazel_rules/.bazelrc b/bazel_rules/.bazelrc new file mode 100644 index 0000000..3ce91d2 --- /dev/null +++ b/bazel_rules/.bazelrc @@ -0,0 +1 @@ +common --enable_bzlmod diff --git a/bazel_rules/.bazelversion b/bazel_rules/.bazelversion new file mode 100644 index 0000000..19b860c --- /dev/null +++ b/bazel_rules/.bazelversion @@ -0,0 +1 @@ +6.4.0 diff --git a/bazel_rules/.gitignore b/bazel_rules/.gitignore new file mode 100644 index 0000000..ac51a05 --- /dev/null +++ b/bazel_rules/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/bazel_rules/BUILD.bazel b/bazel_rules/BUILD.bazel new file mode 100644 index 0000000..4fc2e9a --- /dev/null +++ b/bazel_rules/BUILD.bazel @@ -0,0 +1,44 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +load("@bazel_skylib//rules:common_settings.bzl", "string_setting") +load(":toolchains.bzl", "shtk_toolchain") +load(":versions.bzl", "versions") + +shtk_toolchain(name = "shtk_system_toolchain") + +toolchain_type( + name = "toolchain_type", + visibility = ["//visibility:public"], +) + +toolchain( + name = "system_toolchain", + toolchain = ":shtk_system_toolchain", + toolchain_type = ":toolchain_type", +) diff --git a/bazel_rules/MODULE.bazel b/bazel_rules/MODULE.bazel new file mode 100644 index 0000000..e34a9a4 --- /dev/null +++ b/bazel_rules/MODULE.bazel @@ -0,0 +1,34 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +module( + name = "rules_shtk", + version = "1.7.0", +) + +bazel_dep(name = "bazel_skylib", version = "1.4.2") diff --git a/bazel_rules/README.md b/bazel_rules/README.md new file mode 100644 index 0000000..4977b94 --- /dev/null +++ b/bazel_rules/README.md @@ -0,0 +1,71 @@ +# rules_shtk: Bazel rules for shtk + +This directory contains Bazel rules to build shtk scripts and run shtk tests +from Bazel. + +You can find examples under [bazel_examples](../bazel_examples/). + +## Set up + +To get started, add the following entry to your `MODULE.bazel`: + +```python +bazel_dep(name = "rules_shtk", version = "1.7.0") +``` + +Then, update your `WORKSPACE.bazel` file to load one or more shtk toolchains. +You can choose between: + +* `shtk_dist`, which downloads the version of shtk corresponding to the + rules and builds it. This is typically what you will want to use, + especially if all you care about is building tests. + + ```python + load("@rules_shtk//:repositories.bzl", "shtk_dist") + + # Use the shtk release that matches these rules (if these rules are version + # 1.7.0, then this uses shtk 1.7). + shtk_dist() + ``` + +* `shtk_system`, which discovers an shtk toolchain installed on the + system. Use this if you will want to install the built scripts. + + ```python + load("@rules_shtk//:repositories.bzl", "shtk_system") + + # Auto-discover the system-provided shtk by looking for shtk(1) in the PATH. + shtk_system() + + # Auto-discover the system-provided shtk by looking for shtk(1) in the PATH + # but ensure that it provides a minimum shtk version. + shtk_system(min_version = "1.7") + + # Load a system-provided shtk from the given location. + shtk_system(shtk_path = "/usr/local/bin/shtk") + ``` + +## Usage + +Define binaries like this: + +```python +load("@rules_shtk//:rules.bzl", "shtk_binary") + +shtk_binary( + name = "hello", + src = "hello.sh", +) +``` + +And tests like this: + +```python +load("@rules_shtk//:rules.bzl", "shtk_test") + +shtk_test( + name = "hello_test", + src = "hello_test.sh", + data = [":hello"], +) +``` diff --git a/bazel_rules/WORKSPACE.bazel b/bazel_rules/WORKSPACE.bazel new file mode 100644 index 0000000..4c24019 --- /dev/null +++ b/bazel_rules/WORKSPACE.bazel @@ -0,0 +1,27 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bazel_rules/repositories.bzl b/bazel_rules/repositories.bzl new file mode 100644 index 0000000..345b27d --- /dev/null +++ b/bazel_rules/repositories.bzl @@ -0,0 +1,151 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +load(":toolchains.bzl", "shtk_toolchain") +load(":versions.bzl", "versions") + +"""Version of shtk to use by these rules.""" +SHTK_VERSION = "1.7" + +"""Checksum of the distfile that provides SHTK_VERSION.""" +SHTK_SHA256 = "9386b7dbf1a28361eaf56dd1712385abdbdf3a02f03e17ccbf5579bf22695e27" + +def _shtk_autoconf_toolchain_impl(repository_ctx): + shtk_path = repository_ctx.attr.shtk_path + if not shtk_path: + shtk_path = str(repository_ctx.which("shtk")) + if not shtk_path: + fail("shtk cannot be found in the PATH") + + result = repository_ctx.execute([shtk_path, "version"]) + if result.return_code != 0: + fail("Failed to query shtk version; stdout: {}; stderr: {}".format( + result.stdout, + result.stderr, + )) + version = result.stdout.rstrip().split(" ")[1] + + if versions.lt(version, repository_ctx.attr.min_version): + fail("Repository requires shtk >= {} but {} provides {}".format( + repository_ctx.attr.min_version, + shtk_path, + version, + )) + + repository_ctx.template( + "BUILD.bazel", + repository_ctx.path(Label("@rules_shtk//:toolchain.BUILD.tpl")), + { + "%{shtk_path}": shtk_path, + "%{version}": version, + }, + ) + +_shtk_autoconf_toolchain = repository_rule( + implementation = _shtk_autoconf_toolchain_impl, + attrs = { + "shtk_path": attr.string( + doc = "Path to the shtk(1) binary if a specific one is desired.", + ), + "min_version": attr.string( + doc = "Minimum version of shtk(1) needed.", + ), + }, + configure = True, +) + +def shtk_system(min_version = SHTK_VERSION): + """Discovers and registers the system-installed shtk toolchain. + + This causes Bazel to look for shtk(1) in the path and makes it available + for use. + + Given that the toolchain is provided by the system, any scripts built by + Bazel using this toolchain can be copied out of bazel-bin and placed + elsewhere. + + Args: + min_version: The minimum version of shtk that we expect. If the + detected version is too old, this rule fails. + """ + _shtk_autoconf_toolchain(name = "shtk_autoconf", min_version = min_version) + native.register_toolchains("@shtk_autoconf//:toolchain") + +def _shtk_dist_toolchain_impl(repository_ctx): + version = repository_ctx.attr.version + url = "https://github.com/jmmv/shtk/releases/download/shtk-{}/shtk-{}.tar.gz".format(version, version) + + repository_ctx.download_and_extract( + url, + "shtk.tar.gz", + sha256 = repository_ctx.attr.sha256, + ) + + result = repository_ctx.execute( + [ + repository_ctx.which("sh"), + "-c", + "prefix=\"$(pwd)/local\" && cd {} && ./configure --prefix \"${{prefix}}\" && make install".format( + str(repository_ctx.path("shtk.tar.gz/shtk-" + version)), + ), + ], + ) + if result.return_code != 0: + fail("build failed: " + result.stdout + result.stderr) + + repository_ctx.template( + "BUILD.bazel", + repository_ctx.path(Label("@rules_shtk//:toolchain.BUILD.tpl")), + { + "%{shtk_path}": str(repository_ctx.path("local")) + "/bin/shtk", + "%{version}": version, + }, + ) + +_shtk_dist_toolchain = repository_rule( + implementation = _shtk_dist_toolchain_impl, + attrs = { + "version": attr.string(), + "sha256": attr.string(), + }, +) + +def shtk_dist(): + """Registers a released shtk toolchain. + + This will cause Bazel to download the shtk version that corresponds to these + rules (rules_shtk 1.7.0 pull shtk 1.7), build this toolchain, and make it + available for use. + + The toolchain is built under Bazel's external hierarchy and is ephemeral. + Therefore, you should not copy scripts built with this toolchain out of the + bazel-bin directory because they will not work correctly. + """ + repository = "shtk_dist_" + versions.canonicalize(SHTK_VERSION) + _shtk_dist_toolchain(name = repository, version = SHTK_VERSION, sha256 = SHTK_SHA256) + native.register_toolchains("@{}//:toolchain".format(repository)) diff --git a/bazel_rules/rules.bzl b/bazel_rules/rules.bzl new file mode 100644 index 0000000..94f7a47 --- /dev/null +++ b/bazel_rules/rules.bzl @@ -0,0 +1,125 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +load(":versions.bzl", "versions") + +def _shtk_build(ctx, mnemonic, main): + src = ctx.attr.src[DefaultInfo].files.to_list()[0] + out = ctx.actions.declare_file(ctx.attr.name) + info = ctx.toolchains["//:toolchain_type"].shtkinfo + + ctx.actions.run( + mnemonic = mnemonic, + executable = info.path, + arguments = ["build", "-m", main, "-o", out.path, src.short_path], + inputs = [src], + outputs = [out], + ) + + return out + +def _shtk_binary_impl(ctx): + out = _shtk_build(ctx, "ShtkBinary", "main") + + return [DefaultInfo( + files = depset([out]), + executable = out, + )] + +shtk_binary = rule( + doc = """ +Rule for creating an shtk binary. + +The binaries created by this rule are runnable with "bazel run" as usual. +However, whether the binaries can be copied out of bazel-bin for installation +onto the system or not depends on the toolchain that was used to build them. + +The input file to this rule should not be executable and should not carry +a shebang header. +""", + implementation = _shtk_binary_impl, + attrs = { + "src": attr.label( + doc = "Source file to \"compile\" with shtk.", + mandatory = True, + allow_single_file = True, + ), + }, + executable = True, + toolchains = ["//:toolchain_type"], +) + +def _shtk_test_impl(ctx): + out = _shtk_build(ctx, "ShtkTest", "shtk_unittest_main") + + runfiles = ctx.runfiles(files = ctx.files.data) + transitive_runfiles = [] + for target in ctx.attr.data: + transitive_runfiles.append(target[DefaultInfo].default_runfiles) + runfiles = runfiles.merge_all(transitive_runfiles) + + return [ + DefaultInfo( + files = depset([out]), + runfiles = runfiles, + executable = out, + ), + RunEnvironmentInfo( + environment = ctx.attr.env, + inherited_environment = ctx.attr.env_inherit, + ), + ] + +shtk_test = rule( + doc = """ +Rule for creating an shtk test. + +The input file to this rule should not be executable and should not carry +a shebang header. +""", + implementation = _shtk_test_impl, + attrs = { + "src": attr.label( + doc = "Source file of the test.", + mandatory = True, + allow_single_file = True, + ), + "data": attr.label_list( + doc = "Data files to place in the runfiles tree.", + allow_files = True, + ), + "env": attr.string_dict( + doc = "Environment variable name/value pairs to pass to the test.", + ), + "env_inherit": attr.string_list( + doc = "Environment variables to inherit in the test.", + ), + }, + toolchains = ["//:toolchain_type"], + test = True, +) diff --git a/bazel_rules/toolchain.BUILD.tpl b/bazel_rules/toolchain.BUILD.tpl new file mode 100644 index 0000000..9bc542b --- /dev/null +++ b/bazel_rules/toolchain.BUILD.tpl @@ -0,0 +1,43 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +load("@rules_shtk//:toolchains.bzl", "shtk_toolchain") +load("@rules_shtk//:versions.bzl", "versions") + +shtk_toolchain( + name = "shtk_toolchain", + shtk_path = "%{shtk_path}", + shtk_version = "%{version}", +) + +toolchain( + name = "toolchain", + toolchain = ":shtk_toolchain", + toolchain_type = "@rules_shtk//:toolchain_type", + visibility = ["//visibility:public"], +) diff --git a/bazel_rules/toolchains.bzl b/bazel_rules/toolchains.bzl new file mode 100644 index 0000000..71f7f58 --- /dev/null +++ b/bazel_rules/toolchains.bzl @@ -0,0 +1,54 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ShtkInfo = provider( + doc = "Details about the shtk(1) tool.", + fields = { + "path": "The path to the shtk(1) tool", + "version": "The version of the shtk(3) libraries", + # TODO(jmmv): Propagate what shell they use and allow selection. + # TODO(jmmv): Propagate provenance and allow selection. + }, +) + +def _shtk_toolchain_impl(ctx): + toolchain_info = platform_common.ToolchainInfo( + shtkinfo = ShtkInfo( + path = ctx.attr.shtk_path, + version = ctx.attr.shtk_version, + ), + ) + return [toolchain_info] + +shtk_toolchain = rule( + implementation = _shtk_toolchain_impl, + attrs = { + "shtk_path": attr.string(), + "shtk_version": attr.string(), + }, +) diff --git a/bazel_rules/versions.bzl b/bazel_rules/versions.bzl new file mode 100644 index 0000000..d8169ec --- /dev/null +++ b/bazel_rules/versions.bzl @@ -0,0 +1,46 @@ +# Copyright 2023 Julio Merino +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Utilities to manipulate shtk version numbers.""" + +def _lt(dotted_lhs, dotted_rhs): + """Given two dotted version numbers, returns true if the first one is + strictly before the second one.""" + lhs = [int(s) for s in dotted_lhs.split(".")] + rhs = [int(s) for s in dotted_rhs.split(".")] + return lhs < rhs + +def _canonicalize(dotted_version): + """Converts a dotted version number into its canonical form to appear in a + Bazel target name.""" + return dotted_version.replace(".", "_") + +versions = struct( + canonicalize = _canonicalize, + lt = _lt, +)