diff --git a/.bazelversion b/.bazelversion index 4ac4fde..c0be8a7 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -6.2.0 \ No newline at end of file +6.4.0 \ No newline at end of file diff --git a/intellij/patches/bazel_intellij_aspect_filter.patch b/intellij/patches/bazel_intellij_aspect_filter.patch new file mode 100644 index 0000000..01642cd --- /dev/null +++ b/intellij/patches/bazel_intellij_aspect_filter.patch @@ -0,0 +1,60 @@ +Copyright 2020 The Monogon Project Authors. + +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. + + +# We need to patch the IntelliJ Bazel aspect that is injected via the @intellij_bazel repository +# to: +# - properly resolve go_library rules that have both source files and embeds. +# - allow running test/sync against //... which contains cc_toolchain rules +# (see https://github.com/bazelbuild/intellij/issues/1344 ) +--- a/intellij_info_impl_bundled.bzl ++++ b/intellij_info_impl_bundled.bzl +@@ -13,6 +13,7 @@ + ":make_variables.bzl", + "expand_make_variables", + ) ++load("@io_bazel_rules_go//go:def.bzl", "GoLibrary") + + # Defensive list of features that can appear in the C++ toolchain, but which we + # definitely don't want to enable (when enabled, they'd contribute command line +@@ -350,6 +351,8 @@ + "go_appengine_test", + ]: + sources = [f for src in getattr(ctx.rule.attr, "srcs", []) for f in src.files.to_list()] ++ sources += [f for embed in getattr(ctx.rule.attr, "embed", []) for f in _collect_generated_go_sources(embed, ctx, semantics) or []] ++ + generated = [f for f in sources if not f.is_source] + elif ctx.rule.kind == "go_wrap_cc": + genfiles = target.files.to_list() +@@ -372,6 +375,10 @@ + if go_semantics: + import_path = go_semantics.get_import_path(ctx) + ++ if import_path == None and getattr(ctx.rule.attr, "embed", None) != None and ctx.rule.kind == "go_library": ++ embed_attr = getattr(ctx.rule.attr, "embed", None) ++ import_path = embed_attr[0][GoLibrary].importpath ++ + library_labels = [] + if ctx.rule.kind == "go_test" or ctx.rule.kind == "go_appengine_test": + if getattr(ctx.rule.attr, "library", None) != None: +@@ -457,6 +464,8 @@ + return False + if cc_common.CcToolchainInfo not in target: + return False ++ if type(target[cc_common.CcToolchainInfo]) != 'CcToolchainInfo': ++ return False + + # cc toolchain to access compiler flags + cpp_toolchain = target[cc_common.CcToolchainInfo] + diff --git a/shell.nix b/shell.nix index 241bf32..7600b58 100644 --- a/shell.nix +++ b/shell.nix @@ -15,12 +15,21 @@ let export NIX_SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt" export SSL_CERT_FILE="${cacert}/etc/ssl/certs/ca-bundle.crt" + # Let some downstream machinery know we're on NixOS. This is used mostly to + # work around Bazel/NixOS interactions. + export MONOGON_NIXOS=yep + # Convince rules_go to use /bin/bash and not a NixOS store bash which has # no idea how to resolve other things in the nix store once PATH is # stripped by (host_)action_env. export BAZEL_SH=/bin/bash - exec bash --noprofile --norc + # Allow passing a custom command via env since nix-shell doesn't support + # this yet: https://github.com/NixOS/nix/issues/534 + if [ ! -n "$COMMAND" ]; then + COMMAND="bash --noprofile --norc" + fi + exec $COMMAND ''; in (pkgs.buildFHSUserEnv { @@ -28,6 +37,7 @@ in targetPkgs = pkgs: with pkgs; [ git bazel_6 + openjdk21 ]; runScript = wrapper; }).env diff --git a/third_party/nix/sources.json b/third_party/nix/sources.json index 0e9dd95..6391d1b 100644 --- a/third_party/nix/sources.json +++ b/third_party/nix/sources.json @@ -1,14 +1,14 @@ { "nixpkgs": { - "branch": "release-23.05", + "branch": "release-23.11", "description": "Nix Packages collection", "homepage": null, "owner": "NixOS", "repo": "nixpkgs", - "rev": "b9fc1843e64c11665ef440d02ecb6b3980a62756", - "sha256": "0krzc81cn1vfblhljw9wgx1wkfwlifh9dy3z3c64yhkh3xy6pfji", + "rev": "d2003f2223cbb8cd95134e4a0541beea215c1073", + "sha256": "0n2a72jb0j1iya7j05r6hbvmsnm4ai05g4lmxnfbah87gxl3d9qg", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/b9fc1843e64c11665ef440d02ecb6b3980a62756.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/d2003f2223cbb8cd95134e4a0541beea215c1073.tar.gz", "url_template": "https://github.com///archive/.tar.gz" } } diff --git a/tools/bazel b/tools/bazel new file mode 100755 index 0000000..3263209 --- /dev/null +++ b/tools/bazel @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +# Both bazelisk and bazel's native wrapper scripts will attempt to use the well-known executable +# named "tools/bazel" to run Bazel. The path of the original executable is stored in BAZEL_REAL. +set -euo pipefail +shopt -s nullglob + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Jump into nix-shell if BAZEL_REAL is set to a /nix/store path and we aren't +# inside our shell yet. +if [[ "${BAZEL_REAL:-}" == /nix/store/* && -z "${MONOGON_NIXOS:-}" ]]; then + echo "Detected Nix based bazel installation and we are not in a nix-shell, overriding to nix-shell." >&2 + USE_NIX_SHELL=yes +fi + +# If the wrapper is called directly we check if nix-shell is available +# to automagically switch into the nix-shell. Otherwise complain and +# exit. +if [[ -z "${BAZEL_REAL:-}" ]]; then + if [[ -x $(command -v nix-shell) ]]; then + echo "BAZEL_REAL is not set and nix-shell is available, overriding to nix-shell" >&2 + USE_NIX_SHELL=yes + else + echo "BAZEL_REAL is not set and nix-shell not available. Please check the setup guide." >&2 + exit 1 + fi +fi + +if [[ -n "${USE_NIX_SHELL:-}" ]]; then + # Jump to project root since bwrap hangs if we aren't there + cd "${DIR}/../" + + export COMMAND="bazel $*" + export PWD="$OLDPWD" + exec nix-shell +fi + + +prechecks() { + # Recommend using Bazelisk instead of Bazel's "bazel.sh" wrapper. + # Skip if we're inside the Nix shell (which uses a customized Bazel build). + if [[ -z "${BAZELISK_SKIP_WRAPPER:-}" && -z "${MONOGON_NIXOS:-}" ]]; then + echo "############################################################" >&2 + echo "# Please use Bazelisk to build NetMeta. Using Bazel #" >&2 + echo "# directly may work, but is not recommended or supported. #" >&2 + echo "############################################################" >&2 + fi +} + +intellij_patch() { + # When IntelliJ's Bazel plugin uses //scripts/bin/bazel to either build targets + # or run syncs, it adds a --override_repository flag to the bazel command + # line that points @intellij_aspect into a path on the filesystem. This + # external repository contains a Bazel Aspect definition which Bazel + # executes to provide the IntelliJ Bazel plugin with information about the + # workspace / build targets / etc... + # + # We need to patch the aspect definition to fix a number of bugs + # to make it work with the Monogon monorepo. + # Find all IntelliJ installation/config directories. + local ij_home_paths=("${HOME}/.local/share/JetBrains/IntelliJIdea"*) + # Get the newest one, if any. + local ij_home="" + if ! [[ ${#ij_home_paths[@]} -eq 0 ]]; then + # Reverse sort paths by name, with the first being the newest IntelliJ + # installation. + IFS=$'\n' + local sorted=($(sort -r <<<"${ij_home_paths[*]}")) + unset IFS + ij_home="${sorted[0]}" + fi + # If we don't have or can't find ij_home, don't bother with attempting to patch anything. + if [[ -d "${ij_home}" ]]; then + # aspect_path is the path to the aspect external repository that IntelliJ will + # inject into bazel via --override_repository. + local aspect_path="${ij_home}/ijwb/aspect" + # Our copy of it. + local patched_path="${ij_home}/ijwb/aspect-monogon" + # Checksum of the patch that was used to create patched_path. + local checksum_file="${patched_path}/checksum" + # The patch + local patch_file="${DIR}/../intellij/patches/bazel_intellij_aspect_filter.patch" + # The checksum of the patch we're about to apply. + local checksum + checksum=$(sha256sum "$patch_file" | cut -d' ' -f1) + # If the patched aspect repository doesn't exist, or the checksum of the patch + # we're about to apply doesn't match the checksum of the patch that was used + # to create the patched aspect repository, apply the patch. + if ! [[ -d "${patched_path}" ]] || ! [[ "$(cat "${checksum_file}")" == "${checksum}" ]]; then + echo "IntelliJ found at ${ij_home}, patching aspect repository." >&2 + # Copy the aspect repository to the patched path. + rm -rf "${patched_path}" + cp -r "${aspect_path}" "${patched_path}" + # Apply the patch. + patch -d "${patched_path}" -p1 < "${patch_file}" + # Write the checksum of the patch to the checksum file. + echo "${checksum}" > "${checksum_file}" + else + echo "IntelliJ found at ${ij_home}, aspect repository already patched." >&2 + fi + fi +} + +prechecks +intellij_patch + +# Find the --override_repository=intellij_aspect=[path] +# argument in $@ and replace the path with the patched version. +# This is surprisingly tricky - bash special-cases "$@" to expand +# as "$1" "$2" ... "$n" so that argv is preserved, so we need to +# modify the real $@ array. +for i in $(seq 1 $#); do + if [[ "${!i}" == "--override_repository=intellij_aspect="* ]]; then + new_arg="${!i/\/aspect/\/aspect-monogon}" + set -- "${@:1:$((i-1))}" "${new_arg}" "${@:$((i+1))}" + fi +done + +exec -a "$0" "${BAZEL_REAL}" "$@" \ No newline at end of file