From 3168cc7e0ed3f2f67a1debef408d0f66c87f9d1d Mon Sep 17 00:00:00 2001 From: Ted Xie Date: Thu, 18 Jan 2024 11:28:51 -0800 Subject: [PATCH] New utility to extract pgcfg flags from desugar_jdk_libs JSON config Part of #122 PiperOrigin-RevId: 599570728 Change-Id: I8683c6841553dadf0747d9a721e377323b455d5c --- src/tools/extract_desugar_pgcfg_flags/BUILD | 22 +++++ .../extract_desugar_pgcfg_flags.go | 80 +++++++++++++++++++ .../extract_desugar_pgcfg_flags_test.sh | 58 ++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/tools/extract_desugar_pgcfg_flags/BUILD create mode 100644 src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags.go create mode 100755 src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags_test.sh diff --git a/src/tools/extract_desugar_pgcfg_flags/BUILD b/src/tools/extract_desugar_pgcfg_flags/BUILD new file mode 100644 index 00000000..4b4a90c2 --- /dev/null +++ b/src/tools/extract_desugar_pgcfg_flags/BUILD @@ -0,0 +1,22 @@ +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test") + +# Utility and test for extracting pgcfg flags from the desugar_jdk_libs config JSON file. +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:public"], +) + +licenses(["notice"]) + +go_binary( + name = "extract_desugar_pgcfg_flags", + srcs = ["extract_desugar_pgcfg_flags.go"], +) + +sh_test( + name = "extract_desugar_pgcfg_flags_test", + srcs = ["extract_desugar_pgcfg_flags_test.sh"], + args = ["--binary_under_test $(location :extract_desugar_pgcfg_flags)"], + tools = [":extract_desugar_pgcfg_flags"], +) diff --git a/src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags.go b/src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags.go new file mode 100644 index 00000000..e139963d --- /dev/null +++ b/src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags.go @@ -0,0 +1,80 @@ +// 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. + +// Tool for extracting the shrinker_config field from desugar_jdk_libs's json config file. +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "strings" +) + +var ( + inputJSONFlag = flag.String("input_json", "", "Path to the R8 desugar_jdk_libs.json file") + outputFileFlag = flag.String("output_file", "", "Path to the output file for the extracted pgcfg.") +) + +func main() { + flag.Parse() + + // Check that the input and output file flags are populated. + if *inputJSONFlag == "" { + log.Fatal("--input_json is required") + } + if *outputFileFlag == "" { + log.Fatal("--output_file is required") + } + + // Read the input json file + jsonFile, err := os.Open(*inputJSONFlag) + if err != nil { + log.Fatal(err) + } + + defer jsonFile.Close() + + // Parse the JSON + jsonBytes, err := ioutil.ReadAll(jsonFile) + if err != nil { + log.Fatal(err) + } + + // The r8 desugar config json schema is pretty complicated (+subject to change), and we only + // need one field, so instead of reading into a predefined data structure, we just read into a + // map[string]any to keep things simple. + var result map[string]any + json.Unmarshal(jsonBytes, &result) + + // Read the shrinker_config field as a string, then trim the demarcating [ ] characters. + shrinkerConfigAsString := strings.TrimRight(strings.TrimLeft(fmt.Sprintf("%v", result["shrinker_config"]), "["), "]") + shrinkerConfigList := strings.Split(shrinkerConfigAsString, " ") + // Massage into newline-separated flag list. + shrinkerConfigFlags := strings.Join(shrinkerConfigList, "\n") + + // Write the shrinker config to the output file + shrinkerConfigFile, err := os.Create(*outputFileFlag) + if err != nil { + log.Fatal(err) + } + defer shrinkerConfigFile.Close() + + if _, err := shrinkerConfigFile.WriteString(shrinkerConfigFlags); err != nil { + log.Fatal(err) + } +} diff --git a/src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags_test.sh b/src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags_test.sh new file mode 100755 index 00000000..8358149b --- /dev/null +++ b/src/tools/extract_desugar_pgcfg_flags/extract_desugar_pgcfg_flags_test.sh @@ -0,0 +1,58 @@ +#!/bin/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. + +# Basic end-to-end test for extracting pgcfg flags from desugarer JSON config. + +BINARY_UNDER_TEST= +function ParseArgs() { + while [[ $# -gt 0 ]]; do + case "$1" in + "--binary_under_test") + BINARY_UNDER_TEST="$2" + shift + ;; + *) + die "Unknown argument '$1'" + ;; + esac + + shift + done +} + +# Test setup: get path to binary under test +ParseArgs "$@" +readonly BINARY_UNDER_TEST + +set -euxo pipefail + +# Create dummy data +dummy_json_file="$(mktemp)" +# Dummy data: shrinker_config is a list of strings, and another unrelated field. +echo "{\"shrinker_config\": [\"a\", \"b\", \"c\"], \"foo\": \"bar\"}" > "$dummy_json_file" + +# Dummy output dummy output file +test_output_file="$(mktemp)" +expected_output_file="$(mktemp)" +# Expected outcome is a\nb\nc +echo -ne "a\nb\nc" > "$expected_output_file" + +# Run the binary on the test data +"$BINARY_UNDER_TEST" --input_json "$dummy_json_file" --output_file "$test_output_file" + +# Expect the files to be the same +diff "$test_output_file" "$expected_output_file" + +echo "PASS"