Move first/last unique elements utility functions to android package
Move firstUniqueElements to android.FirstUniqueStrings, lastUniqueElements to android.LastUniqueStrings, and lastUniquePaths to android.LastUniquePaths. Test: m checkbuild Change-Id: Ieac840405126c7f8f98afb4a4ef35c01a18fe7fb
This commit is contained in:
parent
ae88703df5
commit
b671544973
|
@ -67,6 +67,7 @@ bootstrap_go_package {
|
||||||
"android/expand_test.go",
|
"android/expand_test.go",
|
||||||
"android/paths_test.go",
|
"android/paths_test.go",
|
||||||
"android/prebuilt_test.go",
|
"android/prebuilt_test.go",
|
||||||
|
"android/util_test.go",
|
||||||
"android/variable_test.go",
|
"android/variable_test.go",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,8 +286,8 @@ func (p Paths) Strings() []string {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstUniqueElements returns all unique elements of a slice, keeping the first copy of each
|
// FirstUniquePaths returns all unique elements of a Paths, keeping the first copy of each. It
|
||||||
// modifies the slice contents in place, and returns a subslice of the original slice
|
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
|
||||||
func FirstUniquePaths(list Paths) Paths {
|
func FirstUniquePaths(list Paths) Paths {
|
||||||
k := 0
|
k := 0
|
||||||
outer:
|
outer:
|
||||||
|
@ -303,6 +303,24 @@ outer:
|
||||||
return list[:k]
|
return list[:k]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LastUniquePaths returns all unique elements of a Paths, keeping the last copy of each. It
|
||||||
|
// modifies the Paths slice contents in place, and returns a subslice of the original slice.
|
||||||
|
func LastUniquePaths(list Paths) Paths {
|
||||||
|
totalSkip := 0
|
||||||
|
for i := len(list) - 1; i >= totalSkip; i-- {
|
||||||
|
skip := 0
|
||||||
|
for j := i - 1; j >= totalSkip; j-- {
|
||||||
|
if list[i] == list[j] {
|
||||||
|
skip++
|
||||||
|
} else {
|
||||||
|
list[j+skip] = list[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalSkip += skip
|
||||||
|
}
|
||||||
|
return list[totalSkip:]
|
||||||
|
}
|
||||||
|
|
||||||
func indexPathList(s Path, list []Path) int {
|
func indexPathList(s Path, list []Path) int {
|
||||||
for i, l := range list {
|
for i, l := range list {
|
||||||
if l == s {
|
if l == s {
|
||||||
|
|
|
@ -77,6 +77,41 @@ func prefixInList(s string, list []string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
|
||||||
|
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
|
||||||
|
func FirstUniqueStrings(list []string) []string {
|
||||||
|
k := 0
|
||||||
|
outer:
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
for j := 0; j < k; j++ {
|
||||||
|
if list[i] == list[j] {
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list[k] = list[i]
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
return list[:k]
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastUniqueStrings returns all unique elements of a slice of strings, keeping the last copy of
|
||||||
|
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
|
||||||
|
func LastUniqueStrings(list []string) []string {
|
||||||
|
totalSkip := 0
|
||||||
|
for i := len(list) - 1; i >= totalSkip; i-- {
|
||||||
|
skip := 0
|
||||||
|
for j := i - 1; j >= totalSkip; j-- {
|
||||||
|
if list[i] == list[j] {
|
||||||
|
skip++
|
||||||
|
} else {
|
||||||
|
list[j+skip] = list[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalSkip += skip
|
||||||
|
}
|
||||||
|
return list[totalSkip:]
|
||||||
|
}
|
||||||
|
|
||||||
// checkCalledFromInit panics if a Go package's init function is not on the
|
// checkCalledFromInit panics if a Go package's init function is not on the
|
||||||
// call stack.
|
// call stack.
|
||||||
func checkCalledFromInit() {
|
func checkCalledFromInit() {
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
// 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 android
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var firstUniqueStringsTestCases = []struct {
|
||||||
|
in []string
|
||||||
|
out []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: []string{"a"},
|
||||||
|
out: []string{"a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "b"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "a"},
|
||||||
|
out: []string{"a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "b", "a"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"b", "a", "a"},
|
||||||
|
out: []string{"b", "a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "a", "b"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "b", "a", "b"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
|
||||||
|
out: []string{"liblog", "libdl", "libc++", "libc", "libm"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirstUniqueStrings(t *testing.T) {
|
||||||
|
for _, testCase := range firstUniqueStringsTestCases {
|
||||||
|
out := FirstUniqueStrings(testCase.in)
|
||||||
|
if !reflect.DeepEqual(out, testCase.out) {
|
||||||
|
t.Errorf("incorrect output:")
|
||||||
|
t.Errorf(" input: %#v", testCase.in)
|
||||||
|
t.Errorf(" expected: %#v", testCase.out)
|
||||||
|
t.Errorf(" got: %#v", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastUniqueStringsTestCases = []struct {
|
||||||
|
in []string
|
||||||
|
out []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: []string{"a"},
|
||||||
|
out: []string{"a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "b"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "a"},
|
||||||
|
out: []string{"a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "b", "a"},
|
||||||
|
out: []string{"b", "a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"b", "a", "a"},
|
||||||
|
out: []string{"b", "a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "a", "b"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"a", "b", "a", "b"},
|
||||||
|
out: []string{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
|
||||||
|
out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLastUniqueStrings(t *testing.T) {
|
||||||
|
for _, testCase := range lastUniqueStringsTestCases {
|
||||||
|
out := LastUniqueStrings(testCase.in)
|
||||||
|
if !reflect.DeepEqual(out, testCase.out) {
|
||||||
|
t.Errorf("incorrect output:")
|
||||||
|
t.Errorf(" input: %#v", testCase.in)
|
||||||
|
t.Errorf(" expected: %#v", testCase.out)
|
||||||
|
t.Errorf(" got: %#v", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
cc/cc.go
72
cc/cc.go
|
@ -561,7 +561,7 @@ func orderDeps(directDeps []android.Path, transitiveDeps map[android.Path][]andr
|
||||||
orderedAllDeps = append(orderedAllDeps, transitiveDeps[dep]...)
|
orderedAllDeps = append(orderedAllDeps, transitiveDeps[dep]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
orderedAllDeps = lastUniquePaths(orderedAllDeps)
|
orderedAllDeps = android.LastUniquePaths(orderedAllDeps)
|
||||||
|
|
||||||
// We don't want to add any new dependencies into directDeps (to allow the caller to
|
// We don't want to add any new dependencies into directDeps (to allow the caller to
|
||||||
// intentionally exclude or replace any unwanted transitive dependencies), so we limit the
|
// intentionally exclude or replace any unwanted transitive dependencies), so we limit the
|
||||||
|
@ -763,12 +763,12 @@ func (c *Module) deps(ctx DepsContext) Deps {
|
||||||
deps = feature.deps(ctx, deps)
|
deps = feature.deps(ctx, deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
deps.WholeStaticLibs = lastUniqueElements(deps.WholeStaticLibs)
|
deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
|
||||||
deps.StaticLibs = lastUniqueElements(deps.StaticLibs)
|
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
|
||||||
deps.LateStaticLibs = lastUniqueElements(deps.LateStaticLibs)
|
deps.LateStaticLibs = android.LastUniqueStrings(deps.LateStaticLibs)
|
||||||
deps.SharedLibs = lastUniqueElements(deps.SharedLibs)
|
deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
|
||||||
deps.LateSharedLibs = lastUniqueElements(deps.LateSharedLibs)
|
deps.LateSharedLibs = android.LastUniqueStrings(deps.LateSharedLibs)
|
||||||
deps.HeaderLibs = lastUniqueElements(deps.HeaderLibs)
|
deps.HeaderLibs = android.LastUniqueStrings(deps.HeaderLibs)
|
||||||
|
|
||||||
for _, lib := range deps.ReexportSharedLibHeaders {
|
for _, lib := range deps.ReexportSharedLibHeaders {
|
||||||
if !inList(lib, deps.SharedLibs) {
|
if !inList(lib, deps.SharedLibs) {
|
||||||
|
@ -1249,13 +1249,13 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||||
depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps)...)
|
depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps)...)
|
||||||
|
|
||||||
// Dedup exported flags from dependencies
|
// Dedup exported flags from dependencies
|
||||||
depPaths.Flags = firstUniqueElements(depPaths.Flags)
|
depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
|
||||||
depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
|
depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
|
||||||
depPaths.ReexportedFlags = firstUniqueElements(depPaths.ReexportedFlags)
|
depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
|
||||||
depPaths.ReexportedFlagsDeps = android.FirstUniquePaths(depPaths.ReexportedFlagsDeps)
|
depPaths.ReexportedFlagsDeps = android.FirstUniquePaths(depPaths.ReexportedFlagsDeps)
|
||||||
|
|
||||||
if c.sabi != nil {
|
if c.sabi != nil {
|
||||||
c.sabi.Properties.ReexportedIncludeFlags = firstUniqueElements(c.sabi.Properties.ReexportedIncludeFlags)
|
c.sabi.Properties.ReexportedIncludeFlags = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludeFlags)
|
||||||
}
|
}
|
||||||
|
|
||||||
return depPaths
|
return depPaths
|
||||||
|
@ -1438,58 +1438,6 @@ func vendorMutator(mctx android.BottomUpMutatorContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// firstUniqueElements returns all unique elements of a slice, keeping the first copy of each
|
|
||||||
// modifies the slice contents in place, and returns a subslice of the original slice
|
|
||||||
func firstUniqueElements(list []string) []string {
|
|
||||||
k := 0
|
|
||||||
outer:
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
for j := 0; j < k; j++ {
|
|
||||||
if list[i] == list[j] {
|
|
||||||
continue outer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list[k] = list[i]
|
|
||||||
k++
|
|
||||||
}
|
|
||||||
return list[:k]
|
|
||||||
}
|
|
||||||
|
|
||||||
// lastUniqueElements returns all unique elements of a slice, keeping the last copy of each.
|
|
||||||
// It modifies the slice contents in place, and returns a subslice of the original slice
|
|
||||||
func lastUniqueElements(list []string) []string {
|
|
||||||
totalSkip := 0
|
|
||||||
for i := len(list) - 1; i >= totalSkip; i-- {
|
|
||||||
skip := 0
|
|
||||||
for j := i - 1; j >= totalSkip; j-- {
|
|
||||||
if list[i] == list[j] {
|
|
||||||
skip++
|
|
||||||
} else {
|
|
||||||
list[j+skip] = list[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
totalSkip += skip
|
|
||||||
}
|
|
||||||
return list[totalSkip:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// lastUniquePaths is the same as lastUniqueElements but uses Path structs
|
|
||||||
func lastUniquePaths(list []android.Path) []android.Path {
|
|
||||||
totalSkip := 0
|
|
||||||
for i := len(list) - 1; i >= totalSkip; i-- {
|
|
||||||
skip := 0
|
|
||||||
for j := i - 1; j >= totalSkip; j-- {
|
|
||||||
if list[i] == list[j] {
|
|
||||||
skip++
|
|
||||||
} else {
|
|
||||||
list[j+skip] = list[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
totalSkip += skip
|
|
||||||
}
|
|
||||||
return list[totalSkip:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
|
func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
|
||||||
if ctx.AConfig().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt {
|
if ctx.AConfig().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt {
|
||||||
return strconv.Itoa(config.NdkMaxPrebuiltVersionInt)
|
return strconv.Itoa(config.NdkMaxPrebuiltVersionInt)
|
||||||
|
|
100
cc/cc_test.go
100
cc/cc_test.go
|
@ -156,106 +156,6 @@ func TestVendorSrc(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstUniqueElementsTestCases = []struct {
|
|
||||||
in []string
|
|
||||||
out []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
in: []string{"a"},
|
|
||||||
out: []string{"a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "b"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "a"},
|
|
||||||
out: []string{"a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "b", "a"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"b", "a", "a"},
|
|
||||||
out: []string{"b", "a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "a", "b"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "b", "a", "b"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
|
|
||||||
out: []string{"liblog", "libdl", "libc++", "libc", "libm"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFirstUniqueElements(t *testing.T) {
|
|
||||||
for _, testCase := range firstUniqueElementsTestCases {
|
|
||||||
out := firstUniqueElements(testCase.in)
|
|
||||||
if !reflect.DeepEqual(out, testCase.out) {
|
|
||||||
t.Errorf("incorrect output:")
|
|
||||||
t.Errorf(" input: %#v", testCase.in)
|
|
||||||
t.Errorf(" expected: %#v", testCase.out)
|
|
||||||
t.Errorf(" got: %#v", out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastUniqueElementsTestCases = []struct {
|
|
||||||
in []string
|
|
||||||
out []string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
in: []string{"a"},
|
|
||||||
out: []string{"a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "b"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "a"},
|
|
||||||
out: []string{"a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "b", "a"},
|
|
||||||
out: []string{"b", "a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"b", "a", "a"},
|
|
||||||
out: []string{"b", "a"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "a", "b"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"a", "b", "a", "b"},
|
|
||||||
out: []string{"a", "b"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
in: []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
|
|
||||||
out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLastUniqueElements(t *testing.T) {
|
|
||||||
for _, testCase := range lastUniqueElementsTestCases {
|
|
||||||
out := lastUniqueElements(testCase.in)
|
|
||||||
if !reflect.DeepEqual(out, testCase.out) {
|
|
||||||
t.Errorf("incorrect output:")
|
|
||||||
t.Errorf(" input: %#v", testCase.in)
|
|
||||||
t.Errorf(" expected: %#v", testCase.out)
|
|
||||||
t.Errorf(" got: %#v", out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
str11 = "01234567891"
|
str11 = "01234567891"
|
||||||
str10 = str11[:10]
|
str10 = str11[:10]
|
||||||
|
|
Loading…
Reference in New Issue