diff options
22 files changed, 1371 insertions, 337 deletions
diff --git a/apex/apex_test.go b/apex/apex_test.go index 54c1facd5..4e6aa1353 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -8713,196 +8713,6 @@ func TestApexPermittedPackagesRules(t *testing.T) { } } -func TestTestFor(t *testing.T) { - t.Parallel() - ctx := testApex(t, ` - apex { - name: "myapex", - key: "myapex.key", - native_shared_libs: ["mylib", "myprivlib"], - updatable: false, - } - - apex_key { - name: "myapex.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - - cc_library { - name: "mylib", - srcs: ["mylib.cpp"], - system_shared_libs: [], - stl: "none", - stubs: { - versions: ["1"], - }, - apex_available: ["myapex"], - } - - cc_library { - name: "myprivlib", - srcs: ["mylib.cpp"], - system_shared_libs: [], - stl: "none", - apex_available: ["myapex"], - } - - - cc_test { - name: "mytest", - gtest: false, - srcs: ["mylib.cpp"], - system_shared_libs: [], - stl: "none", - shared_libs: ["mylib", "myprivlib", "mytestlib"], - test_for: ["myapex"] - } - - cc_library { - name: "mytestlib", - srcs: ["mylib.cpp"], - system_shared_libs: [], - shared_libs: ["mylib", "myprivlib"], - stl: "none", - test_for: ["myapex"], - } - - cc_benchmark { - name: "mybench", - srcs: ["mylib.cpp"], - system_shared_libs: [], - shared_libs: ["mylib", "myprivlib"], - stl: "none", - test_for: ["myapex"], - } - `) - - ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) { - ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").Args["libFlags"], " ") - mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) }) - android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags) - } - - // These modules are tests for the apex, therefore are linked to the - // actual implementation of mylib instead of its stub. - ensureLinkedLibIs("mytest", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") - ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") - ensureLinkedLibIs("mybench", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") -} - -func TestIndirectTestFor(t *testing.T) { - t.Parallel() - ctx := testApex(t, ` - apex { - name: "myapex", - key: "myapex.key", - native_shared_libs: ["mylib", "myprivlib"], - updatable: false, - } - - apex_key { - name: "myapex.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - - cc_library { - name: "mylib", - srcs: ["mylib.cpp"], - system_shared_libs: [], - stl: "none", - stubs: { - versions: ["1"], - }, - apex_available: ["myapex"], - } - - cc_library { - name: "myprivlib", - srcs: ["mylib.cpp"], - system_shared_libs: [], - stl: "none", - shared_libs: ["mylib"], - apex_available: ["myapex"], - } - - cc_library { - name: "mytestlib", - srcs: ["mylib.cpp"], - system_shared_libs: [], - shared_libs: ["myprivlib"], - stl: "none", - test_for: ["myapex"], - } - `) - - ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) { - ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").Args["libFlags"], " ") - mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) }) - android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags) - } - - // The platform variant of mytestlib links to the platform variant of the - // internal myprivlib. - ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/myprivlib/", "android_arm64_armv8-a_shared/myprivlib.so") - - // The platform variant of myprivlib links to the platform variant of mylib - // and bypasses its stubs. - ensureLinkedLibIs("myprivlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") -} - -func TestTestForForLibInOtherApex(t *testing.T) { - t.Parallel() - // This case is only allowed for known overlapping APEXes, i.e. the ART APEXes. - _ = testApex(t, ` - apex { - name: "com.android.art", - key: "myapex.key", - native_shared_libs: ["libnativebridge"], - updatable: false, - } - - apex { - name: "com.android.art.debug", - key: "myapex.key", - native_shared_libs: ["libnativebridge", "libnativebrdige_test"], - updatable: false, - } - - apex_key { - name: "myapex.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - - cc_library { - name: "libnativebridge", - srcs: ["libnativebridge.cpp"], - system_shared_libs: [], - stl: "none", - stubs: { - versions: ["1"], - }, - apex_available: ["com.android.art", "com.android.art.debug"], - } - - cc_library { - name: "libnativebrdige_test", - srcs: ["mylib.cpp"], - system_shared_libs: [], - shared_libs: ["libnativebridge"], - stl: "none", - apex_available: ["com.android.art.debug"], - test_for: ["com.android.art"], - } - `, - android.MockFS{ - "system/sepolicy/apex/com.android.art-file_contexts": nil, - "system/sepolicy/apex/com.android.art.debug-file_contexts": nil, - }.AddToFixture()) -} - // TODO(jungjw): Move this to proptools func intPtr(i int) *int { return &i @@ -3361,10 +3361,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { func ShouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool { depName := ctx.OtherModuleName(dep) - thisModule, ok := ctx.Module().(android.ApexModule) - if !ok { - panic(fmt.Errorf("Not an APEX module: %q", ctx.ModuleName())) - } inVendorOrProduct := false bootstrap := false @@ -3394,34 +3390,6 @@ func ShouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool { isNotInPlatform := dep.(android.ApexModule).NotInPlatform() useStubs = isNotInPlatform && !bootstrap - - if useStubs { - // Another exception: if this module is a test for an APEX, then - // it is linked with the non-stub variant of a module in the APEX - // as if this is part of the APEX. - testFor, _ := android.ModuleProvider(ctx, android.ApexTestForInfoProvider) - for _, apexContents := range testFor.ApexContents { - if apexContents.DirectlyInApex(depName) { - useStubs = false - break - } - } - } - if useStubs { - // Yet another exception: If this module and the dependency are - // available to the same APEXes then skip stubs between their - // platform variants. This complements the test_for case above, - // which avoids the stubs on a direct APEX library dependency, by - // avoiding stubs for indirect test dependencies as well. - // - // TODO(b/183882457): This doesn't work if the two libraries have - // only partially overlapping apex_available. For that test_for - // modules would need to be split into APEX variants and resolved - // separately for each APEX they have access to. - if android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) { - useStubs = false - } - } } else { // If building for APEX, use stubs when the parent is in any APEX that // the child is not in. diff --git a/cc/cc_test.go b/cc/cc_test.go index 22f7c9f35..989b043be 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -1505,111 +1505,6 @@ func TestVersionedStubs(t *testing.T) { } } -func TestStubsForLibraryInMultipleApexes(t *testing.T) { - t.Parallel() - ctx := testCc(t, ` - cc_library_shared { - name: "libFoo", - srcs: ["foo.c"], - stubs: { - symbol_file: "foo.map.txt", - versions: ["current"], - }, - apex_available: ["bar", "a1"], - } - - cc_library_shared { - name: "libBar", - srcs: ["bar.c"], - shared_libs: ["libFoo"], - apex_available: ["a1"], - } - - cc_library_shared { - name: "libA1", - srcs: ["a1.c"], - shared_libs: ["libFoo"], - apex_available: ["a1"], - } - - cc_library_shared { - name: "libBarA1", - srcs: ["bara1.c"], - shared_libs: ["libFoo"], - apex_available: ["bar", "a1"], - } - - cc_library_shared { - name: "libAnyApex", - srcs: ["anyApex.c"], - shared_libs: ["libFoo"], - apex_available: ["//apex_available:anyapex"], - } - - cc_library_shared { - name: "libBaz", - srcs: ["baz.c"], - shared_libs: ["libFoo"], - apex_available: ["baz"], - } - - cc_library_shared { - name: "libQux", - srcs: ["qux.c"], - shared_libs: ["libFoo"], - apex_available: ["qux", "bar"], - }`) - - variants := ctx.ModuleVariantsForTests("libFoo") - expectedVariants := []string{ - "android_arm64_armv8-a_shared", - "android_arm64_armv8-a_shared_current", - "android_arm_armv7-a-neon_shared", - "android_arm_armv7-a-neon_shared_current", - } - variantsMismatch := false - if len(variants) != len(expectedVariants) { - variantsMismatch = true - } else { - for _, v := range expectedVariants { - if !inList(v, variants) { - variantsMismatch = false - } - } - } - if variantsMismatch { - t.Errorf("variants of libFoo expected:\n") - for _, v := range expectedVariants { - t.Errorf("%q\n", v) - } - t.Errorf(", but got:\n") - for _, v := range variants { - t.Errorf("%q\n", v) - } - } - - linkAgainstFoo := []string{"libBarA1"} - linkAgainstFooStubs := []string{"libBar", "libA1", "libBaz", "libQux", "libAnyApex"} - - libFooPath := "libFoo/android_arm64_armv8-a_shared/libFoo.so" - for _, lib := range linkAgainstFoo { - libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld") - libFlags := libLinkRule.Args["libFlags"] - if !strings.Contains(libFlags, libFooPath) { - t.Errorf("%q: %q is not found in %q", lib, libFooPath, libFlags) - } - } - - libFooStubPath := "libFoo/android_arm64_armv8-a_shared_current/libFoo.so" - for _, lib := range linkAgainstFooStubs { - libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld") - libFlags := libLinkRule.Args["libFlags"] - if !strings.Contains(libFlags, libFooStubPath) { - t.Errorf("%q: %q is not found in %q", lib, libFooStubPath, libFlags) - } - } -} - func TestVersioningMacro(t *testing.T) { t.Parallel() for _, tc := range []struct{ moduleName, expected string }{ diff --git a/cmd/find_input_delta/find_input_delta/Android.bp b/cmd/find_input_delta/find_input_delta/Android.bp new file mode 100644 index 000000000..6b2dbc764 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta/Android.bp @@ -0,0 +1,18 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-find_input_delta", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta", + deps: [ + "golang-protobuf-encoding-prototext", + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + "soong-cmd-find_input_delta-proto", + "soong-cmd-find_input_delta-lib", + ], + srcs: [ + "main.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta/main.go b/cmd/find_input_delta/find_input_delta/main.go new file mode 100644 index 000000000..6b657ea57 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta/main.go @@ -0,0 +1,88 @@ +// Copyright 2024 Google Inc. 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. + +package main + +import ( + "flag" + "os" + "strings" + + fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib" +) + +func main() { + var top string + var prior_state_file string + var new_state_file string + var target string + var inputs_file string + var template string + var inputs []string + var inspect bool + var err error + + flag.StringVar(&top, "top", ".", "path to top of workspace") + flag.StringVar(&prior_state_file, "prior_state", "", "prior internal state file") + flag.StringVar(&new_state_file, "new_state", "", "new internal state file") + flag.StringVar(&target, "target", "", "name of ninja output file for build action") + flag.StringVar(&inputs_file, "inputs_file", "", "file containing list of input files") + flag.StringVar(&template, "template", fid_lib.DefaultTemplate, "output template for FileList") + flag.BoolVar(&inspect, "inspect", false, "whether to inspect file contents") + + flag.Parse() + + if target == "" { + panic("must specify --target") + } + if prior_state_file == "" { + prior_state_file = target + ".pc_state" + } + if new_state_file == "" { + new_state_file = prior_state_file + ".new" + } + + if err = os.Chdir(top); err != nil { + panic(err) + } + + inputs = flag.Args() + if inputs_file != "" { + data, err := os.ReadFile(inputs_file) + if err != nil { + panic(err) + } + inputs = append(inputs, strings.Split(string(data), "\n")...) + } + + // Read the prior state + prior_state, err := fid_lib.LoadState(prior_state_file, fid_lib.OsFs) + if err != nil { + panic(err) + } + // Create the new state + new_state, err := fid_lib.CreateState(inputs, inspect, fid_lib.OsFs) + if err != nil { + panic(err) + } + if err = fid_lib.WriteState(new_state, new_state_file); err != nil { + panic(err) + } + + file_list := *fid_lib.CompareInternalState(prior_state, new_state, target) + + if err = file_list.Format(os.Stdout, template); err != nil { + panic(err) + } +} diff --git a/cmd/find_input_delta/find_input_delta_lib/Android.bp b/cmd/find_input_delta/find_input_delta_lib/Android.bp new file mode 100644 index 000000000..795b14038 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/Android.bp @@ -0,0 +1,34 @@ +// Copyright 2024 Google Inc. 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. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-lib", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta_lib", + deps: [ + "golang-protobuf-encoding-prototext", + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + "soong-cmd-find_input_delta-proto", + "blueprint-pathtools", + ], + srcs: [ + "fs.go", + "file_list.go", + "internal_state.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta_lib/file_list.go b/cmd/find_input_delta/find_input_delta_lib/file_list.go new file mode 100644 index 000000000..23337adc3 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/file_list.go @@ -0,0 +1,78 @@ +// Copyright 2024 Google Inc. 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. + +package find_input_delta_lib + +import ( + "io" + "text/template" + + fid_exp "android/soong/cmd/find_input_delta/find_input_delta_proto" + "google.golang.org/protobuf/proto" +) + +var DefaultTemplate = ` + {{- define "contents"}} + {{- range .Deletions}}-{{.}} {{end}} + {{- range .Additions}}+{{.}} {{end}} + {{- range .Changes}}+{{- .Name}} {{end}} + {{- range .Changes}} + {{- if or .Additions .Deletions .Changes}}--file {{.Name}} {{template "contents" .}}--endfile {{end}} + {{- end}} + {{- end}} + {{- template "contents" .}}` + +type FileList struct { + // The name of the parent for the list of file differences. + // For the outermost FileList, this is the name of the ninja target. + // Under `Changes`, it is the name of the changed file. + Name string + + // The added files + Additions []string + + // The deleted files + Deletions []string + + // The modified files + Changes []FileList +} + +func (fl FileList) Marshal() (*fid_exp.FileList, error) { + ret := &fid_exp.FileList{ + Name: proto.String(fl.Name), + } + if len(fl.Additions) > 0 { + ret.Additions = fl.Additions + } + for _, ch := range fl.Changes { + change, err := ch.Marshal() + if err != nil { + return nil, err + } + ret.Changes = append(ret.Changes, change) + } + if len(fl.Deletions) > 0 { + ret.Deletions = fl.Deletions + } + return ret, nil +} + +func (fl FileList) Format(wr io.Writer, format string) error { + tmpl, err := template.New("filelist").Parse(format) + if err != nil { + return err + } + return tmpl.Execute(wr, fl) +} diff --git a/cmd/find_input_delta/find_input_delta_lib/file_list_test.go b/cmd/find_input_delta/find_input_delta_lib/file_list_test.go new file mode 100644 index 000000000..2459f1ead --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/file_list_test.go @@ -0,0 +1,131 @@ +// Copyright 2024 Google Inc. 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. + +package find_input_delta_lib + +import ( + "bytes" + "slices" + "testing" + + // For Assert*. + "android/soong/android" +) + +func (fl *FileList) Equal(other *FileList) bool { + if fl.Name != other.Name { + return false + } + if !slices.Equal(fl.Additions, other.Additions) { + return false + } + if !slices.Equal(fl.Deletions, other.Deletions) { + return false + } + if len(fl.Changes) != len(other.Changes) { + return false + } + for idx, ch := range fl.Changes { + if !ch.Equal(&other.Changes[idx]) { + return false + } + } + return true +} + +func TestFormat(t *testing.T) { + testCases := []struct { + Name string + Template string + Input FileList + Expected string + Err error + }{ + { + Name: "no contents", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Additions: []string{"add1", "add2"}, + Deletions: []string{"del1", "del2"}, + Changes: []FileList{ + FileList{Name: "mod1"}, + FileList{Name: "mod2"}, + }, + }, + Expected: "-del1 -del2 +add1 +add2 +mod1 +mod2 ", + Err: nil, + }, + { + Name: "adds", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Additions: []string{"add1", "add2"}, + }, + Expected: "+add1 +add2 ", + Err: nil, + }, + { + Name: "deletes", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Deletions: []string{"del1", "del2"}, + }, + Expected: "-del1 -del2 ", + Err: nil, + }, + { + Name: "changes", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Changes: []FileList{ + FileList{Name: "mod1"}, + FileList{Name: "mod2"}, + }, + }, + Expected: "+mod1 +mod2 ", + Err: nil, + }, + { + Name: "with contents", + Template: DefaultTemplate, + Input: FileList{ + Name: "target", + Additions: []string{"add1", "add2"}, + Deletions: []string{"del1", "del2"}, + Changes: []FileList{ + FileList{ + Name: "mod1", + }, + FileList{ + Name: "mod2", + Additions: []string{"a1"}, + Deletions: []string{"d1"}, + }, + }, + }, + Expected: "-del1 -del2 +add1 +add2 +mod1 +mod2 --file mod2 -d1 +a1 --endfile ", + Err: nil, + }, + } + for _, tc := range testCases { + buf := bytes.NewBuffer([]byte{}) + err := tc.Input.Format(buf, tc.Template) + android.AssertSame(t, tc.Name, tc.Err, err) + android.AssertSame(t, tc.Name, tc.Expected, buf.String()) + } +} diff --git a/cmd/find_input_delta/find_input_delta_lib/fs.go b/cmd/find_input_delta/find_input_delta_lib/fs.go new file mode 100644 index 000000000..4a83ed7ff --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/fs.go @@ -0,0 +1,46 @@ +// Copyright 2024 Google Inc. 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. + +package find_input_delta_lib + +import ( + "io" + "io/fs" + "os" +) + +// OsFs provides a minimal implementation so that we can use testing/fstest for +// unit tests. +var OsFs fileSystem = osFS{} + +type fileSystem interface { + Open(path string) (fs.File, error) + Stat(path string) (os.FileInfo, error) + ReadFile(path string) ([]byte, error) +} + +type file interface { + io.Closer + io.Reader + io.ReaderAt + io.Seeker + Stat() (os.FileInfo, error) +} + +// osFS implements fileSystem using the local disk. +type osFS struct{} + +func (osFS) Open(path string) (fs.File, error) { return os.Open(path) } +func (osFS) Stat(path string) (os.FileInfo, error) { return os.Stat(path) } +func (osFS) ReadFile(path string) ([]byte, error) { return os.ReadFile(path) } diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state.go b/cmd/find_input_delta/find_input_delta_lib/internal_state.go new file mode 100644 index 000000000..b2ff8c704 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/internal_state.go @@ -0,0 +1,122 @@ +// Copyright 2024 Google Inc. 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. + +package find_input_delta_lib + +import ( + "errors" + "fmt" + "io/fs" + "slices" + + fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto_internal" + "github.com/google/blueprint/pathtools" + "google.golang.org/protobuf/proto" +) + +// Load the internal state from a file. +// If the file does not exist, an empty state is returned. +func LoadState(filename string, fsys fs.ReadFileFS) (*fid_proto.PartialCompileInputs, error) { + var message = &fid_proto.PartialCompileInputs{} + data, err := fsys.ReadFile(filename) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + return message, err + } + proto.Unmarshal(data, message) + return message, nil +} + +type StatReadFileFS interface { + fs.StatFS + fs.ReadFileFS +} + +// Create the internal state by examining the inputs. +func CreateState(inputs []string, inspect_contents bool, fsys StatReadFileFS) (*fid_proto.PartialCompileInputs, error) { + ret := &fid_proto.PartialCompileInputs{} + slices.Sort(inputs) + for _, input := range inputs { + stat, err := fs.Stat(fsys, input) + if err != nil { + return ret, err + } + pci := &fid_proto.PartialCompileInput{ + Name: proto.String(input), + MtimeNsec: proto.Int64(stat.ModTime().UnixNano()), + // If we ever have an easy hash, assign it here. + } + if inspect_contents { + contents, err := InspectFileContents(input) + if err != nil { + return ret, err + } + if contents != nil { + pci.Contents = contents + } + } + ret.InputFiles = append(ret.InputFiles, pci) + } + return ret, nil +} + +// Inspect the file and extract the state of the elements in the archive. +// If this is not an archive of some sort, nil is returned. +func InspectFileContents(name string) ([]*fid_proto.PartialCompileInput, error) { + // TODO: Actually inspect the contents. + fmt.Printf("inspecting contents for %s\n", name) + return nil, nil +} + +func WriteState(s *fid_proto.PartialCompileInputs, path string) error { + data, err := proto.Marshal(s) + if err != nil { + return err + } + return pathtools.WriteFileIfChanged(path, data, 0644) +} + +func CompareInternalState(prior, other *fid_proto.PartialCompileInputs, target string) *FileList { + return CompareInputFiles(prior.GetInputFiles(), other.GetInputFiles(), target) +} + +func CompareInputFiles(prior, other []*fid_proto.PartialCompileInput, name string) *FileList { + fl := &FileList{ + Name: name, + } + PriorMap := make(map[string]*fid_proto.PartialCompileInput, len(prior)) + // We know that the lists are properly sorted, so we can simply compare them. + for _, v := range prior { + PriorMap[v.GetName()] = v + } + otherMap := make(map[string]*fid_proto.PartialCompileInput, len(other)) + for _, v := range other { + name = v.GetName() + otherMap[name] = v + if _, ok := PriorMap[name]; !ok { + // Added file + fl.Additions = append(fl.Additions, name) + } else if !proto.Equal(PriorMap[name], v) { + // Changed file + fl.Changes = append(fl.Changes, *CompareInputFiles(PriorMap[name].GetContents(), v.GetContents(), name)) + } + } + for _, v := range prior { + name := v.GetName() + if _, ok := otherMap[name]; !ok { + // Deleted file + fl.Deletions = append(fl.Deletions, name) + } + } + return fl +} diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go new file mode 100644 index 000000000..20b8efaa8 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_lib/internal_state_test.go @@ -0,0 +1,232 @@ +// Copyright 2024 Google Inc. 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. + +package find_input_delta_lib + +import ( + "errors" + "io/fs" + "testing" + "testing/fstest" + "time" + + // For Assert*. + "android/soong/android" + + fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto_internal" + "google.golang.org/protobuf/proto" +) + +// Various state files + +func marshalProto(t *testing.T, message proto.Message) []byte { + data, err := proto.Marshal(message) + if err != nil { + t.Errorf("%v", err) + } + return data +} + +func protoFile(name string, mtime_nsec int64, hash string, contents []*fid_proto.PartialCompileInput) (pci *fid_proto.PartialCompileInput) { + pci = &fid_proto.PartialCompileInput{ + Name: proto.String(name), + } + if mtime_nsec != 0 { + pci.MtimeNsec = proto.Int64(mtime_nsec) + } + if len(hash) > 0 { + pci.Hash = proto.String(hash) + } + if contents != nil { + pci.Contents = contents + } + return +} + +func TestLoadState(t *testing.T) { + testCases := []struct { + Name string + Filename string + Mapfs fs.ReadFileFS + Expected *fid_proto.PartialCompileInputs + Err error + }{ + { + Name: "missing file", + Filename: "missing", + Mapfs: fstest.MapFS{}, + Expected: &fid_proto.PartialCompileInputs{}, + Err: nil, + }, + { + Name: "bad file", + Filename: ".", + Mapfs: OsFs, + Expected: &fid_proto.PartialCompileInputs{}, + Err: errors.New("read failed"), + }, + { + Name: "file with mtime", + Filename: "state.old", + Mapfs: fstest.MapFS{ + "state.old": &fstest.MapFile{ + Data: marshalProto(t, &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "", nil), + }, + }), + }, + }, + Expected: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "", nil), + }, + }, + Err: nil, + }, + { + Name: "file with mtime and hash", + Filename: "state.old", + Mapfs: fstest.MapFS{ + "state.old": &fstest.MapFile{ + Data: marshalProto(t, &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "crc:crc_value", nil), + }, + }), + }, + }, + Expected: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("input1", 100, "crc:crc_value", nil), + }, + }, + Err: nil, + }, + } + for _, tc := range testCases { + actual, err := LoadState(tc.Filename, tc.Mapfs) + if tc.Err == nil { + android.AssertSame(t, tc.Name, tc.Err, err) + } else if err == nil { + t.Errorf("%s: expected error, did not get one", tc.Name) + } + if !proto.Equal(tc.Expected, actual) { + t.Errorf("%s: expected %v, actual %v", tc.Name, tc.Expected, actual) + } + } +} + +func TestCreateState(t *testing.T) { + testCases := []struct { + Name string + Inputs []string + Inspect bool + Mapfs StatReadFileFS + Expected *fid_proto.PartialCompileInputs + Err error + }{ + { + Name: "no inputs", + Inputs: []string{}, + Mapfs: fstest.MapFS{}, + Expected: &fid_proto.PartialCompileInputs{}, + Err: nil, + }, + { + Name: "files found", + Inputs: []string{"baz", "foo", "bar"}, + Mapfs: fstest.MapFS{ + "foo": &fstest.MapFile{ModTime: time.Unix(0, 100).UTC()}, + "baz": &fstest.MapFile{ModTime: time.Unix(0, 300).UTC()}, + "bar": &fstest.MapFile{ModTime: time.Unix(0, 200).UTC()}, + }, + Expected: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + // Files are always sorted. + protoFile("bar", 200, "", nil), + protoFile("baz", 300, "", nil), + protoFile("foo", 100, "", nil), + }, + }, + Err: nil, + }, + } + for _, tc := range testCases { + actual, err := CreateState(tc.Inputs, tc.Inspect, tc.Mapfs) + if tc.Err == nil { + android.AssertSame(t, tc.Name, tc.Err, err) + } else if err == nil { + t.Errorf("%s: expected error, did not get one", tc.Name) + } + if !proto.Equal(tc.Expected, actual) { + t.Errorf("%s: expected %v, actual %v", tc.Name, tc.Expected, actual) + } + } +} + +func TestCompareInternalState(t *testing.T) { + testCases := []struct { + Name string + Target string + Prior *fid_proto.PartialCompileInputs + New *fid_proto.PartialCompileInputs + Expected *FileList + }{ + { + Name: "prior is empty", + Target: "foo", + Prior: &fid_proto.PartialCompileInputs{}, + New: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("file1", 100, "", nil), + }, + }, + Expected: &FileList{ + Name: "foo", + Additions: []string{"file1"}, + }, + }, + { + Name: "one of each", + Target: "foo", + Prior: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("file0", 100, "", nil), + protoFile("file1", 100, "", nil), + protoFile("file2", 200, "", nil), + }, + }, + New: &fid_proto.PartialCompileInputs{ + InputFiles: []*fid_proto.PartialCompileInput{ + protoFile("file0", 100, "", nil), + protoFile("file1", 200, "", nil), + protoFile("file3", 300, "", nil), + }, + }, + Expected: &FileList{ + Name: "foo", + Additions: []string{"file3"}, + Changes: []FileList{FileList{Name: "file1"}}, + Deletions: []string{"file2"}, + }, + }, + } + for _, tc := range testCases { + actual := CompareInternalState(tc.Prior, tc.New, tc.Target) + if !tc.Expected.Equal(actual) { + t.Errorf("%s: expected %q, actual %q", tc.Name, tc.Expected, actual) + } + } +} diff --git a/cmd/find_input_delta/find_input_delta_proto/Android.bp b/cmd/find_input_delta/find_input_delta_proto/Android.bp new file mode 100644 index 000000000..18eba6bb8 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2024 Google Inc. 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. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-proto", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "target_delta_files.pb.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go new file mode 100644 index 000000000..648ef224a --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go @@ -0,0 +1,198 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: file_list.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FileList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the file. + // In the outermost message, this is the name of the Ninja target. + // When used in `changes`, this is the name of the changed file. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The added files. + Additions []string `protobuf:"bytes,2,rep,name=additions" json:"additions,omitempty"` + // The deleted files. + Deletions []string `protobuf:"bytes,3,rep,name=deletions" json:"deletions,omitempty"` + // The changed files. + Changes []*FileList `protobuf:"bytes,4,rep,name=changes" json:"changes,omitempty"` +} + +func (x *FileList) Reset() { + *x = FileList{} + if protoimpl.UnsafeEnabled { + mi := &file_file_list_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FileList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileList) ProtoMessage() {} + +func (x *FileList) ProtoReflect() protoreflect.Message { + mi := &file_file_list_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileList.ProtoReflect.Descriptor instead. +func (*FileList) Descriptor() ([]byte, []int) { + return file_file_list_proto_rawDescGZIP(), []int{0} +} + +func (x *FileList) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *FileList) GetAdditions() []string { + if x != nil { + return x.Additions + } + return nil +} + +func (x *FileList) GetDeletions() []string { + if x != nil { + return x.Deletions + } + return nil +} + +func (x *FileList) GetChanges() []*FileList { + if x != nil { + return x.Changes + } + return nil +} + +var File_file_list_proto protoreflect.FileDescriptor + +var file_file_list_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x9e, 0x01, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, + 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, + 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x42, 0x26, 0x5a, 0x24, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, + 0x6f, 0x6e, 0x67, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, + 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_file_list_proto_rawDescOnce sync.Once + file_file_list_proto_rawDescData = file_file_list_proto_rawDesc +) + +func file_file_list_proto_rawDescGZIP() []byte { + file_file_list_proto_rawDescOnce.Do(func() { + file_file_list_proto_rawDescData = protoimpl.X.CompressGZIP(file_file_list_proto_rawDescData) + }) + return file_file_list_proto_rawDescData +} + +var file_file_list_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_file_list_proto_goTypes = []interface{}{ + (*FileList)(nil), // 0: android.find_input_delta_proto.FileList +} +var file_file_list_proto_depIdxs = []int32{ + 0, // 0: android.find_input_delta_proto.FileList.changes:type_name -> android.find_input_delta_proto.FileList + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_file_list_proto_init() } +func file_file_list_proto_init() { + if File_file_list_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_file_list_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FileList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_file_list_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_file_list_proto_goTypes, + DependencyIndexes: file_file_list_proto_depIdxs, + MessageInfos: file_file_list_proto_msgTypes, + }.Build() + File_file_list_proto = out.File + file_file_list_proto_rawDesc = nil + file_file_list_proto_goTypes = nil + file_file_list_proto_depIdxs = nil +} diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.proto b/cmd/find_input_delta/find_input_delta_proto/file_list.proto new file mode 100644 index 000000000..d7faca9c8 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/file_list.proto @@ -0,0 +1,34 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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. + +syntax = "proto2"; +package android.find_input_delta_proto; +option go_package = "android/soong/find_input_delta/proto"; + +message FileList { + // The name of the file. + // In the outermost message, this is the name of the Ninja target. + // When used in `changes`, this is the name of the changed file. + optional string name = 1; + + // The added files. + repeated string additions = 2; + + // The deleted files. + repeated string deletions = 3; + + // The changed files. + repeated FileList changes = 4; +} diff --git a/cmd/find_input_delta/find_input_delta_proto/regen.sh b/cmd/find_input_delta/find_input_delta_proto/regen.sh new file mode 100644 index 000000000..d77365941 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. file_list.proto diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/Android.bp b/cmd/find_input_delta/find_input_delta_proto_internal/Android.bp new file mode 100644 index 000000000..00ba9ff03 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2024 Google Inc. 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. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-cmd-find_input_delta-proto_internal", + pkgPath: "android/soong/cmd/find_input_delta/find_input_delta_proto_internal", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "internal_state.pb.go", + ], +} diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go new file mode 100644 index 000000000..2229a324d --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.pb.go @@ -0,0 +1,268 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: internal_state.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The state of all inputs. +type PartialCompileInputs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The status of each file. + InputFiles []*PartialCompileInput `protobuf:"bytes,1,rep,name=input_files,json=inputFiles" json:"input_files,omitempty"` +} + +func (x *PartialCompileInputs) Reset() { + *x = PartialCompileInputs{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_state_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PartialCompileInputs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartialCompileInputs) ProtoMessage() {} + +func (x *PartialCompileInputs) ProtoReflect() protoreflect.Message { + mi := &file_internal_state_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartialCompileInputs.ProtoReflect.Descriptor instead. +func (*PartialCompileInputs) Descriptor() ([]byte, []int) { + return file_internal_state_proto_rawDescGZIP(), []int{0} +} + +func (x *PartialCompileInputs) GetInputFiles() []*PartialCompileInput { + if x != nil { + return x.InputFiles + } + return nil +} + +// The state of one input. +type PartialCompileInput struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the file. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // The timestamp of the file in (Unix) nanoseconds. + MtimeNsec *int64 `protobuf:"varint,2,opt,name=mtime_nsec,json=mtimeNsec" json:"mtime_nsec,omitempty"` + // The hash of the file, in the form ‘{HASHNAME}:{VALUE}’ + Hash *string `protobuf:"bytes,3,opt,name=hash" json:"hash,omitempty"` + // Contents of the file, if the file was inspected (such as jar files, etc). + Contents []*PartialCompileInput `protobuf:"bytes,4,rep,name=contents" json:"contents,omitempty"` +} + +func (x *PartialCompileInput) Reset() { + *x = PartialCompileInput{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_state_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PartialCompileInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PartialCompileInput) ProtoMessage() {} + +func (x *PartialCompileInput) ProtoReflect() protoreflect.Message { + mi := &file_internal_state_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PartialCompileInput.ProtoReflect.Descriptor instead. +func (*PartialCompileInput) Descriptor() ([]byte, []int) { + return file_internal_state_proto_rawDescGZIP(), []int{1} +} + +func (x *PartialCompileInput) GetName() string { + if x != nil && x.Name != nil { + return *x.Name + } + return "" +} + +func (x *PartialCompileInput) GetMtimeNsec() int64 { + if x != nil && x.MtimeNsec != nil { + return *x.MtimeNsec + } + return 0 +} + +func (x *PartialCompileInput) GetHash() string { + if x != nil && x.Hash != nil { + return *x.Hash + } + return "" +} + +func (x *PartialCompileInput) GetContents() []*PartialCompileInput { + if x != nil { + return x.Contents + } + return nil +} + +var File_internal_state_proto protoreflect.FileDescriptor + +var file_internal_state_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, + 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, + 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6c, 0x0a, 0x14, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, + 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x54, + 0x0a, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, + 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, 0x6d, 0x70, + 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x13, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, + 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x73, 0x65, 0x63, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x4e, 0x73, 0x65, 0x63, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x12, 0x4f, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, + 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, + 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x43, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x42, 0x26, 0x5a, 0x24, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, + 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_internal_state_proto_rawDescOnce sync.Once + file_internal_state_proto_rawDescData = file_internal_state_proto_rawDesc +) + +func file_internal_state_proto_rawDescGZIP() []byte { + file_internal_state_proto_rawDescOnce.Do(func() { + file_internal_state_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_state_proto_rawDescData) + }) + return file_internal_state_proto_rawDescData +} + +var file_internal_state_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_internal_state_proto_goTypes = []interface{}{ + (*PartialCompileInputs)(nil), // 0: android.find_input_delta_proto.PartialCompileInputs + (*PartialCompileInput)(nil), // 1: android.find_input_delta_proto.PartialCompileInput +} +var file_internal_state_proto_depIdxs = []int32{ + 1, // 0: android.find_input_delta_proto.PartialCompileInputs.input_files:type_name -> android.find_input_delta_proto.PartialCompileInput + 1, // 1: android.find_input_delta_proto.PartialCompileInput.contents:type_name -> android.find_input_delta_proto.PartialCompileInput + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_internal_state_proto_init() } +func file_internal_state_proto_init() { + if File_internal_state_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_internal_state_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PartialCompileInputs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PartialCompileInput); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_internal_state_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_internal_state_proto_goTypes, + DependencyIndexes: file_internal_state_proto_depIdxs, + MessageInfos: file_internal_state_proto_msgTypes, + }.Build() + File_internal_state_proto = out.File + file_internal_state_proto_rawDesc = nil + file_internal_state_proto_goTypes = nil + file_internal_state_proto_depIdxs = nil +} diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto new file mode 100644 index 000000000..113fc6434 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/internal_state.proto @@ -0,0 +1,39 @@ +// +// Copyright (C) 2024 The Android Open-Source Project +// +// 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. + +syntax = "proto2"; +package android.find_input_delta_proto; +option go_package = "android/soong/find_input_delta/proto"; + +// The state of all inputs. +message PartialCompileInputs { + // The status of each file. + repeated PartialCompileInput input_files = 1; +} + +// The state of one input. +message PartialCompileInput { + // The name of the file. + optional string name = 1; + + // The timestamp of the file in (Unix) nanoseconds. + optional int64 mtime_nsec = 2; + + // The hash of the file, in the form ‘{HASHNAME}:{VALUE}’ + optional string hash = 3; + + // Contents of the file, if the file was inspected (such as jar files, etc). + repeated PartialCompileInput contents = 4; +} diff --git a/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh b/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh new file mode 100644 index 000000000..cbaf7d056 --- /dev/null +++ b/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. internal_state.proto diff --git a/compliance/notice.go b/compliance/notice.go index 4fc83ab70..edd1b3435 100644 --- a/compliance/notice.go +++ b/compliance/notice.go @@ -18,6 +18,7 @@ import ( "path/filepath" "android/soong/android" + "github.com/google/blueprint" ) @@ -62,8 +63,7 @@ type NoticeXmlModule struct { props noticeXmlProperties - outputFile android.OutputPath - installPath android.InstallPath + outputFile android.OutputPath } type noticeXmlProperties struct { @@ -86,10 +86,8 @@ func (nx *NoticeXmlModule) GenerateAndroidBuildActions(ctx android.ModuleContext nx.outputFile = output.OutputPath - if android.Bool(ctx.Config().ProductVariables().UseSoongSystemImage) { - nx.installPath = android.PathForModuleInPartitionInstall(ctx, nx.props.Partition_name, "etc") - ctx.InstallFile(nx.installPath, "NOTICE.xml.gz", nx.outputFile) - } + installPath := android.PathForModuleInPartitionInstall(ctx, nx.props.Partition_name, "etc") + ctx.PackageFile(installPath, "NOTICE.xml.gz", nx.outputFile) } func (nx *NoticeXmlModule) AndroidMkEntries() []android.AndroidMkEntries { diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp index da865404b..8c808e4b9 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -132,10 +132,10 @@ java_library { // prebuilts/sdk/update_prebuilts.py script to update the prebuilts/sdk // directory. java_library { - name: "core-current-stubs-for-system-modules", + name: "core-current-stubs-for-system-modules-exportable", visibility: ["//development/sdk"], static_libs: [ - "core.current.stubs", + "core.current.stubs.exportable", // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", @@ -155,6 +155,19 @@ java_library { ], } +java_library { + name: "core-current-stubs-for-system-modules", + visibility: ["//development/sdk"], + static_libs: [ + "core.current.stubs", + // This one is not on device but it's needed when javac compiles code + // containing lambdas. + "core-lambda-stubs-for-system-modules", + ], + sdk_version: "none", + system_modules: "none", +} + // Defaults module to strip out android annotations java_defaults { name: "system-modules-no-annotations", diff --git a/java/sdk.go b/java/sdk.go index 036521c86..bb2aa8d7e 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -65,8 +65,6 @@ func defaultJavaLanguageVersion(ctx android.EarlyModuleContext, s android.SdkSpe return JAVA_VERSION_9 } else if sdk.FinalOrFutureInt() <= 33 { return JAVA_VERSION_11 - } else if sdk.FinalOrFutureInt() <= 35 { - return JAVA_VERSION_17 } else if ctx.Config().TargetsJava21() { // Build flag that controls whether Java 21 is used as the // default target version, or Java 17. |