Merge "Change exportedDirs and exportedSystemDirs from []string to android.Paths"
diff --git a/Android.bp b/Android.bp
index 9962b62..714ce37 100644
--- a/Android.bp
+++ b/Android.bp
@@ -341,6 +341,7 @@
"rust/config/global.go",
"rust/config/toolchain.go",
"rust/config/whitelist.go",
+ "rust/config/x86_darwin_host.go",
"rust/config/x86_linux_host.go",
"rust/config/x86_64_device.go",
],
@@ -579,104 +580,21 @@
arch: {
arm: {
src: "prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a",
- strip: {
- keep_symbols_list: [
- // unwind-arm.o
- "_Unwind_Complete",
- "_Unwind_DeleteException",
- "_Unwind_GetCFA",
- "_Unwind_VRS_Get",
- "_Unwind_VRS_Pop",
- "_Unwind_VRS_Set",
- "__aeabi_unwind_cpp_pr0",
- "__aeabi_unwind_cpp_pr1",
- "__aeabi_unwind_cpp_pr2",
- "__gnu_Unwind_Backtrace",
- "__gnu_Unwind_ForcedUnwind",
- "__gnu_Unwind_RaiseException",
- "__gnu_Unwind_Resume",
- "__gnu_Unwind_Resume_or_Rethrow",
-
- // libunwind.o
- "_Unwind_Backtrace",
- "_Unwind_ForcedUnwind",
- "_Unwind_RaiseException",
- "_Unwind_Resume",
- "_Unwind_Resume_or_Rethrow",
- "___Unwind_Backtrace",
- "___Unwind_ForcedUnwind",
- "___Unwind_RaiseException",
- "___Unwind_Resume",
- "___Unwind_Resume_or_Rethrow",
- "__gnu_Unwind_Restore_VFP",
- "__gnu_Unwind_Restore_VFP_D",
- "__gnu_Unwind_Restore_VFP_D_16_to_31",
- "__gnu_Unwind_Restore_WMMXC",
- "__gnu_Unwind_Restore_WMMXD",
- "__gnu_Unwind_Save_VFP",
- "__gnu_Unwind_Save_VFP_D",
- "__gnu_Unwind_Save_VFP_D_16_to_31",
- "__gnu_Unwind_Save_WMMXC",
- "__gnu_Unwind_Save_WMMXD",
- "__restore_core_regs",
- "restore_core_regs",
-
- // pr-support.o
- "_Unwind_GetDataRelBase",
- "_Unwind_GetLanguageSpecificData",
- "_Unwind_GetRegionStart",
- "_Unwind_GetTextRelBase",
- "__gnu_unwind_execute",
- "__gnu_unwind_frame",
- ],
- },
+ repack_objects_to_keep: ["unwind-arm.o", "libunwind.o", "pr-support.o"],
},
arm64: {
src: "prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a",
+ repack_objects_to_keep: ["unwind-dw2.o", "unwind-dw2-fde-dip.o"],
},
x86: {
src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/32/libgcc.a",
-
+ repack_objects_to_keep: ["unwind-dw2.o", "unwind-dw2-fde-dip.o"],
},
x86_64: {
src: "prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/lib/gcc/x86_64-linux-android/4.9.x/libgcc.a",
+ repack_objects_to_keep: ["unwind-dw2.o", "unwind-dw2-fde-dip.o"],
},
},
- strip: {
- keep_symbols_list: [
- // unwind-dw2.o
- "_Unwind_Backtrace",
- "_Unwind_DeleteException",
- "_Unwind_FindEnclosingFunction",
- "_Unwind_ForcedUnwind",
- "_Unwind_GetCFA",
- "_Unwind_GetDataRelBase",
- "_Unwind_GetGR",
- "_Unwind_GetIP",
- "_Unwind_GetIPInfo",
- "_Unwind_GetLanguageSpecificData",
- "_Unwind_GetRegionStart",
- "_Unwind_GetTextRelBase",
- "_Unwind_RaiseException",
- "_Unwind_Resume",
- "_Unwind_Resume_or_Rethrow",
- "_Unwind_SetGR",
- "_Unwind_SetIP",
- "__frame_state_for",
-
- // unwind-dw2-fde-dip.o
- "_Unwind_Find_FDE",
- "__deregister_frame",
- "__deregister_frame_info",
- "__deregister_frame_info_bases",
- "__register_frame",
- "__register_frame_info",
- "__register_frame_info_bases",
- "__register_frame_info_table",
- "__register_frame_info_table_bases",
- "__register_frame_table",
- ],
- },
}
toolchain_library {
diff --git a/OWNERS b/OWNERS
index 797229f..4ae045d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,4 +4,3 @@
per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
per-file tidy.go = srhines@google.com, chh@google.com
per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
-per-file rust/config/whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 8559df9..0ee1201 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -195,6 +195,10 @@
return source == nil || !source.Enabled()
}
+func (p *Prebuilt) SourceExists() bool {
+ return p.properties.SourceExists
+}
+
func (p *Prebuilt) checkSingleSourceProperties() {
if !p.srcProps.IsValid() || p.srcField.Name == "" {
panic(fmt.Errorf("invalid single source prebuilt %+v", p))
@@ -215,7 +219,3 @@
}
return value.String()
}
-
-func (p *Prebuilt) SourceExists() bool {
- return p.properties.SourceExists
-}
diff --git a/androidmk/Android.bp b/androidmk/Android.bp
index 79fe530..4110073 100644
--- a/androidmk/Android.bp
+++ b/androidmk/Android.bp
@@ -19,12 +19,23 @@
blueprint_go_binary {
name: "androidmk",
srcs: [
- "cmd/androidmk/android.go",
- "cmd/androidmk/androidmk.go",
- "cmd/androidmk/values.go",
+ "cmd/androidmk.go",
+ ],
+ deps: [
+ "androidmk-lib",
+ ],
+}
+
+bootstrap_go_package {
+ name: "androidmk-lib",
+ pkgPath: "android/soong/androidmk/androidmk",
+ srcs: [
+ "androidmk/android.go",
+ "androidmk/androidmk.go",
+ "androidmk/values.go",
],
testSrcs: [
- "cmd/androidmk/androidmk_test.go",
+ "androidmk/androidmk_test.go",
],
deps: [
"androidmk-parser",
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/androidmk/android.go
similarity index 99%
rename from androidmk/cmd/androidmk/android.go
rename to androidmk/androidmk/android.go
index fcadd03..be52879 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package androidmk
import (
"android/soong/android"
diff --git a/androidmk/cmd/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
similarity index 93%
rename from androidmk/cmd/androidmk/androidmk.go
rename to androidmk/androidmk/androidmk.go
index d2a84d1..9d0c3ac 100644
--- a/androidmk/cmd/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -12,14 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package androidmk
import (
"bytes"
- "flag"
"fmt"
- "io/ioutil"
- "os"
"strings"
"text/scanner"
@@ -30,13 +27,6 @@
bpparser "github.com/google/blueprint/parser"
)
-var usage = func() {
- fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
- "\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
- flag.PrintDefaults()
- os.Exit(1)
-}
-
// TODO: non-expanded variables with expressions
type bpFile struct {
@@ -118,31 +108,7 @@
eq bool
}
-func main() {
- flag.Usage = usage
- flag.Parse()
- if len(flag.Args()) != 1 {
- usage()
- }
- filePathToRead := flag.Arg(0)
- b, err := ioutil.ReadFile(filePathToRead)
- if err != nil {
- fmt.Println(err.Error())
- return
- }
-
- output, errs := convertFile(os.Args[1], bytes.NewBuffer(b))
- if len(errs) > 0 {
- for _, err := range errs {
- fmt.Fprintln(os.Stderr, "ERROR: ", err)
- }
- os.Exit(1)
- }
-
- fmt.Print(output)
-}
-
-func convertFile(filename string, buffer *bytes.Buffer) (string, []error) {
+func ConvertFile(filename string, buffer *bytes.Buffer) (string, []error) {
p := mkparser.NewParser(filename, buffer)
nodes, errs := p.Parse()
diff --git a/androidmk/cmd/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
similarity index 99%
rename from androidmk/cmd/androidmk/androidmk_test.go
rename to androidmk/androidmk/androidmk_test.go
index dbb7fde..7e1a72c 100644
--- a/androidmk/cmd/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package androidmk
import (
"bytes"
@@ -1350,7 +1350,7 @@
t.Error(err)
}
- got, errs := convertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
+ got, errs := ConvertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
if len(errs) > 0 {
t.Errorf("Unexpected errors: %q", errs)
continue
diff --git a/androidmk/cmd/androidmk/values.go b/androidmk/androidmk/values.go
similarity index 99%
rename from androidmk/cmd/androidmk/values.go
rename to androidmk/androidmk/values.go
index 90f2e74..6b18a65 100644
--- a/androidmk/cmd/androidmk/values.go
+++ b/androidmk/androidmk/values.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package androidmk
import (
"fmt"
diff --git a/androidmk/cmd/androidmk.go b/androidmk/cmd/androidmk.go
new file mode 100644
index 0000000..00488eb
--- /dev/null
+++ b/androidmk/cmd/androidmk.go
@@ -0,0 +1,56 @@
+// Copyright 2017 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 (
+ "bytes"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "android/soong/androidmk/androidmk"
+)
+
+var usage = func() {
+ fmt.Fprintf(os.Stderr, "usage: androidmk [flags] <inputFile>\n"+
+ "\nandroidmk parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n")
+ flag.PrintDefaults()
+ os.Exit(1)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if len(flag.Args()) != 1 {
+ usage()
+ }
+ filePathToRead := flag.Arg(0)
+ b, err := ioutil.ReadFile(filePathToRead)
+ if err != nil {
+ fmt.Println(err.Error())
+ return
+ }
+
+ output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+ if len(errs) > 0 {
+ for _, err := range errs {
+ fmt.Fprintln(os.Stderr, "ERROR: ", err)
+ }
+ os.Exit(1)
+ }
+
+ fmt.Print(output)
+}
diff --git a/androidmk/partner_androidmk/Android.bp b/androidmk/partner_androidmk/Android.bp
new file mode 100644
index 0000000..532116a
--- /dev/null
+++ b/androidmk/partner_androidmk/Android.bp
@@ -0,0 +1,49 @@
+// Copyright 2015 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.
+
+//
+// Sample project for creating an extended androidmk
+//
+
+blueprint_go_binary {
+ name: "partner_androidmk",
+ srcs: [
+ "partner_androidmk/androidmk.go",
+ ],
+ testSrcs: [
+ "partner_androidmk/androidmk_test.go",
+ ],
+ deps: [
+ "androidmk-lib",
+ "partner_bpfix_extensions",
+ ],
+}
+
+blueprint_go_binary {
+ name: "partner_bpfix",
+ srcs: [
+ "partner_bpfix/bpfix.go",
+ ],
+ deps: [
+ "bpfix-cmd",
+ "partner_bpfix_extensions",
+ ],
+}
+
+bootstrap_go_package {
+ name: "partner_bpfix_extensions",
+ pkgPath: "partner/android/bpfix/extensions",
+ srcs: ["fixes/headers.go"],
+ deps: ["bpfix-lib"],
+}
diff --git a/androidmk/partner_androidmk/fixes/headers.go b/androidmk/partner_androidmk/fixes/headers.go
new file mode 100644
index 0000000..169dab6
--- /dev/null
+++ b/androidmk/partner_androidmk/fixes/headers.go
@@ -0,0 +1,120 @@
+package extensions
+
+import (
+ "strings"
+
+ "github.com/google/blueprint/parser"
+
+ "android/soong/bpfix/bpfix"
+)
+
+var fixSteps = bpfix.FixStepsExtension{
+ Name: "partner-include-dirs",
+ Steps: []bpfix.FixStep{
+ {
+ Name: "fixIncludeDirs",
+ Fix: fixIncludeDirs,
+ },
+ },
+}
+
+func init() {
+ bpfix.RegisterFixStepExtension(&fixSteps)
+}
+
+type includeDirFix struct {
+ libName string
+ libType string
+ variable string
+ subdir string
+}
+
+var commonIncludeDirs = []includeDirFix{
+ {
+ libName: "my_header_lib",
+ libType: "header_libs",
+ variable: "TARGET_OUT_HEADERS",
+ subdir: "/my_headers",
+ },
+}
+
+func findHeaderLib(e parser.Expression) (*includeDirFix, bool) {
+ if op, ok := e.(*parser.Operator); ok {
+ if op.Operator != '+' {
+ return nil, false
+ }
+ arg0, ok := op.Args[0].(*parser.Variable)
+ arg1, ok1 := op.Args[1].(*parser.String)
+ if !ok || !ok1 {
+ return nil, false
+ }
+ for _, lib := range commonIncludeDirs {
+ if arg0.Name == lib.variable && arg1.Value == lib.subdir {
+ return &lib, true
+ }
+ }
+ }
+ return nil, false
+}
+func searchThroughOperatorList(mod *parser.Module, e parser.Expression) {
+ if list, ok := e.(*parser.List); ok {
+ newList := make([]parser.Expression, 0, len(list.Values))
+ for _, item := range list.Values {
+ if lib, found := findHeaderLib(item); found {
+ if lib.libName != "" {
+ addLibrary(mod, lib.libType, lib.libName)
+ }
+ } else {
+ newList = append(newList, item)
+ }
+ }
+ list.Values = newList
+ }
+ if op, ok := e.(*parser.Operator); ok {
+ searchThroughOperatorList(mod, op.Args[0])
+ searchThroughOperatorList(mod, op.Args[1])
+ }
+}
+func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) {
+ prop, ok := mod.GetProperty(name)
+ if !ok {
+ return nil, false
+ }
+ list, ok = prop.Value.(*parser.List)
+ return list, ok
+}
+func addLibrary(mod *parser.Module, libType string, libName string) {
+ var list, ok = getLiteralListProperty(mod, libType)
+ if !ok {
+ list = new(parser.List)
+ prop := new(parser.Property)
+ prop.Name = libType
+ prop.Value = list
+ mod.Properties = append(mod.Properties, prop)
+ } else {
+ for _, v := range list.Values {
+ if stringValue, ok := v.(*parser.String); ok && stringValue.Value == libName {
+ return
+ }
+ }
+ }
+ lib := new(parser.String)
+ lib.Value = libName
+ list.Values = append(list.Values, lib)
+}
+func fixIncludeDirs(f *bpfix.Fixer) error {
+ tree := f.Tree()
+ for _, def := range tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !ok {
+ continue
+ }
+ if !strings.HasPrefix(mod.Type, "cc_") {
+ continue
+ }
+ if prop, ok := mod.GetProperty("include_dirs"); ok {
+ searchThroughOperatorList(mod, prop.Value)
+ }
+ }
+ return nil
+}
diff --git a/androidmk/partner_androidmk/partner_androidmk/androidmk.go b/androidmk/partner_androidmk/partner_androidmk/androidmk.go
new file mode 100644
index 0000000..af8cdf3
--- /dev/null
+++ b/androidmk/partner_androidmk/partner_androidmk/androidmk.go
@@ -0,0 +1,58 @@
+// Copyright 2017 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 (
+ "bytes"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "android/soong/androidmk/androidmk"
+
+ _ "partner/android/bpfix/extensions"
+)
+
+var usage = func() {
+ fmt.Fprintf(os.Stderr, "usage: %s [flags] <inputFile>\n"+
+ "\n%s parses <inputFile> as an Android.mk file and attempts to output an analogous Android.bp file (to standard out)\n", os.Args[0], os.Args[0])
+ flag.PrintDefaults()
+ os.Exit(1)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if len(flag.Args()) != 1 {
+ usage()
+ }
+ filePathToRead := flag.Arg(0)
+ b, err := ioutil.ReadFile(filePathToRead)
+ if err != nil {
+ fmt.Println(err.Error())
+ return
+ }
+
+ output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+ if len(errs) > 0 {
+ for _, err := range errs {
+ fmt.Fprintln(os.Stderr, "ERROR: ", err)
+ }
+ os.Exit(1)
+ }
+
+ fmt.Print(output)
+}
diff --git a/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go b/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go
new file mode 100644
index 0000000..ff04e88
--- /dev/null
+++ b/androidmk/partner_androidmk/partner_androidmk/androidmk_test.go
@@ -0,0 +1,73 @@
+// Copyright 2016 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 (
+ "bytes"
+ "fmt"
+ "strings"
+ "testing"
+
+ "android/soong/androidmk/androidmk"
+ "android/soong/bpfix/bpfix"
+
+ _ "partner/android/bpfix/extensions"
+)
+
+var testCases = []struct {
+ desc string
+ in string
+ expected string
+}{
+ {
+ desc: "headers replacement",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := test
+LOCAL_SRC_FILES := a.c
+LOCAL_C_INCLUDES := test1 $(TARGET_OUT_HEADERS)/my_headers test2
+include $(BUILD_SHARED_LIBRARY)`,
+ expected: `
+cc_library_shared {
+ name: "test",
+ srcs: ["a.c"],
+ include_dirs: [
+ "test1",
+
+ "test2",
+ ],
+ header_libs: ["my_header_lib"]
+}`,
+ },
+}
+
+func TestEndToEnd(t *testing.T) {
+ for i, test := range testCases {
+ expected, err := bpfix.Reformat(test.expected)
+ if err != nil {
+ t.Error(err)
+ }
+
+ got, errs := androidmk.ConvertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in))
+ if len(errs) > 0 {
+ t.Errorf("Unexpected errors: %q", errs)
+ continue
+ }
+
+ if got != expected {
+ t.Errorf("failed testcase '%s'\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n", test.desc, strings.TrimSpace(test.in), expected, got)
+ }
+ }
+}
diff --git a/androidmk/partner_androidmk/partner_bpfix/bpfix.go b/androidmk/partner_androidmk/partner_bpfix/bpfix.go
new file mode 100644
index 0000000..2c8e0a8
--- /dev/null
+++ b/androidmk/partner_androidmk/partner_bpfix/bpfix.go
@@ -0,0 +1,27 @@
+// Copyright 2017 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.
+
+// This file provides a command-line interface to bpfix
+
+package main
+
+import (
+ "android/soong/bpfix/bpfix/cmd"
+
+ _ "partner/android/bpfix/extensions"
+)
+
+func main() {
+ cmd.Run()
+}
diff --git a/apex/apex.go b/apex/apex.go
index c9b989a..629cbbf 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -126,11 +126,15 @@
}, "image_content_file", "whitelisted_files_file", "apex_module_name")
)
-var imageApexSuffix = ".apex"
-var zipApexSuffix = ".zipapex"
+const (
+ imageApexSuffix = ".apex"
+ zipApexSuffix = ".zipapex"
-var imageApexType = "image"
-var zipApexType = "zip"
+ imageApexType = "image"
+ zipApexType = "zip"
+
+ vndkApexNamePrefix = "com.android.vndk.v"
+)
type dependencyTag struct {
blueprint.BaseDependencyTag
@@ -182,10 +186,7 @@
android.RegisterModuleType("apex_defaults", defaultsFactory)
android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator).Parallel()
- ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
- })
+ android.PreDepsMutators(RegisterPreDepsMutators)
android.PostDepsMutators(RegisterPostDepsMutators)
android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
@@ -195,6 +196,11 @@
})
}
+func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
+ ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+}
+
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_deps", apexDepsMutator)
ctx.BottomUp("apex", apexMutator).Parallel()
@@ -207,44 +213,39 @@
vndkApexListMutex sync.Mutex
)
-func vndkApexList(config android.Config) map[string]*apexBundle {
+func vndkApexList(config android.Config) map[string]string {
return config.Once(vndkApexListKey, func() interface{} {
- return map[string]*apexBundle{}
- }).(map[string]*apexBundle)
+ return map[string]string{}
+ }).(map[string]string)
}
-// apexVndkGatherMutator gathers "apex_vndk" modules and puts them in a map with vndk_version as a key.
-func apexVndkGatherMutator(mctx android.TopDownMutatorContext) {
+func apexVndkMutator(mctx android.TopDownMutatorContext) {
if ab, ok := mctx.Module().(*apexBundle); ok && ab.vndkApex {
if ab.IsNativeBridgeSupported() {
mctx.PropertyErrorf("native_bridge_supported", "%q doesn't support native bridge binary.", mctx.ModuleType())
}
- vndkVersion := proptools.String(ab.vndkProperties.Vndk_version)
+ vndkVersion := ab.vndkVersion(mctx.DeviceConfig())
+ // Ensure VNDK APEX mount point is formatted as com.android.vndk.v###
+ ab.properties.Apex_name = proptools.StringPtr(vndkApexNamePrefix + vndkVersion)
+ // vndk_version should be unique
vndkApexListMutex.Lock()
defer vndkApexListMutex.Unlock()
vndkApexList := vndkApexList(mctx.Config())
if other, ok := vndkApexList[vndkVersion]; ok {
- mctx.PropertyErrorf("vndk_version", "%v is already defined in %q", vndkVersion, other.BaseModuleName())
+ mctx.PropertyErrorf("vndk_version", "%v is already defined in %q", vndkVersion, other)
}
- vndkApexList[vndkVersion] = ab
+ vndkApexList[vndkVersion] = mctx.ModuleName()
}
}
-// apexVndkAddDepsMutator adds (reverse) dependencies from vndk libs to apex_vndk modules.
-// It filters only libs with matching targets.
-func apexVndkAddDepsMutator(mctx android.BottomUpMutatorContext) {
- if cc, ok := mctx.Module().(*cc.Module); ok && cc.IsVndkOnSystem() {
+func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
+ if m, ok := mctx.Module().(*cc.Module); ok && cc.IsForVndkApex(mctx, m) {
+ vndkVersion := m.VndkVersion()
vndkApexList := vndkApexList(mctx.Config())
- if ab, ok := vndkApexList[cc.VndkVersion()]; ok {
- targetArch := cc.Target().String()
- for _, target := range ab.MultiTargets() {
- if target.String() == targetArch {
- mctx.AddReverseDependency(mctx.Module(), sharedLibTag, ab.Name())
- break
- }
- }
+ if vndkApex, ok := vndkApexList[vndkVersion]; ok {
+ mctx.AddReverseDependency(mctx.Module(), sharedLibTag, vndkApex)
}
}
}
@@ -615,6 +616,12 @@
// intermediate path for apex_manifest.json
manifestOut android.WritablePath
+
+ // list of commands to create symlinks for backward compatibility
+ // these commands will be attached as LOCAL_POST_INSTALL_CMD to
+ // apex package itself(for unflattened build) or apex_manifest.json(for flattened build)
+ // so that compat symlinks are always installed regardless of TARGET_FLATTEN_APEX setting.
+ compatSymlinks []string
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
@@ -654,7 +661,6 @@
}
func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-
targets := ctx.MultiTargets()
config := ctx.DeviceConfig()
@@ -824,6 +830,9 @@
}
func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
+ if a.vndkApex {
+ return "vendor." + a.vndkVersion(config)
+ }
if config.VndkVersion() != "" && proptools.Bool(a.properties.Use_vendor) {
return "vendor." + config.PlatformVndkVersion()
} else {
@@ -1244,7 +1253,7 @@
// prepend the name of this APEX to the module names. These names will be the names of
// modules that will be defined if the APEX is flattened.
for i := range filesInfo {
- filesInfo[i].moduleName = ctx.ModuleName() + "." + filesInfo[i].moduleName
+ filesInfo[i].moduleName = filesInfo[i].moduleName + "." + ctx.ModuleName()
}
a.installDir = android.PathForModuleInstall(ctx, "apex")
@@ -1295,6 +1304,8 @@
a.buildUnflattenedApex(ctx, imageApex)
a.buildFlattenedApex(ctx)
}
+
+ a.compatSymlinks = makeCompatSymlinks(apexName, ctx)
}
func (a *apexBundle) buildNoticeFile(ctx android.ModuleContext, apexFileName string) android.OptionalPath {
@@ -1570,7 +1581,7 @@
if a.installable() {
// For flattened APEX, do nothing but make sure that apex_manifest.json and apex_pubkey are also copied along
// with other ordinary files.
- a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, ctx.ModuleName() + ".apex_manifest.json", ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{a.manifestOut, "apex_manifest.json." + ctx.ModuleName(), ".", etc, nil, nil})
// rename to apex_pubkey
copiedPubkey := android.PathForModuleOut(ctx, "apex_pubkey")
@@ -1579,7 +1590,7 @@
Input: a.public_key_file,
Output: copiedPubkey,
})
- a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, ctx.ModuleName() + ".apex_pubkey", ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, "apex_pubkey." + ctx.ModuleName(), ".", etc, nil, nil})
if ctx.Config().FlattenApex() {
apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
@@ -1712,6 +1723,10 @@
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
} else {
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
+ // For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
+ if !a.isFlattenedVariant() && fi.builtFile.Base() == "apex_manifest.json" && len(a.compatSymlinks) > 0 {
+ fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
+ }
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
}
}
@@ -1762,10 +1777,16 @@
if len(a.externalDeps) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.externalDeps, " "))
}
+ var postInstallCommands []string
if a.prebuiltFileToDelete != "" {
- fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", "rm -rf "+
+ postInstallCommands = append(postInstallCommands, "rm -rf "+
filepath.Join(a.installDir.ToMakePath().String(), a.prebuiltFileToDelete))
}
+ // For unflattened apexes, compat symlinks are attached to apex package itself as LOCAL_POST_INSTALL_CMD
+ postInstallCommands = append(postInstallCommands, a.compatSymlinks...)
+ if len(postInstallCommands) > 0 {
+ fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(postInstallCommands, " && "))
+ }
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
if apexType == imageApex {
@@ -1819,19 +1840,18 @@
}{
proptools.StringPtr("both"),
})
-
- vndkVersion := proptools.StringDefault(bundle.vndkProperties.Vndk_version, "current")
- if vndkVersion == "current" {
- vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
- bundle.vndkProperties.Vndk_version = proptools.StringPtr(vndkVersion)
- }
-
- // Ensure VNDK APEX mount point is formatted as com.android.vndk.v###
- bundle.properties.Apex_name = proptools.StringPtr("com.android.vndk.v" + vndkVersion)
})
return bundle
}
+func (a *apexBundle) vndkVersion(config android.DeviceConfig) string {
+ vndkVersion := proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
+ if vndkVersion == "current" {
+ vndkVersion = config.PlatformVndkVersion()
+ }
+ return vndkVersion
+}
+
//
// Defaults
//
@@ -1997,6 +2017,8 @@
if p.installable() {
ctx.InstallFile(p.installDir, p.installFilename, p.inputApex)
}
+
+ // TODO(b/143192278): Add compat symlinks for prebuilt_apex
}
func (p *Prebuilt) Prebuilt() *android.Prebuilt {
@@ -2031,3 +2053,30 @@
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
+
+func makeCompatSymlinks(apexName string, ctx android.ModuleContext) (symlinks []string) {
+ // small helper to add symlink commands
+ addSymlink := func(target, dir, linkName string) {
+ outDir := filepath.Join("$(PRODUCT_OUT)", dir)
+ link := filepath.Join(outDir, linkName)
+ symlinks = append(symlinks, "mkdir -p "+outDir+" && rm -rf "+link+" && ln -sf "+target+" "+link)
+ }
+
+ // TODO(b/142911355): [VNDK APEX] Fix hard-coded references to /system/lib/vndk
+ // When all hard-coded references are fixed, remove symbolic links
+ // Note that we should keep following symlinks for older VNDKs (<=29)
+ // Since prebuilt vndk libs still depend on system/lib/vndk path
+ if strings.HasPrefix(apexName, vndkApexNamePrefix) {
+ // the name of vndk apex is formatted "com.android.vndk.v" + version
+ vndkVersion := strings.TrimPrefix(apexName, vndkApexNamePrefix)
+ if ctx.Config().Android64() {
+ addSymlink("/apex/"+apexName+"/lib64", "/system/lib64", "vndk-sp-"+vndkVersion)
+ addSymlink("/apex/"+apexName+"/lib64", "/system/lib64", "vndk-"+vndkVersion)
+ }
+ if !ctx.Config().Android64() || ctx.DeviceConfig().DeviceSecondaryArch() != "" {
+ addSymlink("/apex/"+apexName+"/lib", "/system/lib", "vndk-sp-"+vndkVersion)
+ addSymlink("/apex/"+apexName+"/lib", "/system/lib", "vndk-"+vndkVersion)
+ }
+ }
+ return
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7a51bb6..cf38caa 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -18,6 +18,7 @@
"io/ioutil"
"os"
"reflect"
+ "sort"
"strings"
"testing"
@@ -85,6 +86,10 @@
}
}
+func withBinder32bit(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.Binder32bit = proptools.BoolPtr(true)
+}
+
func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
config := android.TestArchConfig(buildDir, nil)
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
@@ -132,13 +137,10 @@
ctx.BottomUp("test_per_src", cc.TestPerSrcMutator).Parallel()
ctx.BottomUp("version", cc.VersionMutator).Parallel()
ctx.BottomUp("begin", cc.BeginMutator).Parallel()
- ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator)
- ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator)
})
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_deps", apexDepsMutator)
- ctx.BottomUp("apex", apexMutator)
- ctx.BottomUp("apex_uses", apexUsesMutator)
ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
})
@@ -1207,16 +1209,22 @@
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
// APEX variant has __ANDROID_APEX__=<apexname> defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
// APEX variant has __ANDROID_APEX__=<apexname> defined
mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_otherapex").Rule("cc").Args["cFlags"]
ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__=myapex")
ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__=otherapex")
+ ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+ ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
}
func TestHeaderLibsDependency(t *testing.T) {
@@ -1267,6 +1275,74 @@
ensureContains(t, cFlags, "-Imy_include")
}
+func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName string, files []string) {
+ t.Helper()
+ apexRule := ctx.ModuleForTests(moduleName, "android_common_"+moduleName).Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ imageApexDir := "/image.apex/"
+ dstFiles := []string{}
+ for _, cmd := range strings.Split(copyCmds, "&&") {
+ cmd = strings.TrimSpace(cmd)
+ if cmd == "" {
+ continue
+ }
+ terms := strings.Split(cmd, " ")
+ switch terms[0] {
+ case "mkdir":
+ case "cp":
+ if len(terms) != 3 {
+ t.Fatal("copyCmds contains invalid cp command", cmd)
+ }
+ dst := terms[2]
+ index := strings.Index(dst, imageApexDir)
+ if index == -1 {
+ t.Fatal("copyCmds should copy a file to image.apex/", cmd)
+ }
+ dstFile := dst[index+len(imageApexDir):]
+ dstFiles = append(dstFiles, dstFile)
+ default:
+ t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
+ }
+ }
+ sort.Strings(dstFiles)
+ sort.Strings(files)
+ missing := []string{}
+ surplus := []string{}
+ i := 0
+ j := 0
+ for i < len(dstFiles) && j < len(files) {
+ if dstFiles[i] == files[j] {
+ i++
+ j++
+ } else if dstFiles[i] < files[j] {
+ surplus = append(surplus, dstFiles[i])
+ i++
+ } else {
+ missing = append(missing, files[j])
+ j++
+ }
+ }
+ if i < len(dstFiles) {
+ surplus = append(surplus, dstFiles[i:]...)
+ }
+ if j < len(files) {
+ missing = append(missing, files[j:]...)
+ }
+
+ failed := false
+ if len(surplus) > 0 {
+ t.Log("surplus files", surplus)
+ failed = true
+ }
+ if len(missing) > 0 {
+ t.Log("missing files", missing)
+ failed = true
+ }
+ if failed {
+ t.Fail()
+ }
+}
+
func TestVndkApexCurrent(t *testing.T) {
ctx, _ := testApex(t, `
apex_vndk {
@@ -1305,12 +1381,12 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
- ensureContains(t, copyCmds, "image.apex/lib/libvndksp.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndksp.so")
+ ensureExactContents(t, ctx, "myapex", []string{
+ "lib/libvndk.so",
+ "lib/libvndksp.so",
+ "lib64/libvndk.so",
+ "lib64/libvndksp.so",
+ })
}
func TestVndkApexWithPrebuilt(t *testing.T) {
@@ -1328,8 +1404,8 @@
}
cc_prebuilt_library_shared {
- name: "libvndkshared",
- srcs: ["libvndkshared.so"],
+ name: "libvndk",
+ srcs: ["libvndk.so"],
vendor_available: true,
vndk: {
enabled: true,
@@ -1337,13 +1413,33 @@
system_shared_libs: [],
stl: "none",
}
+
+ cc_prebuilt_library_shared {
+ name: "libvndk.arm",
+ srcs: ["libvndk.arm.so"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ enabled: false,
+ arch: {
+ arm: {
+ enabled: true,
+ },
+ },
+ system_shared_libs: [],
+ stl: "none",
+ }
`, withFiles(map[string][]byte{
- "libvndkshared.so": nil,
+ "libvndk.so": nil,
+ "libvndk.arm.so": nil,
}))
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndkshared.so")
+ ensureExactContents(t, ctx, "myapex", []string{
+ "lib/libvndk.so",
+ "lib/libvndk.arm.so",
+ "lib64/libvndk.so",
+ })
}
func TestVndkApexVersion(t *testing.T) {
@@ -1361,15 +1457,22 @@
private_key: "testkey.pem",
}
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
vendor_available: true,
vndk: {
enabled: true,
},
- system_shared_libs: [],
- stl: "none",
+ target_arch: "arm64",
+ arch: {
+ arm: {
+ srcs: ["libvndk27_arm.so"],
+ },
+ arm64: {
+ srcs: ["libvndk27_arm64.so"],
+ },
+ },
}
vndk_prebuilt_shared {
@@ -1379,18 +1482,27 @@
vndk: {
enabled: true,
},
- target_arch: "arm64",
- srcs: ["libvndk27.so"],
- }
+ target_arch: "x86_64",
+ arch: {
+ x86: {
+ srcs: ["libvndk27_x86.so"],
+ },
+ x86_64: {
+ srcs: ["libvndk27_x86_64.so"],
+ },
+ },
+ }
`, withFiles(map[string][]byte{
- "libvndk27.so": nil,
+ "libvndk27_arm.so": nil,
+ "libvndk27_arm64.so": nil,
+ "libvndk27_x86.so": nil,
+ "libvndk27_x86_64.so": nil,
}))
- apexRule := ctx.ModuleForTests("myapex_v27", "android_common_myapex_v27").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndk27.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndk27.so")
- ensureNotContains(t, copyCmds, "image.apex/lib/libvndk.so")
+ ensureExactContents(t, ctx, "myapex_v27", []string{
+ "lib/libvndk27_arm.so",
+ "lib64/libvndk27_arm64.so",
+ })
}
func TestVndkApexErrorWithDuplicateVersion(t *testing.T) {
@@ -1505,14 +1617,10 @@
},
}))
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
- copyCmds := apexRule.Args["copy_commands"]
- ensureContains(t, copyCmds, "image.apex/lib/libvndk.so")
- ensureContains(t, copyCmds, "image.apex/lib64/libvndk.so")
-
- // apex
- ensureNotContains(t, copyCmds, "image.apex/lib/x86/libvndk.so")
- ensureNotContains(t, copyCmds, "image.apex/lib64/x86_64/libvndk.so")
+ ensureExactContents(t, ctx, "myapex", []string{
+ "lib/libvndk.so",
+ "lib64/libvndk.so",
+ })
}
func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
@@ -1545,6 +1653,70 @@
`)
}
+func TestVndkApexWithBinder32(t *testing.T) {
+ ctx, _ := testApex(t,
+ `
+ apex_vndk {
+ name: "myapex_v27",
+ key: "myapex.key",
+ file_contexts: "myapex",
+ vndk_version: "27",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
+ target_arch: "arm",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm: {
+ srcs: ["libvndk27.so"],
+ }
+ },
+ }
+
+ vndk_prebuilt_shared {
+ name: "libvndk27",
+ version: "27",
+ target_arch: "arm",
+ binder32bit: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm: {
+ srcs: ["libvndk27binder32.so"],
+ }
+ },
+ }
+ `,
+ withFiles(map[string][]byte{
+ "libvndk27.so": nil,
+ "libvndk27binder32.so": nil,
+ }),
+ withBinder32bit,
+ withTargets(map[android.OsType][]android.Target{
+ android.Android: []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}, NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
+ },
+ }),
+ )
+
+ ensureExactContents(t, ctx, "myapex_v27", []string{
+ "lib/libvndk27binder32.so",
+ })
+}
+
func TestDependenciesInApexManifest(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -2055,12 +2227,12 @@
var builder strings.Builder
data.Custom(&builder, name, prefix, "", data)
androidMk := builder.String()
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest1\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest2\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.mytest3\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_manifest.json\n")
- ensureContains(t, androidMk, "LOCAL_MODULE := myapex.apex_pubkey\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest1.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest2.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := mytest3.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.json.myapex\n")
+ ensureContains(t, androidMk, "LOCAL_MODULE := apex_pubkey.myapex\n")
ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
}
diff --git a/bpfix/Android.bp b/bpfix/Android.bp
index 90a453d..aec9ff9 100644
--- a/bpfix/Android.bp
+++ b/bpfix/Android.bp
@@ -19,7 +19,18 @@
blueprint_go_binary {
name: "bpfix",
srcs: [
- "cmd/bpfix.go",
+ "cmd/main.go",
+ ],
+ deps: [
+ "bpfix-cmd",
+ ],
+}
+
+bootstrap_go_package {
+ name: "bpfix-cmd",
+ pkgPath: "android/soong/bpfix/bpfix/cmd",
+ srcs: [
+ "cmd-lib/bpfix.go",
],
deps: [
"bpfix-lib",
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 5f1cce8..9cba80a 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -45,66 +45,76 @@
// A FixRequest specifies the details of which fixes to apply to an individual file
// A FixRequest doesn't specify whether to do a dry run or where to write the results; that's in cmd/bpfix.go
type FixRequest struct {
- steps []fixStep
+ steps []FixStep
+}
+type FixStepsExtension struct {
+ Name string
+ Steps []FixStep
}
-type fixStep struct {
- name string
- fix func(f *Fixer) error
+type FixStep struct {
+ Name string
+ Fix func(f *Fixer) error
}
-var fixSteps = []fixStep{
+var fixStepsExtensions = []*FixStepsExtension(nil)
+
+func RegisterFixStepExtension(extension *FixStepsExtension) {
+ fixStepsExtensions = append(fixStepsExtensions, extension)
+}
+
+var fixSteps = []FixStep{
{
- name: "simplifyKnownRedundantVariables",
- fix: runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther),
+ Name: "simplifyKnownRedundantVariables",
+ Fix: runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther),
},
{
- name: "rewriteIncorrectAndroidmkPrebuilts",
- fix: rewriteIncorrectAndroidmkPrebuilts,
+ Name: "rewriteIncorrectAndroidmkPrebuilts",
+ Fix: rewriteIncorrectAndroidmkPrebuilts,
},
{
- name: "rewriteCtsModuleTypes",
- fix: rewriteCtsModuleTypes,
+ Name: "rewriteCtsModuleTypes",
+ Fix: rewriteCtsModuleTypes,
},
{
- name: "rewriteIncorrectAndroidmkAndroidLibraries",
- fix: rewriteIncorrectAndroidmkAndroidLibraries,
+ Name: "rewriteIncorrectAndroidmkAndroidLibraries",
+ Fix: rewriteIncorrectAndroidmkAndroidLibraries,
},
{
- name: "rewriteTestModuleTypes",
- fix: rewriteTestModuleTypes,
+ Name: "rewriteTestModuleTypes",
+ Fix: rewriteTestModuleTypes,
},
{
- name: "rewriteAndroidmkJavaLibs",
- fix: rewriteAndroidmkJavaLibs,
+ Name: "rewriteAndroidmkJavaLibs",
+ Fix: rewriteAndroidmkJavaLibs,
},
{
- name: "rewriteJavaStaticLibs",
- fix: rewriteJavaStaticLibs,
+ Name: "rewriteJavaStaticLibs",
+ Fix: rewriteJavaStaticLibs,
},
{
- name: "rewritePrebuiltEtc",
- fix: rewriteAndroidmkPrebuiltEtc,
+ Name: "rewritePrebuiltEtc",
+ Fix: rewriteAndroidmkPrebuiltEtc,
},
{
- name: "mergeMatchingModuleProperties",
- fix: runPatchListMod(mergeMatchingModuleProperties),
+ Name: "mergeMatchingModuleProperties",
+ Fix: runPatchListMod(mergeMatchingModuleProperties),
},
{
- name: "reorderCommonProperties",
- fix: runPatchListMod(reorderCommonProperties),
+ Name: "reorderCommonProperties",
+ Fix: runPatchListMod(reorderCommonProperties),
},
{
- name: "removeTags",
- fix: runPatchListMod(removeTags),
+ Name: "removeTags",
+ Fix: runPatchListMod(removeTags),
},
{
- name: "rewriteAndroidTest",
- fix: rewriteAndroidTest,
+ Name: "rewriteAndroidTest",
+ Fix: rewriteAndroidTest,
},
{
- name: "rewriteAndroidAppImport",
- fix: rewriteAndroidAppImport,
+ Name: "rewriteAndroidAppImport",
+ Fix: rewriteAndroidAppImport,
},
}
@@ -113,8 +123,27 @@
}
func (r FixRequest) AddAll() (result FixRequest) {
- result.steps = append([]fixStep(nil), r.steps...)
+ result.steps = append([]FixStep(nil), r.steps...)
result.steps = append(result.steps, fixSteps...)
+ for _, extension := range fixStepsExtensions {
+ result.steps = append(result.steps, extension.Steps...)
+ }
+ return result
+}
+
+func (r FixRequest) AddBase() (result FixRequest) {
+ result.steps = append([]FixStep(nil), r.steps...)
+ result.steps = append(result.steps, fixSteps...)
+ return result
+}
+
+func (r FixRequest) AddMatchingExtensions(pattern string) (result FixRequest) {
+ result.steps = append([]FixStep(nil), r.steps...)
+ for _, extension := range fixStepsExtensions {
+ if match, _ := filepath.Match(pattern, extension.Name); match {
+ result.steps = append(result.steps, extension.Steps...)
+ }
+ }
return result
}
@@ -122,6 +151,10 @@
tree *parser.File
}
+func (f Fixer) Tree() *parser.File {
+ return f.tree
+}
+
func NewFixer(tree *parser.File) *Fixer {
fixer := &Fixer{tree}
@@ -198,7 +231,7 @@
func (f *Fixer) fixTreeOnce(config FixRequest) error {
for _, fix := range config.steps {
- err := fix.fix(f)
+ err := fix.Fix(f)
if err != nil {
return err
}
diff --git a/bpfix/cmd/bpfix.go b/bpfix/cmd-lib/bpfix.go
similarity index 97%
rename from bpfix/cmd/bpfix.go
rename to bpfix/cmd-lib/bpfix.go
index ccdae16..98122f2 100644
--- a/bpfix/cmd/bpfix.go
+++ b/bpfix/cmd-lib/bpfix.go
@@ -12,11 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// This file provides a command-line interface to bpfix
+// This file provides a bpfix command-line library
// TODO(jeffrygaston) should this file be consolidated with bpfmt.go?
-package main
+package cmd
import (
"bytes"
@@ -128,7 +128,7 @@
filepath.Walk(path, makeFileVisitor(fixRequest))
}
-func main() {
+func Run() {
flag.Parse()
fixRequest := bpfix.NewFixRequest().AddAll()
diff --git a/bpfix/cmd/main.go b/bpfix/cmd/main.go
new file mode 100644
index 0000000..8ca16b4
--- /dev/null
+++ b/bpfix/cmd/main.go
@@ -0,0 +1,25 @@
+// Copyright 2017 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.
+
+// This file provides a wrapper to the bpfix command-line library
+
+package main
+
+import (
+ "android/soong/bpfix/bpfix/cmd"
+)
+
+func main() {
+ cmd.Run()
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index cdd8e92..a978cb9 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -93,6 +93,11 @@
fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
if c.isVndk() && !c.static() {
fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion())
+ // VNDK libraries available to vendor are not installed because
+ // they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
+ if !c.isVndkExt() {
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
+ }
}
}
},
diff --git a/cc/builder.go b/cc/builder.go
index 0760dd4..491ebc5 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -130,6 +130,17 @@
},
"args", "crossCompile")
+ _ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
+
+ archiveRepack = pctx.AndroidStaticRule("archiveRepack",
+ blueprint.RuleParams{
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
+ Command: "CLANG_BIN=${config.ClangBin} $archiveRepackPath -i ${in} -o ${out} -d ${out}.d ${objects}",
+ CommandDeps: []string{"$archiveRepackPath"},
+ },
+ "objects")
+
emptyFile = pctx.AndroidStaticRule("emptyFile",
blueprint.RuleParams{
Command: "rm -f $out && touch $out",
@@ -866,6 +877,20 @@
return android.OptionalPath{}
}
+func TransformArchiveRepack(ctx android.ModuleContext, inputFile android.Path,
+ outputFile android.WritablePath, objects []string) {
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: archiveRepack,
+ Description: "Repack archive " + outputFile.Base(),
+ Output: outputFile,
+ Input: inputFile,
+ Args: map[string]string{
+ "objects": strings.Join(objects, " "),
+ },
+ })
+}
+
func gccCmd(toolchain config.Toolchain, cmd string) string {
return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
}
diff --git a/cc/cc.go b/cc/cc.go
index b92ed44..67132e4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -215,6 +215,10 @@
// Allows this module to use non-APEX version of libraries. Useful
// for building binaries that are started before APEXes are activated.
Bootstrap *bool
+
+ // Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant.
+ // see soong/cc/config/vndk.go
+ MustUseVendorVariant bool `blueprint:"mutated"`
}
type VendorProperties struct {
@@ -488,15 +492,6 @@
return ""
}
-// IsVndkOnSystem returns true if a module is supposed to be a vndk library provided by system to vendor
-func (c *Module) IsVndkOnSystem() bool {
- if linker, ok := c.linker.(libraryInterface); ok {
- return linker.shared() && c.isVndk() && c.useVndk() && !c.isVndkExt()
- }
-
- return false
-}
-
func (c *Module) VndkVersion() string {
return c.vndkVersion()
}
@@ -586,7 +581,7 @@
func (c *Module) isLlndk(config android.Config) bool {
// Returns true for both LLNDK (public) and LLNDK-private libs.
- return inList(c.Name(), *llndkLibraries(config))
+ return inList(c.BaseModuleName(), *llndkLibraries(config))
}
func (c *Module) isLlndkPublic(config android.Config) bool {
@@ -596,7 +591,7 @@
func (c *Module) isVndkPrivate(config android.Config) bool {
// Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private.
- return inList(c.Name(), *vndkPrivateLibraries(config))
+ return inList(c.BaseModuleName(), *vndkPrivateLibraries(config))
}
func (c *Module) isVndk() bool {
@@ -639,7 +634,7 @@
}
func (c *Module) mustUseVendorVariant() bool {
- return c.isVndkSp() || inList(c.Name(), config.VndkMustUseVendorVariantList)
+ return c.isVndkSp() || c.Properties.MustUseVendorVariant
}
func (c *Module) getVndkExtendsModuleName() string {
@@ -2113,7 +2108,6 @@
}
func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
- name := actx.ModuleName()
if c.useVndk() {
if lib, ok := c.linker.(*llndkStubDecorator); ok {
if Bool(lib.Properties.Vendor_available) {
@@ -2135,7 +2129,7 @@
// TODO(b/114741097): use the correct ndk stl once build errors have been fixed
//family, link := getNdkStlFamilyAndLinkType(c)
//return fmt.Sprintf("native:ndk:%s:%s", family, link)
- } else if inList(name, *vndkUsingCoreVariantLibraries(actx.Config())) {
+ } else if actx.DeviceConfig().VndkUseCoreVariant() && !c.mustUseVendorVariant() {
return "native:platform_vndk"
} else {
return "native:platform"
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 689aacd..8418ec7 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -264,6 +264,13 @@
}
}
+func checkVndkOutput(t *testing.T, ctx *android.TestContext, output string, expected []string) {
+ t.Helper()
+ vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
+ actual := strings.FieldsFunc(strings.ReplaceAll(vndkSnapshot.Output(output).Args["content"], "\\n", "\n"), func(r rune) bool { return r == '\n' })
+ assertArrayString(t, actual, expected)
+}
+
func TestVndk(t *testing.T) {
config := android.TestArchConfig(buildDir, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -336,6 +343,69 @@
checkVndkSnapshot(t, ctx, "libvndk", vndkCoreLib2ndPath, variant2nd)
checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLibPath, variant)
checkVndkSnapshot(t, ctx, "libvndk_sp", vndkSpLib2ndPath, variant2nd)
+
+ checkVndkOutput(t, ctx, "vndk/llndk.libraries.txt", []string{"libc.so", "libdl.so", "libft2.so", "libm.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk_private.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkprivate.libraries.txt", []string{"libft2.so", "libvndk_private.so", "libvndk_sp_private.so"})
+ checkVndkOutput(t, ctx, "vndk/vndksp.libraries.txt", []string{"libc++.so", "libvndk_sp.so", "libvndk_sp_private.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", nil)
+ // merged & tagged & filtered-out(libclang_rt)
+ checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
+ "LLNDK: libc.so",
+ "LLNDK: libdl.so",
+ "LLNDK: libft2.so",
+ "LLNDK: libm.so",
+ "VNDK-SP: libc++.so",
+ "VNDK-SP: libvndk_sp.so",
+ "VNDK-SP: libvndk_sp_private.so",
+ "VNDK-core: libvndk.so",
+ "VNDK-core: libvndk_private.so",
+ "VNDK-private: libft2.so",
+ "VNDK-private: libvndk_private.so",
+ "VNDK-private: libvndk_sp_private.so",
+ })
+}
+
+func TestVndkUsingCoreVariant(t *testing.T) {
+ config := android.TestArchConfig(buildDir, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+
+ setVndkMustUseVendorVariantListForTest(config, []string{"libvndk"})
+
+ ctx := testCcWithConfig(t, `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk_sp",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvndk2",
+ vendor_available: false,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+ `, config)
+
+ checkVndkOutput(t, ctx, "vndk/vndkcore.libraries.txt", []string{"libvndk.so", "libvndk2.so"})
+ checkVndkOutput(t, ctx, "vndk/vndkcorevariant.libraries.txt", []string{"libvndk2.so"})
}
func TestVndkDepError(t *testing.T) {
@@ -768,6 +838,19 @@
},
nocrt: true,
}
+ cc_library {
+ name: "libvndk2",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ target: {
+ vendor: {
+ suffix: "-suffix",
+ },
+ },
+ nocrt: true,
+ }
cc_library {
name: "libvndk_ext",
@@ -778,9 +861,22 @@
},
nocrt: true,
}
+
+ cc_library {
+ name: "libvndk2_ext",
+ vendor: true,
+ vndk: {
+ enabled: true,
+ extends: "libvndk2",
+ },
+ nocrt: true,
+ }
`)
checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk")
+
+ mod := ctx.ModuleForTests("libvndk2_ext", vendorVariant).Module().(*Module)
+ assertString(t, mod.outputFile.Path().Base(), "libvndk2-suffix.so")
}
func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
@@ -1340,9 +1436,9 @@
assertArrayString(t, *vndkSpLibraries(config),
[]string{"libc++", "libvndksp"})
assertArrayString(t, *llndkLibraries(config),
- []string{"libc", "libdl", "libllndk", "libllndkprivate", "libm"})
+ []string{"libc", "libdl", "libft2", "libllndk", "libllndkprivate", "libm"})
assertArrayString(t, *vndkPrivateLibraries(config),
- []string{"libllndkprivate", "libvndkprivate"})
+ []string{"libft2", "libllndkprivate", "libvndkprivate"})
vendorVariant27 := "android_arm64_armv8-a_vendor.27_shared"
diff --git a/cc/compiler.go b/cc/compiler.go
index ffb6ad2..438dee7 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -320,7 +320,9 @@
}
if ctx.apexName() != "" {
+ // TODO(b/142582178): remove the value for __ANDROID_APEX__
flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX__="+ctx.apexName())
+ flags.GlobalFlags = append(flags.GlobalFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
}
instructionSet := String(compiler.Properties.Instruction_set)
@@ -528,6 +530,12 @@
return false
}
+// makeDefineString transforms a name of an APEX module into a value to be used as value for C define
+// For example, com.android.foo => COM_ANDROID_FOO
+func makeDefineString(name string) string {
+ return strings.ReplaceAll(strings.ToUpper(name), ".", "_")
+}
+
var gnuToCReplacer = strings.NewReplacer("gnu", "c")
func ndkPathDeps(ctx ModuleContext) android.Paths {
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 1026370..63b9d48 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -63,6 +63,7 @@
"10.12",
"10.13",
"10.14",
+ "10.15",
}
darwinAvailableLibraries = append(
diff --git a/cc/library.go b/cc/library.go
index b5dae0b..1943e89 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -599,7 +599,11 @@
name += suffix
if ctx.isVndkExt() {
- name = ctx.getVndkExtendsModuleName()
+ // vndk-ext lib should have the same name with original lib
+ ctx.VisitDirectDepsWithTag(vndkExtDepTag, func(module android.Module) {
+ originalName := module.(*Module).outputFile.Path()
+ name = strings.TrimSuffix(originalName.Base(), originalName.Ext())
+ })
}
if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
diff --git a/cc/testing.go b/cc/testing.go
index 6fa6ea7..fafaeb0 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -145,6 +145,18 @@
symbol_file: "",
}
cc_library {
+ name: "libft2",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ recovery_available: true,
+ }
+ llndk_library {
+ name: "libft2",
+ symbol_file: "",
+ vendor_available: false,
+ }
+ cc_library {
name: "libc++_static",
no_libcrt: true,
nocrt: true,
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index fef4508..dfc6f76 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -29,6 +29,9 @@
type toolchainLibraryProperties struct {
// the prebuilt toolchain library, as a path from the top of the source tree
Src *string `android:"arch_variant"`
+
+ // Repack the archive with only the selected objects.
+ Repack_objects_to_keep []string `android:"arch_variant"`
}
type toolchainLibraryDecorator struct {
@@ -90,6 +93,14 @@
return outputFile
}
+ if library.Properties.Repack_objects_to_keep != nil {
+ fileName := ctx.ModuleName() + staticLibraryExtension
+ outputFile := android.PathForModuleOut(ctx, fileName)
+ TransformArchiveRepack(ctx, srcPath, outputFile, library.Properties.Repack_objects_to_keep)
+
+ return outputFile
+ }
+
return srcPath
}
diff --git a/cc/vndk.go b/cc/vndk.go
index 1c71a49..46fd7b1 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -194,14 +194,16 @@
}
var (
- vndkCoreLibrariesKey = android.NewOnceKey("vndkCoreLibrarires")
- vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibrarires")
- llndkLibrariesKey = android.NewOnceKey("llndkLibrarires")
- vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibrarires")
- vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
- modulePathsKey = android.NewOnceKey("modulePaths")
- vndkSnapshotOutputsKey = android.NewOnceKey("vndkSnapshotOutputs")
- vndkLibrariesLock sync.Mutex
+ vndkCoreLibrariesKey = android.NewOnceKey("vndkCoreLibrarires")
+ vndkSpLibrariesKey = android.NewOnceKey("vndkSpLibrarires")
+ llndkLibrariesKey = android.NewOnceKey("llndkLibrarires")
+ vndkPrivateLibrariesKey = android.NewOnceKey("vndkPrivateLibrarires")
+ vndkUsingCoreVariantLibrariesKey = android.NewOnceKey("vndkUsingCoreVariantLibrarires")
+ modulePathsKey = android.NewOnceKey("modulePaths")
+ vndkSnapshotOutputsKey = android.NewOnceKey("vndkSnapshotOutputs")
+ vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")
+ testVndkMustUseVendorVariantListKey = android.NewOnceKey("testVndkMustUseVendorVariantListKey")
+ vndkLibrariesLock sync.Mutex
headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
)
@@ -248,6 +250,26 @@
}).(*android.RuleBuilderInstalls)
}
+func vndkMustUseVendorVariantList(cfg android.Config) []string {
+ return cfg.Once(vndkMustUseVendorVariantListKey, func() interface{} {
+ override := cfg.Once(testVndkMustUseVendorVariantListKey, func() interface{} {
+ return []string(nil)
+ }).([]string)
+ if override != nil {
+ return override
+ }
+ return config.VndkMustUseVendorVariantList
+ }).([]string)
+}
+
+// test may call this to override global configuration(config.VndkMustUseVendorVariantList)
+// when it is called, it must be before the first call to vndkMustUseVendorVariantList()
+func setVndkMustUseVendorVariantListForTest(config android.Config, mustUseVendorVariantList []string) {
+ config.Once(testVndkMustUseVendorVariantListKey, func() interface{} {
+ return mustUseVendorVariantList
+ })
+}
+
func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
lib := m.linker.(*llndkStubDecorator)
name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
@@ -276,7 +298,10 @@
defer vndkLibrariesLock.Unlock()
modulePaths := modulePaths(mctx.Config())
- if mctx.DeviceConfig().VndkUseCoreVariant() && !inList(name, config.VndkMustUseVendorVariantList) {
+ if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
+ m.Properties.MustUseVendorVariant = true
+ }
+ if mctx.DeviceConfig().VndkUseCoreVariant() && !m.mustUseVendorVariant() {
vndkUsingCoreVariantLibraries := vndkUsingCoreVariantLibraries(mctx.Config())
if !inList(name, *vndkUsingCoreVariantLibraries) {
*vndkUsingCoreVariantLibraries = append(*vndkUsingCoreVariantLibraries, name)
@@ -307,6 +332,31 @@
}
}
+func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool {
+ if !m.Enabled() {
+ return false
+ }
+
+ if m.Target().NativeBridge == android.NativeBridgeEnabled {
+ return false
+ }
+
+ // prebuilt vndk modules should match with device
+ // TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared
+ // When b/142675459 is landed, remove following check
+ if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.matchesWithDevice(mctx.DeviceConfig()) {
+ return false
+ }
+
+ if lib, ok := m.linker.(libraryInterface); ok {
+ useCoreVariant := m.vndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
+ mctx.DeviceConfig().VndkUseCoreVariant() &&
+ !inList(m.BaseModuleName(), config.VndkMustUseVendorVariantList)
+ return lib.shared() && m.useVndk() && m.isVndk() && !m.isVndkExt() && !useCoreVariant
+ }
+ return false
+}
+
// gather list of vndk-core, vndk-sp, and ll-ndk libs
func VndkMutator(mctx android.BottomUpMutatorContext) {
m, ok := mctx.Module().(*Module)
@@ -365,6 +415,8 @@
return
}
+ c.buildVndkLibrariesTxtFiles(ctx)
+
outputs := vndkSnapshotOutputs(ctx.Config())
snapshotDir := "vndk-snapshot"
@@ -604,3 +656,88 @@
installSnapshotFileFromContent(modulePathTxtBuilder.String(),
filepath.Join(configsDir, "module_paths.txt"))
}
+
+func installListFile(ctx android.SingletonContext, list []string, pathComponents ...string) android.OutputPath {
+ out := android.PathForOutput(ctx, pathComponents...)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: out,
+ Description: "Writing " + out.String(),
+ Args: map[string]string{
+ "content": strings.Join(list, "\\n"),
+ },
+ })
+ return out
+}
+
+func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
+ var (
+ llndk, vndkcore, vndksp, vndkprivate, vndkcorevariant, merged []string
+ )
+ vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
+ config := ctx.Config()
+ ctx.VisitAllModules(func(m android.Module) {
+ if !m.Enabled() {
+ return
+ }
+ c, ok := m.(*Module)
+ if !ok || c.Os().Class != android.Device {
+ return
+ }
+ lib, ok := c.linker.(interface{ shared() bool })
+ if !ok || !lib.shared() {
+ return
+ }
+
+ if !c.OutputFile().Valid() {
+ return
+ }
+
+ filename := c.OutputFile().Path().Base()
+ if c.isLlndk(config) {
+ llndk = append(llndk, filename)
+ if c.isVndkPrivate(config) {
+ vndkprivate = append(vndkprivate, filename)
+ }
+ } else if c.vndkVersion() == vndkVersion && c.isVndk() && !c.isVndkExt() {
+ if c.isVndkSp() {
+ vndksp = append(vndksp, filename)
+ } else {
+ vndkcore = append(vndkcore, filename)
+ }
+ if c.isVndkPrivate(config) {
+ vndkprivate = append(vndkprivate, filename)
+ }
+ if ctx.DeviceConfig().VndkUseCoreVariant() && !c.mustUseVendorVariant() {
+ vndkcorevariant = append(vndkcorevariant, filename)
+ }
+ }
+ })
+ llndk = android.SortedUniqueStrings(llndk)
+ vndkcore = android.SortedUniqueStrings(vndkcore)
+ vndksp = android.SortedUniqueStrings(vndksp)
+ vndkprivate = android.SortedUniqueStrings(vndkprivate)
+ vndkcorevariant = android.SortedUniqueStrings(vndkcorevariant)
+
+ installListFile(ctx, llndk, "vndk", "llndk.libraries.txt")
+ installListFile(ctx, vndkcore, "vndk", "vndkcore.libraries.txt")
+ installListFile(ctx, vndksp, "vndk", "vndksp.libraries.txt")
+ installListFile(ctx, vndkprivate, "vndk", "vndkprivate.libraries.txt")
+ installListFile(ctx, vndkcorevariant, "vndk", "vndkcorevariant.libraries.txt")
+
+ // merged & tagged & filtered-out(libclang_rt)
+ filterOutLibClangRt := func(libList []string) (filtered []string) {
+ for _, lib := range libList {
+ if !strings.HasPrefix(lib, "libclang_rt.") {
+ filtered = append(filtered, lib)
+ }
+ }
+ return
+ }
+ merged = append(merged, addPrefix(filterOutLibClangRt(llndk), "LLNDK: ")...)
+ merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
+ merged = append(merged, addPrefix(filterOutLibClangRt(vndkcore), "VNDK-core: ")...)
+ merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
+
+ installListFile(ctx, merged, "vndk", "vndk.libraries.txt")
+}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index a6d5085..c941c46 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -130,13 +130,7 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- arches := ctx.DeviceConfig().Arches()
- if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
- ctx.Module().SkipInstall()
- return nil
- }
-
- if ctx.DeviceConfig().BinderBitness() != p.binderBit() {
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
ctx.Module().SkipInstall()
return nil
}
@@ -154,6 +148,20 @@
return nil
}
+func (p *vndkPrebuiltLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+ arches := config.Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
+ return false
+ }
+ if config.BinderBitness() != p.binderBit() {
+ return false
+ }
+ if len(p.properties.Srcs) == 0 {
+ return false
+ }
+ return true
+}
+
func (p *vndkPrebuiltLibraryDecorator) nativeCoverage() bool {
return false
}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index f39ec4a..9215eff 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -24,8 +24,6 @@
// GlobalConfig stores the configuration for dex preopting set by the product
type GlobalConfig struct {
- DefaultNoStripping bool // don't strip dex files by default
-
DisablePreopt bool // disable preopt for all modules
DisablePreoptModules []string // modules with preopt disabled by product-specific config
@@ -55,8 +53,7 @@
DefaultCompilerFilter string // default compiler filter to pass to dex2oat, overridden by --compiler-filter= in module-specific dex2oat flags
SystemServerCompilerFilter string // default compiler filter to pass to dex2oat for system server jars
- GenerateDMFiles bool // generate Dex Metadata files
- NeverAllowStripping bool // whether stripping should not be done - used as build time check to make sure dex files are always available
+ GenerateDMFiles bool // generate Dex Metadata files
NoDebugInfo bool // don't generate debug info by default
DontResolveStartupStrings bool // don't resolve string literals loaded during application startup.
@@ -133,10 +130,6 @@
ForceCreateAppImage bool
PresignedPrebuilt bool
-
- NoStripping bool
- StripInputPath android.Path
- StripOutputPath android.WritablePath
}
func constructPath(ctx android.PathContext, path string) android.Path {
@@ -233,8 +226,6 @@
LibraryPaths map[string]string
DexPreoptImages []string
PreoptBootClassPathDexFiles []string
- StripInputPath string
- StripOutputPath string
}
config := ModuleJSONConfig{}
@@ -252,8 +243,6 @@
config.ModuleConfig.LibraryPaths = constructPathMap(ctx, config.LibraryPaths)
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
- config.ModuleConfig.StripInputPath = constructPath(ctx, config.StripInputPath)
- config.ModuleConfig.StripOutputPath = constructWritablePath(ctx, config.StripOutputPath)
// This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON.
config.ModuleConfig.DexPreoptImagesDeps = make([]android.Paths, len(config.ModuleConfig.DexPreoptImages))
@@ -283,7 +272,6 @@
func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
return GlobalConfig{
- DefaultNoStripping: false,
DisablePreopt: false,
DisablePreoptModules: nil,
OnlyPreoptBootImageAndSystemServer: false,
@@ -302,7 +290,6 @@
DefaultCompilerFilter: "",
SystemServerCompilerFilter: "",
GenerateDMFiles: false,
- NeverAllowStripping: false,
NoDebugInfo: false,
DontResolveStartupStrings: false,
AlwaysSystemServerDebugInfo: false,
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 511b840..46e0f0a 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -13,7 +13,7 @@
// limitations under the License.
// The dexpreopt package converts a global dexpreopt config and a module dexpreopt config into rules to perform
-// dexpreopting and to strip the dex files from the APK or JAR.
+// dexpreopting.
//
// It is used in two places; in the dexpeopt_gen binary for modules defined in Make, and directly linked into Soong.
//
@@ -22,8 +22,7 @@
// changed. One script takes an APK or JAR as an input and produces a zip file containing any outputs of preopting,
// in the location they should be on the device. The Make build rules will unzip the zip file into $(PRODUCT_OUT) when
// installing the APK, which will install the preopt outputs into $(PRODUCT_OUT)/system or $(PRODUCT_OUT)/system_other
-// as necessary. The zip file may be empty if preopting was disabled for any reason. The second script takes an APK or
-// JAR as an input and strips the dex files in it as necessary.
+// as necessary. The zip file may be empty if preopting was disabled for any reason.
//
// The intermediate shell scripts allow changes to this package or to the global config to regenerate the shell scripts
// but only require re-executing preopting if the script has changed.
@@ -48,45 +47,6 @@
const SystemPartition = "/system/"
const SystemOtherPartition = "/system_other/"
-// GenerateStripRule generates a set of commands that will take an APK or JAR as an input and strip the dex files if
-// they are no longer necessary after preopting.
-func GenerateStripRule(global GlobalConfig, module ModuleConfig) (rule *android.RuleBuilder, err error) {
- defer func() {
- if r := recover(); r != nil {
- if _, ok := r.(runtime.Error); ok {
- panic(r)
- } else if e, ok := r.(error); ok {
- err = e
- rule = nil
- } else {
- panic(r)
- }
- }
- }()
-
- tools := global.Tools
-
- rule = android.NewRuleBuilder()
-
- strip := shouldStripDex(module, global)
-
- if strip {
- if global.NeverAllowStripping {
- panic(fmt.Errorf("Stripping requested on %q, though the product does not allow it", module.DexLocation))
- }
- // Only strips if the dex files are not already uncompressed
- rule.Command().
- Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, module.StripInputPath).
- Tool(tools.Zip2zip).FlagWithInput("-i ", module.StripInputPath).FlagWithOutput("-o ", module.StripOutputPath).
- FlagWithArg("-x ", `"classes*.dex"`).
- Textf(`; else cp -f %s %s; fi`, module.StripInputPath, module.StripOutputPath)
- } else {
- rule.Command().Text("cp -f").Input(module.StripInputPath).Output(module.StripOutputPath)
- }
-
- return rule, nil
-}
-
// GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a
// ModuleConfig. The produced files and their install locations will be available through rule.Installs().
func GenerateDexpreoptRule(ctx android.PathContext,
@@ -120,7 +80,6 @@
if !dexpreoptDisabled(global, module) {
// Don't preopt individual boot jars, they will be preopted together.
- // This check is outside dexpreoptDisabled because they still need to be stripped.
if !contains(global.BootJars, module.Name) {
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
!module.NoCreateAppImage
@@ -515,51 +474,6 @@
rule.Install(vdexPath, vdexInstallPath)
}
-// Return if the dex file in the APK should be stripped. If an APK is found to contain uncompressed dex files at
-// dex2oat time it will not be stripped even if strip=true.
-func shouldStripDex(module ModuleConfig, global GlobalConfig) bool {
- strip := !global.DefaultNoStripping
-
- if dexpreoptDisabled(global, module) {
- strip = false
- }
-
- if module.NoStripping {
- strip = false
- }
-
- // Don't strip modules that are not on the system partition in case the oat/vdex version in system ROM
- // doesn't match the one in other partitions. It needs to be able to fall back to the APK for that case.
- if !strings.HasPrefix(module.DexLocation, SystemPartition) {
- strip = false
- }
-
- // system_other isn't there for an OTA, so don't strip if module is on system, and odex is on system_other.
- if odexOnSystemOther(module, global) {
- strip = false
- }
-
- if module.HasApkLibraries {
- strip = false
- }
-
- // Don't strip with dex files we explicitly uncompress (dexopt will not store the dex code).
- if module.UncompressedDex {
- strip = false
- }
-
- if shouldGenerateDM(module, global) {
- strip = false
- }
-
- if module.PresignedPrebuilt {
- // Only strip out files if we can re-sign the package.
- strip = false
- }
-
- return strip
-}
-
func shouldGenerateDM(module ModuleConfig, global GlobalConfig) bool {
// Generating DM files only makes sense for verify, avoid doing for non verify compiler filter APKs.
// No reason to use a dm file if the dex is already uncompressed.
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index d54ddb1..009e906 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -31,7 +31,6 @@
var (
dexpreoptScriptPath = flag.String("dexpreopt_script", "", "path to output dexpreopt script")
- stripScriptPath = flag.String("strip_script", "", "path to output strip script")
globalConfigPath = flag.String("global", "", "path to global configuration file")
moduleConfigPath = flag.String("module", "", "path to module configuration file")
outDir = flag.String("out_dir", "", "path to output directory")
@@ -64,10 +63,6 @@
usage("path to output dexpreopt script is required")
}
- if *stripScriptPath == "" {
- usage("path to output strip script is required")
- }
-
if *globalConfigPath == "" {
usage("path to global configuration file is required")
}
@@ -90,10 +85,6 @@
os.Exit(2)
}
- // This shouldn't be using *PathForTesting, but it's outside of soong_build so its OK for now.
- moduleConfig.StripInputPath = android.PathForTesting("$1")
- moduleConfig.StripOutputPath = android.WritablePathForTesting("$2")
-
moduleConfig.DexPath = android.PathForTesting("$1")
defer func() {
@@ -110,11 +101,11 @@
}
}()
- writeScripts(ctx, globalConfig, moduleConfig, *dexpreoptScriptPath, *stripScriptPath)
+ writeScripts(ctx, globalConfig, moduleConfig, *dexpreoptScriptPath)
}
func writeScripts(ctx android.PathContext, global dexpreopt.GlobalConfig, module dexpreopt.ModuleConfig,
- dexpreoptScriptPath, stripScriptPath string) {
+ dexpreoptScriptPath string) {
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, module)
if err != nil {
panic(err)
@@ -135,11 +126,6 @@
FlagWithArg("-C ", installDir.String()).
FlagWithArg("-D ", installDir.String())
- stripRule, err := dexpreopt.GenerateStripRule(global, module)
- if err != nil {
- panic(err)
- }
-
write := func(rule *android.RuleBuilder, file string) {
script := &bytes.Buffer{}
script.WriteString(scriptHeader)
@@ -180,15 +166,8 @@
if module.DexPath.String() != "$1" {
panic(fmt.Errorf("module.DexPath must be '$1', was %q", module.DexPath))
}
- if module.StripInputPath.String() != "$1" {
- panic(fmt.Errorf("module.StripInputPath must be '$1', was %q", module.StripInputPath))
- }
- if module.StripOutputPath.String() != "$2" {
- panic(fmt.Errorf("module.StripOutputPath must be '$2', was %q", module.StripOutputPath))
- }
write(dexpreoptRule, dexpreoptScriptPath)
- write(stripRule, stripScriptPath)
}
const scriptHeader = `#!/bin/bash
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index bf692fe..6f8120e 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -17,8 +17,6 @@
import (
"android/soong/android"
"fmt"
- "reflect"
- "strings"
"testing"
)
@@ -58,9 +56,6 @@
NoCreateAppImage: false,
ForceCreateAppImage: false,
PresignedPrebuilt: false,
- NoStripping: false,
- StripInputPath: android.PathForOutput(ctx, fmt.Sprintf("unstripped/%s.apk", name)),
- StripOutputPath: android.PathForOutput(ctx, fmt.Sprintf("stripped/%s.apk", name)),
}
}
@@ -83,20 +78,6 @@
}
}
-func TestDexPreoptStrip(t *testing.T) {
- // Test that we panic if we strip in a configuration where stripping is not allowed.
- ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
-
- global.NeverAllowStripping = true
- module.NoStripping = false
-
- _, err := GenerateStripRule(global, module)
- if err == nil {
- t.Errorf("Expected an error when calling GenerateStripRule on a stripped module")
- }
-}
-
func TestDexPreoptSystemOther(t *testing.T) {
ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
global := GlobalConfigForTests(ctx)
@@ -176,56 +157,3 @@
t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
}
}
-
-func TestStripDex(t *testing.T) {
- tests := []struct {
- name string
- setup func(global *GlobalConfig, module *ModuleConfig)
- strip bool
- }{
- {
- name: "default strip",
- setup: func(global *GlobalConfig, module *ModuleConfig) {},
- strip: true,
- },
- {
- name: "global no stripping",
- setup: func(global *GlobalConfig, module *ModuleConfig) { global.DefaultNoStripping = true },
- strip: false,
- },
- {
- name: "module no stripping",
- setup: func(global *GlobalConfig, module *ModuleConfig) { module.NoStripping = true },
- strip: false,
- },
- }
-
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
-
- ctx := android.PathContextForTesting(android.TestConfig("out", nil), nil)
- global, module := GlobalConfigForTests(ctx), testSystemModuleConfig(ctx, "test")
-
- test.setup(&global, &module)
-
- rule, err := GenerateStripRule(global, module)
- if err != nil {
- t.Fatal(err)
- }
-
- if test.strip {
- want := `zip2zip -i out/unstripped/test.apk -o out/stripped/test.apk -x "classes*.dex"`
- if len(rule.Commands()) < 1 || !strings.Contains(rule.Commands()[0], want) {
- t.Errorf("\nwant commands[0] to have:\n %v\ngot:\n %v", want, rule.Commands()[0])
- }
- } else {
- wantCommands := []string{
- "cp -f out/unstripped/test.apk out/stripped/test.apk",
- }
- if !reflect.DeepEqual(rule.Commands(), wantCommands) {
- t.Errorf("\nwant commands:\n %v\ngot:\n %v", wantCommands, rule.Commands())
- }
- }
- })
- }
-}
diff --git a/java/androidmk.go b/java/androidmk.go
index 7927acf..9e9b277 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -534,6 +534,9 @@
if dstubs.jdiffDocZip != nil {
entries.SetPath("LOCAL_DROIDDOC_JDIFF_DOC_ZIP", dstubs.jdiffDocZip)
}
+ if dstubs.metadataZip != nil {
+ entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
+ }
apiFilePrefix := "INTERNAL_PLATFORM_"
if String(dstubs.properties.Api_tag_name) != "" {
apiFilePrefix += String(dstubs.properties.Api_tag_name) + "_"
diff --git a/java/app_test.go b/java/app_test.go
index f2aaec3..05ab856 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1149,13 +1149,7 @@
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs")
}
- // Make sure stripping wasn't done.
- stripRule := variant.Output("dexpreopt/foo.apk")
- if !strings.HasPrefix(stripRule.RuleParams.Command, "cp -f") {
- t.Errorf("unexpected, non-skipping strip command: %q", stripRule.RuleParams.Command)
- }
-
- // Make sure signing was skipped and aligning was done instead.
+ // Make sure signing was skipped and aligning was done.
if variant.MaybeOutput("signed/foo.apk").Rule != nil {
t.Errorf("signing rule shouldn't be included.")
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index b48871e..2b1c994 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -40,13 +40,9 @@
type DexpreoptProperties struct {
Dex_preopt struct {
- // If false, prevent dexpreopting and stripping the dex file from the final jar. Defaults to
- // true.
+ // If false, prevent dexpreopting. Defaults to true.
Enabled *bool
- // If true, never strip the dex files from the final jar when dexpreopting. Defaults to false.
- No_stripping *bool
-
// If true, generate an app image (.art file) for this module.
App_image *bool
@@ -136,8 +132,6 @@
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
- strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base())
-
var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath
profileIsTextListing := false
@@ -191,10 +185,6 @@
ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
PresignedPrebuilt: d.isPresignedPrebuilt,
-
- NoStripping: Bool(d.dexpreoptProperties.Dex_preopt.No_stripping),
- StripInputPath: dexJarFile,
- StripOutputPath: strippedDexJarFile.OutputPath,
}
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, global, dexpreoptConfig)
@@ -207,13 +197,5 @@
d.builtInstalled = dexpreoptRule.Installs().String()
- stripRule, err := dexpreopt.GenerateStripRule(global, dexpreoptConfig)
- if err != nil {
- ctx.ModuleErrorf("error generating dexpreopt strip rule: %s", err.Error())
- return dexJarFile
- }
-
- stripRule.Build(pctx, ctx, "dexpreopt_strip", "dexpreopt strip")
-
- return strippedDexJarFile
+ return dexJarFile
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 043f9da..429bbdb 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -96,80 +96,9 @@
return targets
}
-// defaultBootImageConfig returns the bootImageConfig that will be used to dexpreopt modules. It is computed once the
-// first time it is called for any ctx.Config(), and returns the same slice for all future calls with the same
-// ctx.Config().
-func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
- return ctx.Config().Once(defaultBootImageConfigKey, func() interface{} {
- global := dexpreoptGlobalConfig(ctx)
-
- artModules := global.ArtApexJars
- nonFrameworkModules := concat(artModules, global.ProductUpdatableBootModules)
- frameworkModules := android.RemoveListFromList(global.BootJars, nonFrameworkModules)
-
- var nonUpdatableBootModules []string
- var nonUpdatableBootLocations []string
-
- for _, m := range artModules {
- nonUpdatableBootModules = append(nonUpdatableBootModules, m)
- nonUpdatableBootLocations = append(nonUpdatableBootLocations,
- filepath.Join("/apex/com.android.art/javalib", m+".jar"))
- }
-
- for _, m := range frameworkModules {
- nonUpdatableBootModules = append(nonUpdatableBootModules, m)
- nonUpdatableBootLocations = append(nonUpdatableBootLocations,
- filepath.Join("/system/framework", m+".jar"))
- }
-
- // The path to bootclasspath dex files needs to be known at module GenerateAndroidBuildAction time, before
- // the bootclasspath modules have been compiled. Set up known paths for them, the singleton rules will copy
- // them there.
- // TODO: use module dependencies instead
- var nonUpdatableBootDexPaths android.WritablePaths
- for _, m := range nonUpdatableBootModules {
- nonUpdatableBootDexPaths = append(nonUpdatableBootDexPaths,
- android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_input", m+".jar"))
- }
-
- dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars")
- symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_unstripped")
- zip := dir.Join(ctx, "boot.zip")
-
- targets := dexpreoptTargets(ctx)
-
- imageConfig := bootImageConfig{
- name: "boot",
- modules: nonUpdatableBootModules,
- dexLocations: nonUpdatableBootLocations,
- dexPaths: nonUpdatableBootDexPaths,
- dir: dir,
- symbolsDir: symbolsDir,
- images: make(map[android.ArchType]android.OutputPath),
- imagesDeps: make(map[android.ArchType]android.Paths),
- targets: targets,
- zip: zip,
- }
-
- for _, target := range targets {
- imageDir := dir.Join(ctx, "system/framework", target.Arch.ArchType.String())
- imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, "boot.art")
-
- imagesDeps := make([]android.Path, 0, len(imageConfig.modules)*3)
- for _, dep := range imageConfig.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex") {
- imagesDeps = append(imagesDeps, dep)
- }
- imageConfig.imagesDeps[target.Arch.ArchType] = imagesDeps
- }
-
- return imageConfig
- }).(bootImageConfig)
-}
-
-var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig")
-
-func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
- return ctx.Config().Once(apexBootImageConfigKey, func() interface{} {
+func getBootImageConfig(ctx android.PathContext, key android.OnceKey, name string,
+ needZip bool) bootImageConfig {
+ return ctx.Config().Once(key, func() interface{} {
global := dexpreoptGlobalConfig(ctx)
artModules := global.ArtApexJars
@@ -196,16 +125,21 @@
var bootDexPaths android.WritablePaths
for _, m := range imageModules {
bootDexPaths = append(bootDexPaths,
- android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars_input", m+".jar"))
+ android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_input", m+".jar"))
}
- dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars")
- symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_apexjars_unstripped")
+ dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars")
+ symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_"+name+"jars_unstripped")
+
+ var zip android.WritablePath
+ if needZip {
+ zip = dir.Join(ctx, name+".zip")
+ }
targets := dexpreoptTargets(ctx)
imageConfig := bootImageConfig{
- name: "apex",
+ name: name,
modules: imageModules,
dexLocations: bootLocations,
dexPaths: bootDexPaths,
@@ -214,11 +148,12 @@
targets: targets,
images: make(map[android.ArchType]android.OutputPath),
imagesDeps: make(map[android.ArchType]android.Paths),
+ zip: zip,
}
for _, target := range targets {
imageDir := dir.Join(ctx, "system/framework", target.Arch.ArchType.String())
- imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, "apex.art")
+ imageConfig.images[target.Arch.ArchType] = imageDir.Join(ctx, name+".art")
imagesDeps := make([]android.Path, 0, len(imageConfig.modules)*3)
for _, dep := range imageConfig.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex") {
@@ -231,8 +166,17 @@
}).(bootImageConfig)
}
+var defaultBootImageConfigKey = android.NewOnceKey("defaultBootImageConfig")
var apexBootImageConfigKey = android.NewOnceKey("apexBootImageConfig")
+func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
+ return getBootImageConfig(ctx, defaultBootImageConfigKey, "boot", true)
+}
+
+func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
+ return getBootImageConfig(ctx, apexBootImageConfigKey, "apex", false)
+}
+
func defaultBootclasspath(ctx android.PathContext) []string {
return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
global := dexpreoptGlobalConfig(ctx)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 3b581cb..12335ff 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1193,6 +1193,9 @@
jdiffDocZip android.WritablePath
jdiffStubsSrcJar android.WritablePath
+
+ metadataZip android.WritablePath
+ metadataDir android.WritablePath
}
// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
@@ -1304,7 +1307,8 @@
}
if Bool(d.properties.Write_sdk_values) {
- cmd.FlagWithArg("--sdk-values ", android.PathForModuleOut(ctx, "out").String())
+ d.metadataDir = android.PathForModuleOut(ctx, "metadata")
+ cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
}
if Bool(d.properties.Create_doc_stubs) {
@@ -1511,6 +1515,18 @@
FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
FlagWithArg("-C ", stubsDir.String()).
FlagWithArg("-D ", stubsDir.String())
+
+ if Bool(d.properties.Write_sdk_values) {
+ d.metadataZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-metadata.zip")
+ rule.Command().
+ BuiltTool(ctx, "soong_zip").
+ Flag("-write_if_changed").
+ Flag("-d").
+ FlagWithOutput("-o ", d.metadataZip).
+ FlagWithArg("-C ", d.metadataDir.String()).
+ FlagWithArg("-D ", d.metadataDir.String())
+ }
+
rule.Restat()
zipSyncCleanupCmd(rule, srcJarDir)
diff --git a/java/java_test.go b/java/java_test.go
index a3499cc..3767d1b 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1073,32 +1073,32 @@
}
func TestPatchModule(t *testing.T) {
- bp := `
- java_library {
- name: "foo",
- srcs: ["a.java"],
- }
-
- java_library {
- name: "bar",
- srcs: ["b.java"],
- sdk_version: "none",
- system_modules: "none",
- patch_module: "java.base",
- }
-
- java_library {
- name: "baz",
- srcs: ["c.java"],
- patch_module: "java.base",
- }
- `
-
t.Run("Java language level 8", func(t *testing.T) {
// Test with legacy javac -source 1.8 -target 1.8
- config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "false"})
- ctx := testContext(bp, nil)
- run(t, ctx, config)
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ java_version: "1.8",
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ patch_module: "java.base",
+ java_version: "1.8",
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["c.java"],
+ patch_module: "java.base",
+ java_version: "1.8",
+ }
+ `
+ ctx, _ := testJava(t, bp)
checkPatchModuleFlag(t, ctx, "foo", "")
checkPatchModuleFlag(t, ctx, "bar", "")
@@ -1107,6 +1107,26 @@
t.Run("Java language level 9", func(t *testing.T) {
// Test with default javac -source 9 -target 9
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ patch_module: "java.base",
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["c.java"],
+ patch_module: "java.base",
+ }
+ `
ctx, _ := testJava(t, bp)
checkPatchModuleFlag(t, ctx, "foo", "")
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 5e0e592..fd47d81 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -206,7 +206,7 @@
moduleType = testcase.moduleType
}
- bp := moduleType + ` {
+ props := `
name: "foo",
srcs: ["a.java"],
target: {
@@ -214,6 +214,10 @@
srcs: ["bar-doc/IFoo.aidl"],
},
},
+ `
+ bp := moduleType + " {" + props + testcase.properties + `
+ }`
+ bpJava8 := moduleType + " {" + props + `java_version: "1.8",
` + testcase.properties + `
}`
@@ -233,45 +237,64 @@
bootclasspath := convertModulesToPaths(testcase.bootclasspath)
classpath := convertModulesToPaths(testcase.classpath)
- bc := strings.Join(bootclasspath, ":")
- if bc != "" {
- bc = "-bootclasspath " + bc
+ bc := ""
+ var bcDeps []string
+ if len(bootclasspath) > 0 {
+ bc = "-bootclasspath " + strings.Join(bootclasspath, ":")
+ if bootclasspath[0] != `""` {
+ bcDeps = bootclasspath
+ }
}
- c := strings.Join(classpath, ":")
- if c != "" {
- c = "-classpath " + c
+ c := ""
+ if len(classpath) > 0 {
+ c = "-classpath " + strings.Join(classpath, ":")
}
+
system := ""
+ var systemDeps []string
if testcase.system == "none" {
system = "--system=none"
+ } else if testcase.system == "bootclasspath" {
+ system = bc
+ systemDeps = bcDeps
} else if testcase.system != "" {
system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system")
+ // The module-relative parts of these paths are hardcoded in system_modules.go:
+ systemDeps = []string{
+ filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "modules"),
+ filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "jrt-fs.jar"),
+ filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "release"),
+ }
}
- checkClasspath := func(t *testing.T, ctx *android.TestContext) {
+ checkClasspath := func(t *testing.T, ctx *android.TestContext, isJava8 bool) {
foo := ctx.ModuleForTests("foo", variant)
javac := foo.Rule("javac")
+ var deps []string
aidl := foo.MaybeRule("aidl")
+ if aidl.Rule != nil {
+ deps = append(deps, aidl.Output.String())
+ }
got := javac.Args["bootClasspath"]
- if got != bc {
- t.Errorf("bootclasspath expected %q != got %q", bc, got)
+ expected := ""
+ if isJava8 {
+ expected = bc
+ deps = append(deps, bcDeps...)
+ } else {
+ expected = system
+ deps = append(deps, systemDeps...)
+ }
+ if got != expected {
+ t.Errorf("bootclasspath expected %q != got %q", expected, got)
}
got = javac.Args["classpath"]
if got != c {
t.Errorf("classpath expected %q != got %q", c, got)
}
-
- var deps []string
- if aidl.Rule != nil {
- deps = append(deps, aidl.Output.String())
- }
- if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
- deps = append(deps, bootclasspath...)
- }
deps = append(deps, classpath...)
if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
@@ -281,17 +304,17 @@
// Test with legacy javac -source 1.8 -target 1.8
t.Run("Java language level 8", func(t *testing.T) {
- config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "false"})
+ config := testConfig(nil)
if testcase.unbundled {
config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
}
if testcase.pdk {
config.TestProductVariables.Pdk = proptools.BoolPtr(true)
}
- ctx := testContext(bp, nil)
+ ctx := testContext(bpJava8, nil)
run(t, ctx, config)
- checkClasspath(t, ctx)
+ checkClasspath(t, ctx, true /* isJava8 */)
if testcase.host != android.Host {
aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
@@ -314,21 +337,20 @@
ctx := testContext(bp, nil)
run(t, ctx, config)
- javac := ctx.ModuleForTests("foo", variant).Rule("javac")
- got := javac.Args["bootClasspath"]
- expected := system
- if testcase.system == "bootclasspath" {
- expected = bc
- }
- if got != expected {
- t.Errorf("bootclasspath expected %q != got %q", expected, got)
+ checkClasspath(t, ctx, false /* isJava8 */)
+
+ if testcase.host != android.Host {
+ aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
+
+ if g, w := aidl.RuleParams.Command, testcase.aidl+" -I."; !strings.Contains(g, w) {
+ t.Errorf("want aidl command to contain %q, got %q", w, g)
+ }
}
})
- // Test again with PLATFORM_VERSION_CODENAME=REL
- t.Run("REL", func(t *testing.T) {
- // TODO(b/115604102): This test should be rewritten with language level 9
- config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "false"})
+ // Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 8 -target 8
+ t.Run("REL + Java language level 8", func(t *testing.T) {
+ config := testConfig(nil)
config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("REL")
config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(true)
@@ -338,11 +360,13 @@
if testcase.pdk {
config.TestProductVariables.Pdk = proptools.BoolPtr(true)
}
- ctx := testContext(bp, nil)
+ ctx := testContext(bpJava8, nil)
run(t, ctx, config)
- checkClasspath(t, ctx)
+ checkClasspath(t, ctx, true /* isJava8 */)
})
+
+ // TODO(b/142896162): Add a with PLATFORM_VERSION_CODENAME=REL, javac -source 9 -target 9, when that all works.
})
}
diff --git a/rust/OWNERS b/rust/OWNERS
new file mode 100644
index 0000000..82713f9
--- /dev/null
+++ b/rust/OWNERS
@@ -0,0 +1,5 @@
+# Additional owner/reviewers for rust rules, including parent directory owners.
+per-file * = chh@google.com, ivanlozano@google.com, jeffv@google.com, srhines@google.com
+
+# Limited owners/reviewers of the whitelist.
+per-file whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/rust/config/whitelist.go b/rust/config/whitelist.go
index 4646264..8025bcf 100644
--- a/rust/config/whitelist.go
+++ b/rust/config/whitelist.go
@@ -2,7 +2,7 @@
var (
RustAllowedPaths = []string{
- "external/rust/crates",
+ "external/rust",
"external/crosvm",
"external/adhd",
}
diff --git a/rust/config/x86_darwin_host.go b/rust/config/x86_darwin_host.go
new file mode 100644
index 0000000..7cfc59c
--- /dev/null
+++ b/rust/config/x86_darwin_host.go
@@ -0,0 +1,81 @@
+// Copyright 2019 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.
+
+package config
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ DarwinRustFlags = []string{}
+ DarwinRustLinkFlags = []string{}
+ darwinX8664Rustflags = []string{}
+ darwinX8664Linkflags = []string{}
+)
+
+func init() {
+ registerToolchainFactory(android.Darwin, android.X86_64, darwinX8664ToolchainFactory)
+ pctx.StaticVariable("DarwinToolchainRustFlags", strings.Join(DarwinRustFlags, " "))
+ pctx.StaticVariable("DarwinToolchainLinkFlags", strings.Join(DarwinRustLinkFlags, " "))
+ pctx.StaticVariable("DarwinToolchainX8664RustFlags", strings.Join(darwinX8664Rustflags, " "))
+ pctx.StaticVariable("DarwinToolchainX8664LinkFlags", strings.Join(darwinX8664Linkflags, " "))
+
+}
+
+type toolchainDarwin struct {
+ toolchainRustFlags string
+ toolchainLinkFlags string
+}
+
+type toolchainDarwinX8664 struct {
+ toolchain64Bit
+ toolchainDarwin
+}
+
+func (toolchainDarwinX8664) Supported() bool {
+ return true
+}
+
+func (toolchainDarwinX8664) Bionic() bool {
+ return false
+}
+
+func (t *toolchainDarwinX8664) Name() string {
+ return "x86_64"
+}
+
+func (t *toolchainDarwinX8664) RustTriple() string {
+ return "x86_64-apple-darwin"
+}
+
+func (t *toolchainDarwin) ShlibSuffix() string {
+ return ".dylib"
+}
+
+func (t *toolchainDarwinX8664) ToolchainLinkFlags() string {
+ return "${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainX8664LinkFlags}"
+}
+
+func (t *toolchainDarwinX8664) ToolchainRustFlags() string {
+ return "${config.DarwinToolchainRustFlags} ${config.DarwinToolchainX8664RustFlags}"
+}
+
+func darwinX8664ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainDarwinX8664Singleton
+}
+
+var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{}
diff --git a/rust/rust.go b/rust/rust.go
index 4f5e7fb..707de4b 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -164,15 +164,11 @@
android.AddLoadHook(mod, func(ctx android.LoadHookContext) {
disableTargets := struct {
Target struct {
- Darwin struct {
- Enabled *bool
- }
Linux_bionic struct {
Enabled *bool
}
}
}{}
- disableTargets.Target.Darwin.Enabled = proptools.BoolPtr(false)
disableTargets.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
ctx.AppendProperties(&disableTargets)
diff --git a/scripts/archive_repack.sh b/scripts/archive_repack.sh
new file mode 100755
index 0000000..f09372d
--- /dev/null
+++ b/scripts/archive_repack.sh
@@ -0,0 +1,87 @@
+#!/bin/bash -e
+
+# Copyright 2019 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.
+
+# Script to extract and repack an archive with specified object files.
+# Inputs:
+# Environment:
+# CLANG_BIN: path to the clang bin directory
+# Arguments:
+# -i ${file}: input file
+# -o ${file}: output file
+# -d ${file}: deps file
+
+set -o pipefail
+
+OPTSTRING=d:i:o:
+
+usage() {
+ cat <<EOF
+Usage: archive_repack.sh [options] <objects to repack>
+
+OPTIONS:
+ -i <file>: input file
+ -o <file>: output file
+ -d <file>: deps file
+EOF
+ exit 1
+}
+
+while getopts $OPTSTRING opt; do
+ case "$opt" in
+ d) depsfile="${OPTARG}" ;;
+ i) infile="${OPTARG}" ;;
+ o) outfile="${OPTARG}" ;;
+ ?) usage ;;
+ esac
+done
+shift "$(($OPTIND -1))"
+
+if [ -z "${infile}" ]; then
+ echo "-i argument is required"
+ usage
+fi
+
+if [ -z "${outfile}" ]; then
+ echo "-o argument is required"
+ usage
+fi
+
+# Produce deps file
+if [ ! -z "${depsfile}" ]; then
+ cat <<EOF > "${depsfile}"
+${outfile}: ${infile} ${CLANG_BIN}/llvm-ar
+EOF
+fi
+
+# Get absolute path for outfile and llvm-ar.
+LLVM_AR="${PWD}/${CLANG_BIN}/llvm-ar"
+if [[ "$outfile" != /* ]]; then
+ outfile="${PWD}/${outfile}"
+fi
+
+tempdir="${outfile}.tmp"
+
+# Clean up any previous temporary files.
+rm -f "${outfile}"
+rm -rf "${tempdir}"
+
+# Do repack
+# We have to change working directory since ar only allows extracting to CWD.
+mkdir "${tempdir}"
+cp "${infile}" "${tempdir}/archive"
+cd "${tempdir}"
+"${LLVM_AR}" x "archive"
+"${LLVM_AR}" --format=gnu qc "${outfile}" "$@"
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 1af816b..1bd3c98 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -80,7 +80,6 @@
"diff": Allowed,
"dlv": Allowed,
"expr": Allowed,
- "find": Allowed,
"fuser": Allowed,
"getopt": Allowed,
"git": Allowed,