Skip to content

Commit

Permalink
Convert custom StarlarkValues to string for json.encode (#65)
Browse files Browse the repository at this point in the history
Custom `StarlarkValue`s can show up in `settings`, but are not supported
by `json.encode`. Convert them to strings before turning them into JSON
to fix issues such as:

```
Error in encode: in dict key "//command_line_option:compilation_mode": cannot encode CompilationMode as JSON
```

Fixes #63
  • Loading branch information
fmeum authored Feb 15, 2024
1 parent 3d3554a commit 6668529
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 1 deletion.
43 changes: 43 additions & 0 deletions examples/opt_filegroup_with_reset/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
load(":opt_filegroup.bzl", "opt_filegroup", "opt_filegroup_reset")
load("@with_cfg.bzl", "original_settings")

cc_binary(
name = "slow_to_run_app",
srcs = ["slow_to_run_app.cpp"],
# Don't unnecessarily build the app in fastbuild mode.
tags = ["manual"],
)

cc_binary(
name = "slow_to_build_app",
srcs = ["slow_to_build_app.cpp"],
tags = ["manual"],
)

opt_filegroup_reset(
name = "slow_to_build_app_reset",
exports = ":slow_to_build_app",
)

opt_filegroup(
name = "opt_test_data",
srcs = [
":slow_to_build_app_reset",
":slow_to_run_app",
],
)

sh_test(
name = "slow_apps_integration_test",
srcs = ["slow_apps_integration_test.sh"],
data = [":opt_test_data"],
env = select({
"@platforms//os:windows": {"EXE_SUFFIX": ".exe"},
"//conditions:default": {"EXE_SUFFIX": ""},
}),
deps = ["@bazel_tools//tools/bash/runfiles"],
)

original_settings(
name = "opt_filegroup_original_settings",
)
3 changes: 3 additions & 0 deletions examples/opt_filegroup_with_reset/opt_filegroup.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
load("@with_cfg.bzl", "with_cfg")

opt_filegroup, opt_filegroup_reset = with_cfg(native.filegroup).set("compilation_mode", "opt").resettable(Label(":opt_filegroup_original_settings")).build()
37 changes: 37 additions & 0 deletions examples/opt_filegroup_with_reset/slow_apps_integration_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash

# --- begin runfiles.bash initialization v3 ---
# Copy-pasted from the Bazel Bash runfiles library v3.
set -uo pipefail; set +e; 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 v3 ---

slow_to_run_app=$(rlocation "with_cfg_examples/opt_filegroup_with_reset/slow_to_run_app${EXE_SUFFIX}")
slow_to_build_app=$(rlocation "with_cfg_examples/opt_filegroup_with_reset/slow_to_build_app${EXE_SUFFIX}")

if [ "$(uname)" == "Darwin" ]; then
slow_to_run_app_realpath=$(python3 -c "import os, sys; print(os.path.realpath(sys.argv[1]))" "$slow_to_run_app")
slow_to_build_app_realpath=$(python3 -c "import os, sys; print(os.path.realpath(sys.argv[1]))" "$slow_to_build_app")
else
slow_to_run_app_realpath=$(realpath "$slow_to_run_app")
slow_to_build_app_realpath=$(realpath "$slow_to_build_app")
fi

if [[ "$slow_to_run_app_realpath" != *"-opt-ST-"*"/bin/opt_filegroup_with_reset/slow_to_run_app"* ]]; then
echo "ERROR: slow_to_run_app wasn't built in opt mode: $slow_to_run_app_realpath"
exit 1
fi

"$slow_to_run_app"

if [[ "$slow_to_build_app_realpath" != *"-fastbuild/bin/opt_filegroup_with_reset/slow_to_build_app"* ]]; then
echo "ERROR: slow_to_build_app wasn't built in fastbuild mode: $slow_to_build_app_realpath"
exit 1
fi

"$slow_to_build_app"
6 changes: 6 additions & 0 deletions examples/opt_filegroup_with_reset/slow_to_build_app.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <iostream>

int main(int arg, char** argv) {
std::cout << "This app is slow to build with optimizations." << std::endl;
return 0;
}
6 changes: 6 additions & 0 deletions examples/opt_filegroup_with_reset/slow_to_run_app.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <iostream>

int main(int arg, char** argv) {
std::cout << "This app is slow to run unless built in release mode." << std::endl;
return 0;
}
17 changes: 16 additions & 1 deletion with_cfg/private/transition.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _transition_base_impl(settings, attr, *, operations, original_settings_label
)

else:
new_settings[str(original_settings_label)] = json.encode(settings)
new_settings[str(original_settings_label)] = _encode_settings(settings)

return new_settings

Expand All @@ -99,3 +99,18 @@ def _get_settings_key(setting):
return "//command_line_option:" + setting
else:
fail("Expected Label or string, got: {} ({})".format(setting, type(setting)))

_STARLARK_TYPES = {
type(t): None
for t in [True, "", 0, 0.0, []]
}

def _encode_settings(settings):
# Certain setting values supplied by Bazel are special StarlarkValue types and thus unsupported
# by json.encode. We work around this by converting everything that isn't a native Starlark type
# to a string.
fixed_settings = {
k: v if type(v) in _STARLARK_TYPES else str(v)
for k, v in settings.items()
}
return json.encode(fixed_settings)

0 comments on commit 6668529

Please sign in to comment.