Merge "Switch to clang-r349610"
diff --git a/Android.bp b/Android.bp
index 3215fa2..a70f73c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -61,6 +61,7 @@
"android/prebuilt_etc.go",
"android/proto.go",
"android/register.go",
+ "android/sh_binary.go",
"android/singleton.go",
"android/testing.go",
"android/util.go",
diff --git a/OWNERS b/OWNERS
index 7983c19..85c70df 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,4 +3,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 apex.go = jiyong@google.com
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index 46d128e..42c7c2c 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -125,7 +125,8 @@
p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
- // This ensures that outputFilePath has the same name as this module.
+ // This ensures that outputFilePath has the correct name for others to
+ // use, as the source file may have a different name.
ctx.Build(pctx, BuildParams{
Rule: Cp,
Output: p.outputFilePath,
diff --git a/android/sh_binary.go b/android/sh_binary.go
new file mode 100644
index 0000000..3915193
--- /dev/null
+++ b/android/sh_binary.go
@@ -0,0 +1,141 @@
+// 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.
+
+package android
+
+import (
+ "fmt"
+ "io"
+)
+
+// sh_binary is for shell scripts (and batch files) that are installed as
+// executable files into .../bin/
+//
+// Do not use them for prebuilt C/C++/etc files. Use cc_prebuilt_binary
+// instead.
+
+func init() {
+ RegisterModuleType("sh_binary", ShBinaryFactory)
+ RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
+}
+
+type shBinaryProperties struct {
+ // Source file of this prebuilt.
+ Src *string `android:"arch_variant"`
+
+ // optional subdirectory under which this file is installed into
+ Sub_dir *string `android:"arch_variant"`
+
+ // optional name for the installed file. If unspecified, name of the module is used as the file name
+ Filename *string `android:"arch_variant"`
+
+ // when set to true, and filename property is not set, the name for the installed file
+ // is the same as the file name of the source file.
+ Filename_from_src *bool `android:"arch_variant"`
+
+ // Whether this module is directly installable to one of the partitions. Default: true.
+ Installable *bool
+}
+
+type ShBinary struct {
+ ModuleBase
+
+ properties shBinaryProperties
+
+ sourceFilePath Path
+ outputFilePath OutputPath
+}
+
+func (s *ShBinary) DepsMutator(ctx BottomUpMutatorContext) {
+ if s.properties.Src == nil {
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ }
+
+ // To support ":modulename" in src
+ ExtractSourceDeps(ctx, s.properties.Src)
+}
+
+func (s *ShBinary) SourceFilePath(ctx ModuleContext) Path {
+ return ctx.ExpandSource(String(s.properties.Src), "src")
+}
+
+func (s *ShBinary) OutputFile() OutputPath {
+ return s.outputFilePath
+}
+
+func (s *ShBinary) SubDir() string {
+ return String(s.properties.Sub_dir)
+}
+
+func (s *ShBinary) Installable() bool {
+ return s.properties.Installable == nil || Bool(s.properties.Installable)
+}
+
+func (s *ShBinary) GenerateAndroidBuildActions(ctx ModuleContext) {
+ s.sourceFilePath = ctx.ExpandSource(String(s.properties.Src), "src")
+ filename := String(s.properties.Filename)
+ filename_from_src := Bool(s.properties.Filename_from_src)
+ if filename == "" {
+ if filename_from_src {
+ filename = s.sourceFilePath.Base()
+ } else {
+ filename = ctx.ModuleName()
+ }
+ } else if filename_from_src {
+ ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
+ return
+ }
+ s.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
+
+ // This ensures that outputFilePath has the correct name for others to
+ // use, as the source file may have a different name.
+ ctx.Build(pctx, BuildParams{
+ Rule: CpExecutable,
+ Output: s.outputFilePath,
+ Input: s.sourceFilePath,
+ })
+}
+
+func (s *ShBinary) AndroidMk() AndroidMkData {
+ return AndroidMkData{
+ Class: "EXECUTABLES",
+ OutputFile: OptionalPathForPath(s.outputFilePath),
+ Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
+ Extra: []AndroidMkExtraFunc{
+ func(w io.Writer, outputFile Path) {
+ fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", String(s.properties.Sub_dir))
+ fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX :=")
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", s.outputFilePath.Rel())
+ },
+ },
+ }
+}
+
+func InitShBinaryModule(s *ShBinary) {
+ s.AddProperties(&s.properties)
+}
+
+func ShBinaryFactory() Module {
+ module := &ShBinary{}
+ InitShBinaryModule(module)
+ InitAndroidArchModule(module, HostAndDeviceSupported, MultilibFirst)
+ return module
+}
+
+func ShBinaryHostFactory() Module {
+ module := &ShBinary{}
+ InitShBinaryModule(module)
+ InitAndroidArchModule(module, HostSupported, MultilibFirst)
+ return module
+}
diff --git a/apex/OWNERS b/apex/OWNERS
new file mode 100644
index 0000000..a382ae8
--- /dev/null
+++ b/apex/OWNERS
@@ -0,0 +1 @@
+per-file * = jiyong@google.com
\ No newline at end of file
diff --git a/apex/apex.go b/apex/apex.go
index 96a4bd5..f6daf9b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -177,6 +177,29 @@
}
}
+type apexNativeDependencies struct {
+ // List of native libraries
+ Native_shared_libs []string
+ // List of native executables
+ Binaries []string
+}
+type apexMultilibProperties struct {
+ // Native dependencies whose compile_multilib is "first"
+ First apexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "both"
+ Both apexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "prefer32"
+ Prefer32 apexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "32"
+ Lib32 apexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "64"
+ Lib64 apexNativeDependencies
+}
+
type apexBundleProperties struct {
// Json manifest file describing meta info of this APEX bundle. Default:
// "apex_manifest.json"
@@ -218,36 +241,29 @@
// Default is false.
Use_vendor *bool
- Multilib struct {
- First struct {
- // List of native libraries whose compile_multilib is "first"
- Native_shared_libs []string
- // List of native executables whose compile_multilib is "first"
- Binaries []string
+ // For telling the apex to ignore special handling for system libraries such as bionic. Default is false.
+ Ignore_system_library_special_case *bool
+
+ Multilib apexMultilibProperties
+}
+
+type apexTargetBundleProperties struct {
+ Target struct {
+ // Multilib properties only for android.
+ Android struct {
+ Multilib apexMultilibProperties
}
- Both struct {
- // List of native libraries whose compile_multilib is "both"
- Native_shared_libs []string
- // List of native executables whose compile_multilib is "both"
- Binaries []string
+ // Multilib properties only for host.
+ Host struct {
+ Multilib apexMultilibProperties
}
- Prefer32 struct {
- // List of native libraries whose compile_multilib is "prefer32"
- Native_shared_libs []string
- // List of native executables whose compile_multilib is "prefer32"
- Binaries []string
+ // Multilib properties only for host linux_bionic.
+ Linux_bionic struct {
+ Multilib apexMultilibProperties
}
- Lib32 struct {
- // List of native libraries whose compile_multilib is "32"
- Native_shared_libs []string
- // List of native executables whose compile_multilib is "32"
- Binaries []string
- }
- Lib64 struct {
- // List of native libraries whose compile_multilib is "64"
- Native_shared_libs []string
- // List of native executables whose compile_multilib is "64"
- Binaries []string
+ // Multilib properties only for host linux_glibc.
+ Linux_glibc struct {
+ Multilib apexMultilibProperties
}
}
}
@@ -329,7 +345,6 @@
type apexFile struct {
builtFile android.Path
moduleName string
- archType android.ArchType
installDir string
class apexFileClass
module android.Module
@@ -340,7 +355,8 @@
android.ModuleBase
android.DefaultableModuleBase
- properties apexBundleProperties
+ properties apexBundleProperties
+ targetProperties apexTargetBundleProperties
apexTypes apexPackaging
@@ -373,9 +389,26 @@
}, executableTag, binaries...)
}
+func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
+ if ctx.Os().Class == android.Device {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
+ } else {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil)
+ if ctx.Os().Bionic() {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil)
+ } else {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil)
+ }
+ }
+}
+
func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+
targets := ctx.MultiTargets()
config := ctx.DeviceConfig()
+
+ a.combineProperties(ctx)
+
has32BitTarget := false
for _, target := range targets {
if target.Arch.ArchType.Multilib == "lib32" {
@@ -498,7 +531,7 @@
return android.InList(sanitizerName, globalSanitizerNames)
}
-func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
+func getCopyManifestForNativeLibrary(cc *cc.Module, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
// Decide the APEX-local directory by the multilib of the library
// In the future, we may query this to the module.
switch cc.Arch().ArchType.Multilib {
@@ -510,18 +543,20 @@
if !cc.Arch().Native {
dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
}
- switch cc.Name() {
- case "libc", "libm", "libdl":
- // Special case for bionic libs. This is to prevent the bionic libs
- // from being included in the search path /apex/com.android.apex/lib.
- // This exclusion is required because bionic libs in the runtime APEX
- // are available via the legacy paths /system/lib/libc.so, etc. By the
- // init process, the bionic libs in the APEX are bind-mounted to the
- // legacy paths and thus will be loaded into the default linker namespace.
- // If the bionic libs are directly in /apex/com.android.apex/lib then
- // the same libs will be again loaded to the runtime linker namespace,
- // which will result double loading of bionic libs that isn't supported.
- dirInApex = filepath.Join(dirInApex, "bionic")
+ if handleSpecialLibs {
+ switch cc.Name() {
+ case "libc", "libm", "libdl":
+ // Special case for bionic libs. This is to prevent the bionic libs
+ // from being included in the search path /apex/com.android.apex/lib.
+ // This exclusion is required because bionic libs in the runtime APEX
+ // are available via the legacy paths /system/lib/libc.so, etc. By the
+ // init process, the bionic libs in the APEX are bind-mounted to the
+ // legacy paths and thus will be loaded into the default linker namespace.
+ // If the bionic libs are directly in /apex/com.android.apex/lib then
+ // the same libs will be again loaded to the runtime linker namespace,
+ // which will result double loading of bionic libs that isn't supported.
+ dirInApex = filepath.Join(dirInApex, "bionic")
+ }
}
fileToCopy = cc.OutputFile().Path()
@@ -564,6 +599,8 @@
return
}
+ handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
+
ctx.WalkDeps(func(child, parent android.Module) bool {
if _, ok := parent.(*apexBundle); ok {
// direct dependencies
@@ -572,8 +609,8 @@
switch depTag {
case sharedLibTag:
if cc, ok := child.(*cc.Module); ok {
- fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
- filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc, nil})
+ fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
return true
} else {
ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
@@ -586,7 +623,7 @@
return true
}
fileToCopy, dirInApex := getCopyManifestForExecutable(cc)
- filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeExecutable, cc, cc.Symlinks()})
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeExecutable, cc, cc.Symlinks()})
return true
} else {
ctx.PropertyErrorf("binaries", "%q is not a cc_binary module", depName)
@@ -597,7 +634,7 @@
if fileToCopy == nil {
ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
} else {
- filesInfo = append(filesInfo, apexFile{fileToCopy, depName, java.Arch().ArchType, dirInApex, javaSharedLib, java, nil})
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, javaSharedLib, java, nil})
}
return true
} else {
@@ -606,7 +643,7 @@
case prebuiltTag:
if prebuilt, ok := child.(*android.PrebuiltEtc); ok {
fileToCopy, dirInApex := getCopyManifestForPrebuiltEtc(prebuilt)
- filesInfo = append(filesInfo, apexFile{fileToCopy, depName, prebuilt.Arch().ArchType, dirInApex, etc, prebuilt, nil})
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, etc, prebuilt, nil})
return true
} else {
ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
@@ -640,8 +677,8 @@
return false
}
depName := ctx.OtherModuleName(child)
- fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
- filesInfo = append(filesInfo, apexFile{fileToCopy, depName, cc.Arch().ArchType, dirInApex, nativeSharedLib, cc, nil})
+ fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
+ filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
return true
}
}
@@ -888,7 +925,7 @@
Input: manifest,
Output: copiedManifest,
})
- a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc, nil, nil})
+ a.filesInfo = append(a.filesInfo, apexFile{copiedManifest, ctx.ModuleName() + ".apex_manifest.json", ".", etc, nil, nil})
for _, fi := range a.filesInfo {
dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
@@ -914,57 +951,92 @@
}
func (a *apexBundle) androidMkForType(apexType apexPackaging) android.AndroidMkData {
- // Only image APEXes can be flattened.
- if a.flattened && apexType.image() {
- return android.AndroidMkData{
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- moduleNames := []string{}
- for _, fi := range a.filesInfo {
- if !android.InList(fi.moduleName, moduleNames) {
- moduleNames = append(moduleNames, fi.moduleName)
+ return android.AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ moduleNames := []string{}
+ for _, fi := range a.filesInfo {
+ if !android.InList(fi.moduleName, moduleNames) {
+ moduleNames = append(moduleNames, fi.moduleName)
+ }
+ }
+
+ for _, fi := range a.filesInfo {
+ if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
+ continue
+ }
+ fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
+ fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+ fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
+ if a.flattened {
+ // /system/apex/<name>/{lib|framework|...}
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)",
+ a.installDir.RelPathString(), name, fi.installDir))
+ } else {
+ // /apex/<name>/{lib|framework|...}
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(PRODUCT_OUT)",
+ "apex", name, fi.installDir))
+ }
+ fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
+ fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.NameInMake())
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
+ if fi.module != nil {
+ archStr := fi.module.Target().Arch.ArchType.String()
+ host := false
+ switch fi.module.Target().Os.Class {
+ case android.Host:
+ if archStr != "common" {
+ fmt.Fprintln(w, "LOCAL_MODULE_HOST_ARCH :=", archStr)
+ }
+ host = true
+ case android.HostCross:
+ if archStr != "common" {
+ fmt.Fprintln(w, "LOCAL_MODULE_HOST_CROSS_ARCH :=", archStr)
+ }
+ host = true
+ case android.Device:
+ if archStr != "common" {
+ fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
+ }
+ }
+ if host {
+ makeOs := fi.module.Target().Os.String()
+ if fi.module.Target().Os == android.Linux || fi.module.Target().Os == android.LinuxBionic {
+ makeOs = "linux"
+ }
+ fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", makeOs)
+ fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
}
}
+ if fi.class == javaSharedLib {
+ javaModule := fi.module.(*java.Library)
+ // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
+ // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
+ // we will have foo.jar.jar
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".jar"))
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
+ fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
+ fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
+ } else if fi.class == nativeSharedLib || fi.class == nativeExecutable {
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
+ if cc, ok := fi.module.(*cc.Module); ok && cc.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", cc.UnstrippedOutputFile().String())
+ }
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
+ } else {
+ fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
+ fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
+ }
+ }
+ if a.flattened && apexType.image() {
+ // Only image APEXes can be flattened.
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
-
- for _, fi := range a.filesInfo {
- if cc, ok := fi.module.(*cc.Module); ok && cc.Properties.HideFromMake {
- continue
- }
- fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
- fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
- fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName)
- fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString(), name, fi.installDir))
- fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
- fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.NameInMake())
- fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
- archStr := fi.archType.String()
- if archStr != "common" {
- fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
- }
- if fi.class == javaSharedLib {
- javaModule := fi.module.(*java.Library)
- // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
- // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
- // we will have foo.jar.jar
- fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".jar"))
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
- fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
- fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
- fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
- } else {
- fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
- fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
- }
- }
- }}
- } else {
- return android.AndroidMkData{
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ } else {
// zip-apex is the less common type so have the name refer to the image-apex
// only and use {name}.zip if you want the zip-apex
if apexType == zipApex && a.apexTypes == both {
@@ -979,13 +1051,14 @@
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+apexType.suffix())
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
+ fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(moduleNames, " "))
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
if apexType == imageApex {
fmt.Fprintln(w, "ALL_MODULES.$(LOCAL_MODULE).BUNDLE :=", a.bundleModuleFile.String())
}
- }}
- }
+ }
+ }}
}
func ApexBundleFactory() android.Module {
@@ -993,6 +1066,7 @@
outputFiles: map[apexPackaging]android.WritablePath{},
}
module.AddProperties(&module.properties)
+ module.AddProperties(&module.targetProperties)
module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
})
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7ae49f6..9d33060 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -864,3 +864,83 @@
// Ensure that the include path of the header lib is exported to 'otherlib'
ensureContains(t, cFlags, "-Imy_include")
}
+
+func TestApexWithTarget(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ multilib: {
+ first: {
+ native_shared_libs: ["mylib_common"],
+ }
+ },
+ target: {
+ android: {
+ multilib: {
+ first: {
+ native_shared_libs: ["mylib"],
+ }
+ }
+ },
+ host: {
+ multilib: {
+ first: {
+ native_shared_libs: ["mylib2"],
+ }
+ }
+ }
+ }
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "mylib_common",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ compile_multilib: "first",
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ compile_multilib: "first",
+ }
+ `)
+
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+
+ // Ensure that main rule creates an output
+ ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
+
+ // Ensure that apex variant is created for the direct dep
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex")
+
+ // Ensure that both direct and indirect deps are copied into apex
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+ ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
+ ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+
+ // Ensure that the platform variant ends with _core_shared
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared")
+ ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared")
+}
diff --git a/cc/binary.go b/cc/binary.go
index 4c86371..a8eb641 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -249,7 +249,11 @@
} else {
switch ctx.Os() {
case android.Android:
- flags.DynamicLinker = "/system/bin/linker"
+ if ctx.bootstrap() {
+ flags.DynamicLinker = "/system/bin/bootstrap/linker"
+ } else {
+ flags.DynamicLinker = "/system/bin/linker"
+ }
if flags.Toolchain.Is64Bit() {
flags.DynamicLinker += "64"
}
@@ -401,6 +405,10 @@
return ret
}
+func (binary *binaryDecorator) unstrippedOutputFilePath() android.Path {
+ return binary.unstrippedOutputFile
+}
+
func (binary *binaryDecorator) symlinkList() []string {
return binary.symlinks
}
diff --git a/cc/builder.go b/cc/builder.go
index b012d6f..645b3c2 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -663,18 +663,33 @@
// Generate a rule to combine .dump sAbi dump files from multiple source files
// into a single .ldump sAbi dump file
func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
- baseName, exportedHeaderFlags string) android.OptionalPath {
+ baseName, exportedHeaderFlags string, symbolFile android.OptionalPath,
+ excludedSymbolVersions, excludedSymbolTags []string) android.OptionalPath {
+
outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
sabiLock.Lock()
lsdumpPaths = append(lsdumpPaths, outputFile.String())
sabiLock.Unlock()
+
+ implicits := android.Paths{soFile}
symbolFilterStr := "-so " + soFile.String()
+
+ if symbolFile.Valid() {
+ implicits = append(implicits, symbolFile.Path())
+ symbolFilterStr += " -v " + symbolFile.String()
+ }
+ for _, ver := range excludedSymbolVersions {
+ symbolFilterStr += " --exclude-symbol-version " + ver
+ }
+ for _, tag := range excludedSymbolTags {
+ symbolFilterStr += " --exclude-symbol-tag " + tag
+ }
ctx.Build(pctx, android.BuildParams{
Rule: sAbiLink,
Description: "header-abi-linker " + outputFile.Base(),
Output: outputFile,
Inputs: sAbiDumps,
- Implicit: soFile,
+ Implicits: implicits,
Args: map[string]string{
"symbolFilter": symbolFilterStr,
"arch": ctx.Arch().ArchType.Name,
diff --git a/cc/cc.go b/cc/cc.go
index a30708a..4c26e60 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -261,6 +261,7 @@
apexName() string
hasStubsVariants() bool
isStubs() bool
+ bootstrap() bool
}
type ModuleContext interface {
@@ -305,6 +306,7 @@
link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
appendLdflags([]string)
+ unstrippedOutputFilePath() android.Path
}
type installer interface {
@@ -404,6 +406,13 @@
return c.outputFile
}
+func (c *Module) UnstrippedOutputFile() android.Path {
+ if c.linker != nil {
+ return c.linker.unstrippedOutputFilePath()
+ }
+ return nil
+}
+
func (c *Module) Init() android.Module {
c.AddProperties(&c.Properties, &c.VendorProperties)
if c.compiler != nil {
@@ -562,6 +571,10 @@
return false
}
+func (c *Module) bootstrap() bool {
+ return Bool(c.Properties.Bootstrap)
+}
+
type baseModuleContext struct {
android.BaseContext
moduleContextImpl
@@ -732,6 +745,10 @@
return ctx.mod.IsStubs()
}
+func (ctx *moduleContextImpl) bootstrap() bool {
+ return ctx.mod.bootstrap()
+}
+
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
return &Module{
hod: hod,
@@ -1166,15 +1183,9 @@
depTag = headerExportDepTag
}
if buildStubs {
- imageVariation := "core"
- if c.useVndk() {
- imageVariation = "vendor"
- } else if c.inRecovery() {
- imageVariation = "recovery"
- }
actx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "arch", Variation: ctx.Target().String()},
- {Mutator: "image", Variation: imageVariation},
+ {Mutator: "image", Variation: c.imageVariation()},
}, depTag, lib)
} else {
actx.AddVariationDependencies(nil, depTag, lib)
@@ -1550,7 +1561,7 @@
// If not building for APEX, use stubs only when it is from
// an APEX (and not from platform)
useThisDep = (depInPlatform != depIsStubs)
- if c.inRecovery() || Bool(c.Properties.Bootstrap) {
+ if c.inRecovery() || c.bootstrap() {
// However, for recovery or bootstrap modules,
// always link to non-stub variant
useThisDep = !depIsStubs
@@ -1836,6 +1847,16 @@
return false
}
+func (c *Module) imageVariation() string {
+ variation := "core"
+ if c.useVndk() {
+ variation = "vendor"
+ } else if c.inRecovery() {
+ variation = "recovery"
+ }
+ return variation
+}
+
//
// Defaults
//
diff --git a/cc/library.go b/cc/library.go
index ad07db4..13acfae 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -87,6 +87,19 @@
// binaries would be installed by default (in PRODUCT_PACKAGES) the other library will be removed
// from PRODUCT_PACKAGES.
Overrides []string
+
+ // Properties for ABI compatibility checker
+ Header_abi_checker struct {
+ // Path to a symbol file that specifies the symbols to be included in the generated
+ // ABI dump file
+ Symbol_file *string
+
+ // Symbol versions that should be ignored from the symbol file
+ Exclude_symbol_versions []string
+
+ // Symbol tags that should be ignored from the symbol file
+ Exclude_symbol_tags []string
+ }
}
type LibraryMutatedProperties struct {
@@ -567,11 +580,15 @@
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs)
}
if ctx.inRecovery() {
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Recovery.Exclude_shared_libs)
deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
+ deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, library.baseLinker.Properties.Target.Recovery.Exclude_shared_libs)
+ deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs)
}
android.ExtractSourceDeps(ctx, library.Properties.Unexported_symbols_list)
@@ -723,6 +740,10 @@
return ret
}
+func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
+ return library.unstrippedOutputFile
+}
+
func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path {
isLlndk := inList(ctx.baseModuleName(), llndkLibraries) || inList(ctx.baseModuleName(), ndkMigratedLibs)
@@ -760,7 +781,10 @@
SourceAbiFlags = append(SourceAbiFlags, reexportedInclude)
}
exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
- library.sAbiOutputFile = TransformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags)
+ library.sAbiOutputFile = TransformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
+ android.OptionalPathForModuleSrc(ctx, library.Properties.Header_abi_checker.Symbol_file),
+ library.Properties.Header_abi_checker.Exclude_symbol_versions,
+ library.Properties.Header_abi_checker.Exclude_symbol_tags)
refAbiDumpFile := getRefAbiDumpFile(ctx, vndkVersion, fileName)
if refAbiDumpFile != nil {
@@ -867,6 +891,18 @@
library.baseInstaller.subDir += "-" + vndkVersion
}
}
+ } else if len(library.Properties.Stubs.Versions) > 0 && android.DirectlyInAnyApex(ctx, ctx.ModuleName()) {
+ // If a library in an APEX has stable versioned APIs, we basically don't need
+ // to have the platform variant of the library in /system partition because
+ // platform components can just use the lib from the APEX without fearing about
+ // compatibility. However, if the library is required for some early processes
+ // before the APEX is activated, the platform variant may also be required.
+ // In that case, it is installed to the subdirectory 'bootstrap' in order to
+ // be distinguished/isolated from other non-bootstrap libraries in /system/lib
+ // so that the bootstrap libraries are used only when the APEX isn't ready.
+ if !library.buildStubs() && ctx.Arch().Native {
+ library.baseInstaller.subDir = "bootstrap"
+ }
}
library.baseInstaller.install(ctx, file)
}
diff --git a/cc/object.go b/cc/object.go
index 552f639..b9c5742 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -107,3 +107,7 @@
ctx.CheckbuildFile(outputFile)
return outputFile
}
+
+func (object *objectLinker) unstrippedOutputFilePath() android.Path {
+ return nil
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b95e2a8..b9787f0 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -79,7 +79,8 @@
scs
)
-func (t sanitizerType) String() string {
+// Name of the sanitizer variation for this sanitizer type
+func (t sanitizerType) variationName() string {
switch t {
case asan:
return "asan"
@@ -98,6 +99,26 @@
}
}
+// This is the sanitizer names in SANITIZE_[TARGET|HOST]
+func (t sanitizerType) name() string {
+ switch t {
+ case asan:
+ return "address"
+ case hwasan:
+ return "hwaddress"
+ case tsan:
+ return "thread"
+ case intOverflow:
+ return "integer_overflow"
+ case cfi:
+ return "cfi"
+ case scs:
+ return "shadow-call-stack"
+ default:
+ panic(fmt.Errorf("unknown sanitizerType %d", t))
+ }
+}
+
type SanitizeProperties struct {
// enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
Sanitize struct {
@@ -787,7 +808,7 @@
}
if mctx.Device() && runtimeLibrary != "" {
- if inList(runtimeLibrary, llndkLibraries) && !c.static() {
+ if inList(runtimeLibrary, llndkLibraries) && !c.static() && c.useVndk() {
runtimeLibrary = runtimeLibrary + llndkLibrarySuffix
}
@@ -802,12 +823,14 @@
// static executable gets static runtime libs
mctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
+ {Mutator: "image", Variation: c.imageVariation()},
{Mutator: "arch", Variation: mctx.Target().String()},
}, staticDepTag, runtimeLibrary)
} else if !c.static() {
- // dynamic executable andshared libs get shared runtime libs
+ // dynamic executable and shared libs get shared runtime libs
mctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "shared"},
+ {Mutator: "image", Variation: c.imageVariation()},
{Mutator: "arch", Variation: mctx.Target().String()},
}, earlySharedDepTag, runtimeLibrary)
}
@@ -828,14 +851,14 @@
return func(mctx android.BottomUpMutatorContext) {
if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) {
- modules := mctx.CreateVariations(t.String())
+ modules := mctx.CreateVariations(t.variationName())
modules[0].(*Module).sanitize.SetSanitizer(t, true)
} else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep {
// Save original sanitizer status before we assign values to variant
// 0 as that overwrites the original.
isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t)
- modules := mctx.CreateVariations("", t.String())
+ modules := mctx.CreateVariations("", t.variationName())
modules[0].(*Module).sanitize.SetSanitizer(t, false)
modules[1].(*Module).sanitize.SetSanitizer(t, true)
@@ -924,9 +947,9 @@
}
}
c.sanitize.Properties.SanitizeDep = false
- } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.String()) {
+ } else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
// APEX modules fall here
- mctx.CreateVariations(t.String())
+ mctx.CreateVariations(t.variationName())
}
}
}
diff --git a/cc/xom.go b/cc/xom.go
index 182069f..9337990 100644
--- a/cc/xom.go
+++ b/cc/xom.go
@@ -50,7 +50,7 @@
// If any static dependencies have XOM disabled, we should disable XOM in this module,
// the assumption being if it's been explicitly disabled then there's probably incompatible
// code in the library which may get pulled in.
- if !ctx.static() && !disableXom {
+ if !disableXom {
ctx.VisitDirectDeps(func(m android.Module) {
cc, ok := m.(*Module)
if !ok || cc.xom == nil || !cc.static() {
diff --git a/java/android_resources.go b/java/android_resources.go
index 47535d2..efd3e3d 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -44,10 +44,6 @@
type overlayGlobResult struct {
dir string
paths android.DirectorySortedPaths
-
- // Set to true of the product has selected that values in this overlay should not be moved to
- // Runtime Resource Overlay (RRO) packages.
- excludeFromRRO bool
}
const overlayDataKey = "overlayDataKey"
@@ -69,10 +65,11 @@
files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
if len(files) > 0 {
overlayModuleDir := android.PathForSource(ctx, data.dir, dir.String())
+
// If enforce RRO is enabled for this module and this overlay is not in the
// exclusion list, ignore the overlay. The list of ignored overlays will be
// passed to Make to be turned into an RRO package.
- if rroEnabled && !data.excludeFromRRO {
+ if rroEnabled && !ctx.Config().EnforceRROExcludedOverlay(overlayModuleDir.String()) {
rroDirs = append(rroDirs, overlayModuleDir)
} else {
res = append(res, globbedResourceDir{
@@ -102,10 +99,6 @@
var result overlayGlobResult
result.dir = overlay
- // Mark overlays that will not have Runtime Resource Overlays enforced on them
- // based on the product config
- result.excludeFromRRO = ctx.Config().EnforceRROExcludedOverlay(overlay)
-
files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
if err != nil {
ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
diff --git a/java/androidmk.go b/java/androidmk.go
index ccb5109..089ed4f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -381,6 +381,15 @@
fmt.Fprintln(w, ".PHONY:", ddoc.Name()+"-check-last-released-api")
fmt.Fprintln(w, ddoc.Name()+"-check-last-released-api:",
ddoc.checkLastReleasedApiTimestamp.String())
+
+ if ddoc.Name() == "api-stubs-docs" || ddoc.Name() == "system-api-stubs-docs" {
+ fmt.Fprintln(w, ".PHONY: checkapi")
+ fmt.Fprintln(w, "checkapi:",
+ ddoc.checkLastReleasedApiTimestamp.String())
+
+ fmt.Fprintln(w, ".PHONY: droidcore")
+ fmt.Fprintln(w, "droidcore: checkapi")
+ }
}
apiFilePrefix := "INTERNAL_PLATFORM_"
if String(ddoc.properties.Api_tag_name) != "" {
@@ -459,6 +468,15 @@
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-last-released-api")
fmt.Fprintln(w, dstubs.Name()+"-check-last-released-api:",
dstubs.checkLastReleasedApiTimestamp.String())
+
+ if dstubs.Name() == "api-stubs-docs" || dstubs.Name() == "system-api-stubs-docs" {
+ fmt.Fprintln(w, ".PHONY: checkapi")
+ fmt.Fprintln(w, "checkapi:",
+ dstubs.checkLastReleasedApiTimestamp.String())
+
+ fmt.Fprintln(w, ".PHONY: droidcore")
+ fmt.Fprintln(w, "droidcore: checkapi")
+ }
}
if dstubs.checkNullabilityWarningsTimestamp != nil {
fmt.Fprintln(w, ".PHONY:", dstubs.Name()+"-check-nullability-warnings")
diff --git a/java/app_test.go b/java/app_test.go
index 7e06dba..21bda3c 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -149,9 +149,13 @@
},
},
{
- name: "enforce RRO on all",
- enforceRROTargets: []string{"*"},
- enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
+ name: "enforce RRO on all",
+ enforceRROTargets: []string{"*"},
+ enforceRROExcludedOverlays: []string{
+ // Excluding specific apps/res directories also allowed.
+ "device/vendor/blah/static_overlay/foo",
+ "device/vendor/blah/static_overlay/bar/res",
+ },
overlayFiles: map[string][]string{
"foo": []string{"device/vendor/blah/static_overlay/foo/res/values/strings.xml"},
"bar": []string{"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
@@ -208,11 +212,12 @@
getOverlays := func(moduleName string) ([]string, []string) {
module := ctx.ModuleForTests(moduleName, "android_common")
- overlayCompiledPaths := module.Output("aapt2/overlay.list").Inputs.Strings()
-
+ overlayFile := module.MaybeOutput("aapt2/overlay.list")
var overlayFiles []string
- for _, o := range overlayCompiledPaths {
- overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
+ if overlayFile.Rule != nil {
+ for _, o := range overlayFile.Inputs.Strings() {
+ overlayFiles = append(overlayFiles, module.Output(o).Inputs.Strings()...)
+ }
}
rroDirs := module.Module().(*AndroidApp).rroDirs.Strings()
diff --git a/ui/status/kati.go b/ui/status/kati.go
index 7c26d42..1485c8d 100644
--- a/ui/status/kati.go
+++ b/ui/status/kati.go
@@ -121,6 +121,7 @@
}
scanner := bufio.NewScanner(pipe)
+ scanner.Buffer(nil, 2*1024*1024)
for scanner.Scan() {
parser.parseLine(scanner.Text())
}