diff options
-rw-r--r-- | android/apex.go | 3 | ||||
-rw-r--r-- | android/bazel_handler.go | 4 | ||||
-rw-r--r-- | bazel/aquery.go | 16 | ||||
-rw-r--r-- | bazel/aquery_test.go | 107 | ||||
-rw-r--r-- | bp2build/conversion.go | 7 | ||||
-rw-r--r-- | bp2build/conversion_test.go | 74 | ||||
-rw-r--r-- | cc/builder.go | 12 | ||||
-rw-r--r-- | cc/cc.go | 4 | ||||
-rw-r--r-- | cc/stl.go | 7 | ||||
-rw-r--r-- | java/config/kotlin.go | 9 | ||||
-rw-r--r-- | java/java.go | 2 | ||||
-rw-r--r-- | java/kotlin.go | 9 | ||||
-rwxr-xr-x | scripts/toc.sh | 30 |
13 files changed, 196 insertions, 88 deletions
diff --git a/android/apex.go b/android/apex.go index 01ac9b3f8..7f9f0f5c3 100644 --- a/android/apex.go +++ b/android/apex.go @@ -809,8 +809,10 @@ var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel { "androidx.arch.core_core-common-nodeps": 29, "androidx.collection_collection-nodeps": 29, "androidx.collection_collection-ktx-nodeps": 30, + "androidx.concurrent_concurrent-futures-nodeps": 30, "androidx.lifecycle_lifecycle-common-java8-nodeps": 30, "androidx.lifecycle_lifecycle-common-nodeps": 29, + "androidx.room_room-common-nodeps": 30, "androidx-constraintlayout_constraintlayout-solver-nodeps": 29, "apache-commons-compress": 29, "bouncycastle_ike_digests": 30, @@ -820,6 +822,7 @@ var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel { "flatbuffer_headers": 30, "framework-permission": 30, "gemmlowp_headers": 30, + "guava-listenablefuture-prebuilt-jar": 30, "ike-internals": 30, "kotlinx-coroutines-android": 28, "kotlinx-coroutines-android-nodeps": 30, diff --git a/android/bazel_handler.go b/android/bazel_handler.go index abc793f8e..ba5231f2c 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -692,6 +692,10 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { cmd.Implicit(PathForBazelOut(ctx, inputPath)) } + if depfile := buildStatement.Depfile; depfile != nil { + cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile)) + } + // This is required to silence warnings pertaining to unexpected timestamps. Particularly, // some Bazel builtins (such as files in the bazel_tools directory) have far-future // timestamps. Without restat, Ninja would emit warnings that the input files of a diff --git a/bazel/aquery.go b/bazel/aquery.go index c82b464ad..555f1dcb4 100644 --- a/bazel/aquery.go +++ b/bazel/aquery.go @@ -74,6 +74,7 @@ type actionGraphContainer struct { // with a Bazel action from Bazel's action graph. type BuildStatement struct { Command string + Depfile *string OutputPaths []string InputPaths []string Env []KeyValuePair @@ -133,12 +134,22 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) { continue } outputPaths := []string{} + var depfile *string for _, outputId := range actionEntry.OutputIds { outputPath, exists := artifactIdToPath[outputId] if !exists { return nil, fmt.Errorf("undefined outputId %d", outputId) } - outputPaths = append(outputPaths, outputPath) + ext := filepath.Ext(outputPath) + if ext == ".d" { + if depfile != nil { + return nil, fmt.Errorf("found multiple potential depfiles %q, %q", *depfile, outputPath) + } else { + depfile = &outputPath + } + } else { + outputPaths = append(outputPaths, outputPath) + } } inputPaths := []string{} for _, inputDepSetId := range actionEntry.InputDepSetIds { @@ -161,12 +172,13 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) { } buildStatement := BuildStatement{ Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "), + Depfile: depfile, OutputPaths: outputPaths, InputPaths: inputPaths, Env: actionEntry.EnvironmentVariables, Mnemonic: actionEntry.Mnemonic} if len(actionEntry.Arguments) < 1 { - return nil, fmt.Errorf("received action with no command: [%s]", buildStatement) + return nil, fmt.Errorf("received action with no command: [%v]", buildStatement) continue } buildStatements = append(buildStatements, buildStatement) diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go index a48e0834a..fa8810f0d 100644 --- a/bazel/aquery_test.go +++ b/bazel/aquery_test.go @@ -393,6 +393,109 @@ func TestInvalidPathFragmentId(t *testing.T) { assertError(t, err, "undefined path fragment id 3") } +func TestDepfiles(t *testing.T) { + const inputString = ` +{ + "artifacts": [{ + "id": 1, + "pathFragmentId": 1 + }, { + "id": 2, + "pathFragmentId": 2 + }, { + "id": 3, + "pathFragmentId": 3 + }], + "actions": [{ + "targetId": 1, + "actionKey": "x", + "mnemonic": "x", + "arguments": ["touch", "foo"], + "inputDepSetIds": [1], + "outputIds": [2, 3], + "primaryOutputId": 2 + }], + "depSetOfFiles": [{ + "id": 1, + "directArtifactIds": [1, 2, 3] + }], + "pathFragments": [{ + "id": 1, + "label": "one" + }, { + "id": 2, + "label": "two" + }, { + "id": 3, + "label": "two.d" + }] +}` + + actual, err := AqueryBuildStatements([]byte(inputString)) + if err != nil { + t.Errorf("Unexpected error %q", err) + } + if expected := 1; len(actual) != expected { + t.Fatalf("Expected %d build statements, got %d", expected, len(actual)) + } + + bs := actual[0] + expectedDepfile := "two.d" + if bs.Depfile == nil { + t.Errorf("Expected depfile %q, but there was none found", expectedDepfile) + } else if *bs.Depfile != expectedDepfile { + t.Errorf("Expected depfile %q, but got %q", expectedDepfile, *bs.Depfile) + } +} + +func TestMultipleDepfiles(t *testing.T) { + const inputString = ` +{ + "artifacts": [{ + "id": 1, + "pathFragmentId": 1 + }, { + "id": 2, + "pathFragmentId": 2 + }, { + "id": 3, + "pathFragmentId": 3 + }, { + "id": 4, + "pathFragmentId": 4 + }], + "actions": [{ + "targetId": 1, + "actionKey": "x", + "mnemonic": "x", + "arguments": ["touch", "foo"], + "inputDepSetIds": [1], + "outputIds": [2,3,4], + "primaryOutputId": 2 + }], + "depSetOfFiles": [{ + "id": 1, + "directArtifactIds": [1, 2, 3, 4] + }], + "pathFragments": [{ + "id": 1, + "label": "one" + }, { + "id": 2, + "label": "two" + }, { + "id": 3, + "label": "two.d" + }, { + "id": 4, + "label": "other.d" + }] +}` + + _, err := AqueryBuildStatements([]byte(inputString)) + assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`) +} + func TestTransitiveInputDepsets(t *testing.T) { // The input aquery for this test comes from a proof-of-concept starlark rule which registers // a single action with many inputs given via a deep depset. @@ -627,7 +730,7 @@ func assertError(t *testing.T, err error, expected string) { // Build statement equivalence is determined using buildStatementEquals. func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) { if len(expected) != len(actual) { - t.Errorf("expected %d build statements, but got %d,\n expected: %s,\n actual: %s", + t.Errorf("expected %d build statements, but got %d,\n expected: %v,\n actual: %v", len(expected), len(actual), expected, actual) return } @@ -638,7 +741,7 @@ ACTUAL_LOOP: continue ACTUAL_LOOP } } - t.Errorf("unexpected build statement %s.\n expected: %s", + t.Errorf("unexpected build statement %v.\n expected: %v", actualStatement, expected) return } diff --git a/bp2build/conversion.go b/bp2build/conversion.go index 787222d6e..6b47cd1f1 100644 --- a/bp2build/conversion.go +++ b/bp2build/conversion.go @@ -19,12 +19,13 @@ func CreateBazelFiles( ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { - files := make([]BazelFile, 0, len(ruleShims)+len(buildToTargets)+numAdditionalFiles) - // Write top level files: WORKSPACE. These files are empty. - files = append(files, newFile("", "WORKSPACE", "")) + var files []BazelFile if mode == QueryView { + // Write top level WORKSPACE. + files = append(files, newFile("", "WORKSPACE", "")) + // Used to denote that the top level directory is a package. files = append(files, newFile("", GeneratedBuildFileName, "")) diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go index a115ddcd6..9fd68172c 100644 --- a/bp2build/conversion_test.go +++ b/bp2build/conversion_test.go @@ -24,36 +24,6 @@ type filepath struct { basename string } -func assertFilecountsAreEqual(t *testing.T, actual []BazelFile, expected []filepath) { - if a, e := len(actual), len(expected); a != e { - t.Errorf("Expected %d files, got %d", e, a) - } -} - -func assertFileContent(t *testing.T, actual []BazelFile, expected []filepath) { - for i := range actual { - if g, w := actual[i], expected[i]; g.Dir != w.dir || g.Basename != w.basename { - t.Errorf("Did not find expected file %s/%s", g.Dir, g.Basename) - } else if g.Basename == "BUILD" || g.Basename == "WORKSPACE" { - if g.Contents != "" { - t.Errorf("Expected %s to have no content.", g) - } - } else if g.Contents == "" { - t.Errorf("Contents of %s unexpected empty.", g) - } - } -} - -func sortFiles(files []BazelFile) { - sort.Slice(files, func(i, j int) bool { - if dir1, dir2 := files[i].Dir, files[j].Dir; dir1 == dir2 { - return files[i].Basename < files[j].Basename - } else { - return dir1 < dir2 - } - }) -} - func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) { files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, QueryView) expectedFilePaths := []filepath{ @@ -79,21 +49,39 @@ func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) { }, } - assertFilecountsAreEqual(t, files, expectedFilePaths) - sortFiles(files) - assertFileContent(t, files, expectedFilePaths) + // Compare number of files + if a, e := len(files), len(expectedFilePaths); a != e { + t.Errorf("Expected %d files, got %d", e, a) + } + + // Sort the files to be deterministic + sort.Slice(files, func(i, j int) bool { + if dir1, dir2 := files[i].Dir, files[j].Dir; dir1 == dir2 { + return files[i].Basename < files[j].Basename + } else { + return dir1 < dir2 + } + }) + + // Compare the file contents + for i := range files { + actualFile, expectedFile := files[i], expectedFilePaths[i] + + if actualFile.Dir != expectedFile.dir || actualFile.Basename != expectedFile.basename { + t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename) + } else if actualFile.Basename == "BUILD" || actualFile.Basename == "WORKSPACE" { + if actualFile.Contents != "" { + t.Errorf("Expected %s to have no content.", actualFile) + } + } else if actualFile.Contents == "" { + t.Errorf("Contents of %s unexpected empty.", actualFile) + } + } } -func TestCreateBazelFiles_Bp2Build_AddsTopLevelFiles(t *testing.T) { +func TestCreateBazelFiles_Bp2Build_CreatesNoFilesWithNoTargets(t *testing.T) { files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, Bp2Build) - expectedFilePaths := []filepath{ - { - dir: "", - basename: "WORKSPACE", - }, + if len(files) != 0 { + t.Errorf("Expected no files, got %d", len(files)) } - - assertFilecountsAreEqual(t, files, expectedFilePaths) - sortFiles(files) - assertFileContent(t, files, expectedFilePaths) } diff --git a/cc/builder.go b/cc/builder.go index 4771b8932..8c9743ff4 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -182,11 +182,11 @@ var ( blueprint.RuleParams{ Depfile: "${out}.d", Deps: blueprint.DepsGCC, - Command: "CROSS_COMPILE=$crossCompile $tocPath $format -i ${in} -o ${out} -d ${out}.d", + Command: "CLANG_BIN=$clangBin $tocPath $format -i ${in} -o ${out} -d ${out}.d", CommandDeps: []string{"$tocPath"}, Restat: true, }, - "crossCompile", "format") + "clangBin", "format") // Rule for invoking clang-tidy (a clang-based linter). clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy", @@ -918,16 +918,12 @@ func transformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Pat outputFile android.WritablePath, flags builderFlags) { var format string - var crossCompile string if ctx.Darwin() { format = "--macho" - crossCompile = "${config.MacToolPath}" } else if ctx.Windows() { format = "--pe" - crossCompile = gccCmd(flags.toolchain, "") } else { format = "--elf" - crossCompile = gccCmd(flags.toolchain, "") } ctx.Build(pctx, android.BuildParams{ @@ -936,8 +932,8 @@ func transformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Pat Output: outputFile, Input: inputFile, Args: map[string]string{ - "crossCompile": crossCompile, - "format": format, + "clangBin": "${config.ClangBin}", + "format": format, }, }) } @@ -1892,8 +1892,8 @@ func (c *Module) deps(ctx DepsContext) Deps { } for _, lib := range deps.ReexportStaticLibHeaders { - if !inList(lib, deps.StaticLibs) { - ctx.PropertyErrorf("export_static_lib_headers", "Static library not in static_libs: '%s'", lib) + if !inList(lib, deps.StaticLibs) && !inList(lib, deps.WholeStaticLibs) { + ctx.PropertyErrorf("export_static_lib_headers", "Static library not in static_libs or whole_static_libs: '%s'", lib) } } @@ -188,12 +188,7 @@ func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { if needsLibAndroidSupport(ctx) { deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support") } - // TODO: Switch the NDK over to the LLVM unwinder for non-arm32 architectures. - if ctx.Arch().ArchType == android.Arm { - deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind") - } else { - deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped") - } + deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind") default: panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) } diff --git a/java/config/kotlin.go b/java/config/kotlin.go index fd8e3dbe9..6cb61f306 100644 --- a/java/config/kotlin.go +++ b/java/config/kotlin.go @@ -35,11 +35,16 @@ func init() { pctx.SourcePathVariable("KotlinAnnotationJar", "external/kotlinc/lib/annotations-13.0.jar") pctx.SourcePathVariable("KotlinStdlibJar", KotlinStdlibJar) - // These flags silence "Illegal reflective access" warnings when running kotlinc in OpenJDK9 - pctx.StaticVariable("KotlincSuppressJDK9Warnings", strings.Join([]string{ + // These flags silence "Illegal reflective access" warnings when running kapt in OpenJDK9+ + pctx.StaticVariable("KaptSuppressJDK9Warnings", strings.Join([]string{ "-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", "-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "-J--add-opens=java.base/sun.net.www.protocol.jar=ALL-UNNAMED", }, " ")) + + // These flags silence "Illegal reflective access" warnings when running kotlinc in OpenJDK9+ + pctx.StaticVariable("KotlincSuppressJDK9Warnings", strings.Join([]string{ + "-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704 + }, " ")) } diff --git a/java/java.go b/java/java.go index 26e5091b6..3ffe5729e 100644 --- a/java/java.go +++ b/java/java.go @@ -776,7 +776,7 @@ func (j *TestHost) AddExtraResource(p android.Path) { func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) { if j.testProperties.Test_options.Unit_test == nil && ctx.Host() { // TODO(b/): Clean temporary heuristic to avoid unexpected onboarding. - defaultUnitTest := !inList("tradefed", j.properties.Static_libs) && !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites) + defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites) j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest) } j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template, diff --git a/java/kotlin.go b/java/kotlin.go index 2960f819d..3a6fc0f48 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -34,8 +34,9 @@ var kotlinc = pctx.AndroidRemoteStaticRule("kotlinc", android.RemoteRuleSupports `${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` + ` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` + ` $commonSrcFilesArg --out "$kotlinBuildFile" && ` + - `${config.KotlincCmd} ${config.JavacHeapFlags} $kotlincFlags ` + - `-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile -kotlin-home $emptyDir && ` + + `${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} ` + + `$kotlincFlags -jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile ` + + `-kotlin-home $emptyDir && ` + `${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir && ` + `rm -rf "$srcJarDir"`, CommandDeps: []string{ @@ -123,8 +124,8 @@ var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: `${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` + ` --srcs "$out.rsp" --srcs "$srcJarDir/list"` + ` $commonSrcFilesArg --out "$kotlinBuildFile" && ` + - `${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} $kotlincFlags ` + - `-Xplugin=${config.KotlinKaptJar} ` + + `${config.KotlincCmd} ${config.KaptSuppressJDK9Warnings} ${config.KotlincSuppressJDK9Warnings} ` + + `${config.JavacHeapFlags} $kotlincFlags -Xplugin=${config.KotlinKaptJar} ` + `-P plugin:org.jetbrains.kotlin.kapt3:sources=$kaptDir/sources ` + `-P plugin:org.jetbrains.kotlin.kapt3:classes=$kaptDir/classes ` + `-P plugin:org.jetbrains.kotlin.kapt3:stubs=$kaptDir/stubs ` + diff --git a/scripts/toc.sh b/scripts/toc.sh index 8b1d25fb9..af8bece94 100755 --- a/scripts/toc.sh +++ b/scripts/toc.sh @@ -17,7 +17,7 @@ # Script to handle generating a .toc file from a .so file # Inputs: # Environment: -# CROSS_COMPILE: prefix added to readelf tool +# CLANG_BIN: path to the clang bin directory # Arguments: # -i ${file}: input file (required) # -o ${file}: output file (required) @@ -35,34 +35,34 @@ EOF } do_elf() { - ("${CROSS_COMPILE}readelf" -d "${infile}" | grep SONAME || echo "No SONAME for ${infile}") > "${outfile}.tmp" - "${CROSS_COMPILE}readelf" --dyn-syms "${infile}" | awk '{$2=""; $3=""; print}' >> "${outfile}.tmp" + ("${CLANG_BIN}/llvm-readelf" -d "${infile}" | grep SONAME || echo "No SONAME for ${infile}") > "${outfile}.tmp" + "${CLANG_BIN}/llvm-readelf" --dyn-syms "${infile}" | awk '{$2=""; $3=""; print}' >> "${outfile}.tmp" cat <<EOF > "${depsfile}" ${outfile}: \\ - ${CROSS_COMPILE}readelf \\ + ${CLANG_BIN}/llvm-readelf \\ EOF } do_macho() { - "${CROSS_COMPILE}/otool" -l "${infile}" | grep LC_ID_DYLIB -A 5 > "${outfile}.tmp" - "${CROSS_COMPILE}/nm" -gP "${infile}" | cut -f1-2 -d" " | (grep -v 'U$' >> "${outfile}.tmp" || true) + "${CLANG_BIN}/llvm-objdump" -p "${infile}" | grep LC_ID_DYLIB -A 5 > "${outfile}.tmp" + "${CLANG_BIN}/llvm-nm" -gP "${infile}" | cut -f1-2 -d" " | (grep -v 'U$' >> "${outfile}.tmp" || true) cat <<EOF > "${depsfile}" ${outfile}: \\ - ${CROSS_COMPILE}/otool \\ - ${CROSS_COMPILE}/nm \\ + ${CLANG_BIN}/llvm-objdump \\ + ${CLANG_BIN}/llvm-nm \\ EOF } do_pe() { - "${CROSS_COMPILE}objdump" -x "${infile}" | grep "^Name" | cut -f3 -d" " > "${outfile}.tmp" - "${CROSS_COMPILE}nm" -g -f p "${infile}" | cut -f1-2 -d" " >> "${outfile}.tmp" + "${CLANG_BIN}/llvm-objdump" -x "${infile}" | grep "^Name" | cut -f3 -d" " > "${outfile}.tmp" + "${CLANG_BIN}/llvm-nm" -g -f p "${infile}" | cut -f1-2 -d" " >> "${outfile}.tmp" cat <<EOF > "${depsfile}" ${outfile}: \\ - ${CROSS_COMPILE}objdump \\ - ${CROSS_COMPILE}nm \\ + ${CLANG_BIN}/llvm-objdump \\ + ${CLANG_BIN}/llvm-nm \\ EOF } @@ -98,8 +98,8 @@ if [ -z "${depsfile:-}" ]; then usage fi -if [ -z "${CROSS_COMPILE:-}" ]; then - echo "CROSS_COMPILE environment variable must be set" +if [ -z "${CLANG_BIN:-}" ]; then + echo "CLANG_BIN environment variable must be set" usage fi @@ -107,7 +107,7 @@ rm -f "${outfile}.tmp" cat <<EOF > "${depsfile}" ${outfile}: \\ - ${CROSS_COMPILE}readelf \\ + ${CLANG_BIN}/llvm-readelf \\ EOF if [ -n "${elf:-}" ]; then |