diff options
| -rw-r--r-- | README.md | 59 | ||||
| -rw-r--r-- | android/androidmk.go | 15 | ||||
| -rw-r--r-- | android/arch.go | 7 | ||||
| -rw-r--r-- | android/bazel.go | 4 | ||||
| -rw-r--r-- | android/makevars.go | 94 | ||||
| -rw-r--r-- | android/module.go | 147 | ||||
| -rw-r--r-- | bazel/configurability.go | 2 | ||||
| -rw-r--r-- | cc/config/Android.bp | 2 | ||||
| -rw-r--r-- | cc/config/darwin_host.go (renamed from cc/config/x86_darwin_host.go) | 55 | ||||
| -rw-r--r-- | java/bootclasspath_fragment.go | 2 | ||||
| -rw-r--r-- | java/robolectric.go | 12 | ||||
| -rw-r--r-- | java/systemserver_classpath_fragment.go | 11 | ||||
| -rw-r--r-- | rust/binary.go | 13 | ||||
| -rw-r--r-- | rust/config/Android.bp | 2 | ||||
| -rw-r--r-- | rust/config/darwin_host.go (renamed from rust/config/x86_darwin_host.go) | 41 | ||||
| -rw-r--r-- | rust/rust.go | 15 | ||||
| -rw-r--r-- | rust/sanitize.go | 4 | ||||
| -rw-r--r-- | scripts/check_boot_jars/package_allowed_list.txt | 1 | ||||
| -rwxr-xr-x | scripts/manifest_check.py | 32 | ||||
| -rw-r--r-- | ui/build/soong.go | 67 |
20 files changed, 478 insertions, 107 deletions
@@ -561,27 +561,41 @@ written to a [ninja](http://ninja-build.org) build file. ## Developing for Soong -To load Soong code in a Go-aware IDE, create a directory outside your android tree and then: -```bash -apt install bindfs -export GOPATH=<path to the directory you created> -build/soong/scripts/setup_go_workspace_for_soong.sh -``` - -This will bind mount the Soong source directories into the directory in the layout expected by -the IDE. - +To load the code of Soong in IntelliJ: + +* File -> Open, open the `build/soong` directory. It will be opened as a new + project. +* File -> Settings, then Languages & Frameworks -> Go -> GOROOT, then set it to + `prebuilts/go/linux-x86` +* File -> Project Structure, then, Project Settings -> Modules, then Add + Content Root, then add the `build/blueprint` directory. +* Optional: also add the `external/golang-protobuf` directory. In practice, + IntelliJ seems to work well enough without this, too. ### Running Soong in a debugger -To run the soong_build process in a debugger, install `dlv` and then start the build with -`SOONG_DELVE=<listen addr>` in the environment. +To make `soong_build` wait for a debugger connection, install `dlv` and then +start the build with `SOONG_DELVE=<listen addr>` in the environment. For example: ```bash -SOONG_DELVE=:1234 m nothing +SOONG_DELVE=:5006 m nothing +``` + +To make `soong_ui` wait for a debugger connection, use the `SOONG_UI_DELVE` +variable: + +``` +SOONG_UI_DELVE=:5006 m nothing ``` -and then in another terminal: + + +setting or unsetting `SOONG_DELVE` causes a recompilation of `soong_build`. This +is because in order to debug the binary, it needs to be built with debug +symbols. + +To test the debugger connection, run this command: + ``` -dlv connect :1234 +dlv connect :5006 ``` If you see an error: @@ -596,6 +610,21 @@ using: sudo sysctl -w kernel.yama.ptrace_scope=0 ``` +To connect to the process using IntelliJ: + +* Run -> Edit Configurations... +* Choose "Go Remote" on the left +* Click on the "+" buttion on the top-left +* Give it a nice name and set "Host" to localhost and "Port" to the port in the + environment variable + +Debugging works far worse than debugging Java, but is sometimes useful. + +Sometimes the `dlv` process hangs on connection. A symptom of this is `dlv` +spinning a core or two. In that case, `kill -9` `dlv` and try again. +Anecdotally, it _feels_ like waiting a minute after the start of `soong_build` +helps. + ## Contact Email android-building@googlegroups.com (external) for any questions, or see diff --git a/android/androidmk.go b/android/androidmk.go index f5a9f874b..b6b04a6bc 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -516,6 +516,16 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...) a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...) + // If the install rule was generated by Soong tell Make about it. + if amod.InstallBypassMake() && len(base.katiInstalls) > 0 { + // Assume the primary install file is last since it probably needs to depend on any other + // installed files. If that is not the case we can add a method to specify the primary + // installed file. + a.SetPath("LOCAL_SOONG_INSTALLED_MODULE", base.katiInstalls[len(base.katiInstalls)-1].to) + a.SetString("LOCAL_SOONG_INSTALL_PAIRS", base.katiInstalls.BuiltInstalled()) + a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths()) + } + if am, ok := mod.(ApexModule); ok { a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform()) } @@ -911,6 +921,11 @@ func shouldSkipAndroidMkProcessing(module *ModuleBase) bool { return true } + // Only expose the primary Darwin target, as Make does not understand Darwin+Arm64 + if module.Os() == Darwin && module.Target().HostCross { + return true + } + return !module.Enabled() || module.commonProperties.HideFromMake || // Make does not understand LinuxBionic diff --git a/android/arch.go b/android/arch.go index 5e3e9204a..3bf54b711 100644 --- a/android/arch.go +++ b/android/arch.go @@ -308,7 +308,7 @@ var ( // LinuxMusl is the OS for the Linux kernel plus the musl runtime. LinuxMusl = newOsType("linux_musl", Host, false, X86, X86_64) // Darwin is the OS for MacOS/Darwin host machines. - Darwin = newOsType("darwin", Host, false, X86_64) + Darwin = newOsType("darwin", Host, false, Arm64, X86_64) // LinuxBionic is the OS for the Linux kernel plus the Bionic libc runtime, but without the // rest of Android. LinuxBionic = newOsType("linux_bionic", Host, false, Arm64, X86_64) @@ -696,6 +696,11 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { for i, m := range modules { addTargetProperties(m, targets[i], multiTargets, i == 0) m.base().setArchProperties(mctx) + + // Install support doesn't understand Darwin+Arm64 + if os == Darwin && targets[i].HostCross { + m.base().commonProperties.SkipInstall = true + } } } diff --git a/android/bazel.go b/android/bazel.go index 5dda65537..87a9d507d 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -249,8 +249,8 @@ var ( "build_tools_source_properties", // //external/libcap/... - "libcap", // http://b/198595332, depends on _makenames, a cc_binary - "cap_names.h", // http://b/198596102, depends on _makenames, a cc_binary + "cap_names.h", // http://b/196105070 host toolchain misconfigurations for mixed builds + "libcap", // http://b/196105070 host toolchain misconfigurations for mixed builds "libminijail", // depends on unconverted modules: libcap "getcap", // depends on unconverted modules: libcap diff --git a/android/makevars.go b/android/makevars.go index 40c0ccded..20db65a50 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -17,6 +17,8 @@ package android import ( "bytes" "fmt" + "path/filepath" + "runtime" "sort" "strings" @@ -222,6 +224,9 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { lateOutFile := absolutePath(PathForOutput(ctx, "late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String()) + installsFile := absolutePath(PathForOutput(ctx, + "installs"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String()) + if ctx.Failed() { return } @@ -229,6 +234,8 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { var vars []makeVarsVariable var dists []dist var phonies []phony + var katiInstalls []katiInstall + var katiSymlinks []katiInstall providers := append([]makeVarsProvider(nil), makeVarsInitProviders...) providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...) @@ -258,6 +265,11 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { phonies = append(phonies, mctx.phonies...) dists = append(dists, mctx.dists...) } + + if m.ExportedToMake() { + katiInstalls = append(katiInstalls, m.base().katiInstalls...) + katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...) + } }) if ctx.Failed() { @@ -297,6 +309,10 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { ctx.Errorf(err.Error()) } + installsBytes := s.writeInstalls(katiInstalls, katiSymlinks) + if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil { + ctx.Errorf(err.Error()) + } } func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte { @@ -405,6 +421,84 @@ func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte { return buf.Bytes() } +// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules +// are exported to Make instead of written directly to the ninja file so that main.mk can add +// the dependencies from the `required` property that are hard to resolve in Soong. +func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []byte { + buf := &bytes.Buffer{} + + fmt.Fprint(buf, `# Autogenerated file + +# Values written by Soong to generate install rules that can be amended by Kati. + + +`) + + preserveSymlinksFlag := "-d" + if runtime.GOOS == "darwin" { + preserveSymlinksFlag = "-R" + } + + for _, install := range installs { + // Write a rule for each install request in the form: + // to: from [ deps ] [ | order only deps ] + // cp -f -d $< $@ [ && chmod +x $@ ] + fmt.Fprintf(buf, "%s: %s", install.to.String(), install.from.String()) + for _, dep := range install.implicitDeps { + fmt.Fprintf(buf, " %s", dep.String()) + } + if len(install.orderOnlyDeps) > 0 { + fmt.Fprintf(buf, " |") + } + for _, dep := range install.orderOnlyDeps { + fmt.Fprintf(buf, " %s", dep.String()) + } + fmt.Fprintln(buf) + + fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@", preserveSymlinksFlag) + if install.executable { + fmt.Fprintf(buf, " && chmod +x $@") + } + fmt.Fprintln(buf) + fmt.Fprintln(buf) + } + + for _, symlink := range symlinks { + fmt.Fprintf(buf, "%s:", symlink.to.String()) + for _, dep := range symlink.implicitDeps { + fmt.Fprintf(buf, " %s", dep.String()) + } + if symlink.from != nil || len(symlink.orderOnlyDeps) > 0 { + fmt.Fprintf(buf, " |") + } + if symlink.from != nil { + fmt.Fprintf(buf, " %s", symlink.from.String()) + } + for _, dep := range symlink.orderOnlyDeps { + fmt.Fprintf(buf, " %s", dep.String()) + } + fmt.Fprintln(buf) + + fromStr := "" + if symlink.from != nil { + rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String()) + if err != nil { + panic(fmt.Errorf("failed to find relative path for symlink from %q to %q: %w", + symlink.from.String(), symlink.to.String(), err)) + } + fromStr = rel + } else { + fromStr = symlink.absFrom + } + + fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr) + fmt.Fprintln(buf) + fmt.Fprintln(buf) + } + + return buf.Bytes() +} + func (c *makeVarsContext) DeviceConfig() DeviceConfig { return DeviceConfig{c.Config().deviceConfig} } diff --git a/android/module.go b/android/module.go index 503fff3da..3447f2b51 100644 --- a/android/module.go +++ b/android/module.go @@ -1194,7 +1194,10 @@ type ModuleBase struct { packagingSpecs []PackagingSpec packagingSpecsDepSet *packagingSpecsDepSet noticeFiles Paths - phonies map[string]Paths + // katiInstalls tracks the install rules that were created by Soong but are being exported + // to Make to convert to ninja rules so that Make can add additional dependencies. + katiInstalls katiInstalls + katiSymlinks katiInstalls // The files to copy to the dist as explicitly specified in the .bp file. distFiles TaggedDistFiles @@ -2016,9 +2019,8 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...) m.tidyFiles = append(m.tidyFiles, ctx.tidyFiles...) m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...) - for k, v := range ctx.phonies { - m.phonies[k] = append(m.phonies[k], v...) - } + m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...) + m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...) } else if ctx.Config().AllowMissingDependencies() { // If the module is not enabled it will not create any build rules, nothing will call // ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled @@ -2217,12 +2219,52 @@ type moduleContext struct { module Module phonies map[string]Paths + katiInstalls []katiInstall + katiSymlinks []katiInstall + // For tests buildParams []BuildParams ruleParams map[blueprint.Rule]blueprint.RuleParams variables map[string]string } +// katiInstall stores a request from Soong to Make to create an install rule. +type katiInstall struct { + from Path + to InstallPath + implicitDeps Paths + orderOnlyDeps Paths + executable bool + + absFrom string +} + +type katiInstalls []katiInstall + +// BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a +// space separated list of from:to tuples. +func (installs katiInstalls) BuiltInstalled() string { + sb := strings.Builder{} + for i, install := range installs { + if i != 0 { + sb.WriteRune(' ') + } + sb.WriteString(install.from.String()) + sb.WriteRune(':') + sb.WriteString(install.to.String()) + } + return sb.String() +} + +// InstallPaths returns the install path of each entry. +func (installs katiInstalls) InstallPaths() InstallPaths { + paths := make(InstallPaths, 0, len(installs)) + for _, install := range installs { + paths = append(paths, install.to) + } + return paths +} + func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) { return pctx, BuildParams{ Rule: ErrorRule, @@ -2854,20 +2896,33 @@ func (m *moduleContext) installFile(installPath InstallPath, name string, srcPat orderOnlyDeps = deps } - rule := Cp - if executable { - rule = CpExecutable - } + if m.Config().KatiEnabled() && m.InstallBypassMake() { + // When creating the install rule in Soong but embedding in Make, write the rule to a + // makefile instead of directly to the ninja file so that main.mk can add the + // dependencies from the `required` property that are hard to resolve in Soong. + m.katiInstalls = append(m.katiInstalls, katiInstall{ + from: srcPath, + to: fullInstallPath, + implicitDeps: implicitDeps, + orderOnlyDeps: orderOnlyDeps, + executable: executable, + }) + } else { + rule := Cp + if executable { + rule = CpExecutable + } - m.Build(pctx, BuildParams{ - Rule: rule, - Description: "install " + fullInstallPath.Base(), - Output: fullInstallPath, - Input: srcPath, - Implicits: implicitDeps, - OrderOnly: orderOnlyDeps, - Default: !m.Config().KatiEnabled(), - }) + m.Build(pctx, BuildParams{ + Rule: rule, + Description: "install " + fullInstallPath.Base(), + Output: fullInstallPath, + Input: srcPath, + Implicits: implicitDeps, + OrderOnly: orderOnlyDeps, + Default: !m.Config().KatiEnabled(), + }) + } m.installFiles = append(m.installFiles, fullInstallPath) } @@ -2889,16 +2944,26 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src } if !m.skipInstall() { - m.Build(pctx, BuildParams{ - Rule: Symlink, - Description: "install symlink " + fullInstallPath.Base(), - Output: fullInstallPath, - Input: srcPath, - Default: !m.Config().KatiEnabled(), - Args: map[string]string{ - "fromPath": relPath, - }, - }) + if m.Config().KatiEnabled() && m.InstallBypassMake() { + // When creating the symlink rule in Soong but embedding in Make, write the rule to a + // makefile instead of directly to the ninja file so that main.mk can add the + // dependencies from the `required` property that are hard to resolve in Soong. + m.katiSymlinks = append(m.katiSymlinks, katiInstall{ + from: srcPath, + to: fullInstallPath, + }) + } else { + m.Build(pctx, BuildParams{ + Rule: Symlink, + Description: "install symlink " + fullInstallPath.Base(), + Output: fullInstallPath, + Input: srcPath, + Default: !m.Config().KatiEnabled(), + Args: map[string]string{ + "fromPath": relPath, + }, + }) + } m.installFiles = append(m.installFiles, fullInstallPath) m.checkbuildFiles = append(m.checkbuildFiles, srcPath) @@ -2921,15 +2986,25 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true) if !m.skipInstall() { - m.Build(pctx, BuildParams{ - Rule: Symlink, - Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath, - Output: fullInstallPath, - Default: !m.Config().KatiEnabled(), - Args: map[string]string{ - "fromPath": absPath, - }, - }) + if m.Config().KatiEnabled() && m.InstallBypassMake() { + // When creating the symlink rule in Soong but embedding in Make, write the rule to a + // makefile instead of directly to the ninja file so that main.mk can add the + // dependencies from the `required` property that are hard to resolve in Soong. + m.katiSymlinks = append(m.katiSymlinks, katiInstall{ + absFrom: absPath, + to: fullInstallPath, + }) + } else { + m.Build(pctx, BuildParams{ + Rule: Symlink, + Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath, + Output: fullInstallPath, + Default: !m.Config().KatiEnabled(), + Args: map[string]string{ + "fromPath": absPath, + }, + }) + } m.installFiles = append(m.installFiles, fullInstallPath) } diff --git a/bazel/configurability.go b/bazel/configurability.go index e9641e7ff..f05c8e55c 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -39,6 +39,7 @@ const ( osArchAndroidArm64 = "android_arm64" osArchAndroidX86 = "android_x86" osArchAndroidX86_64 = "android_x86_64" + osArchDarwinArm64 = "darwin_arm64" osArchDarwinX86_64 = "darwin_x86_64" osArchLinuxX86 = "linux_glibc_x86" osArchLinuxX86_64 = "linux_glibc_x86_64" @@ -96,6 +97,7 @@ var ( osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64", osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86", osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64", + osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64", osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64", osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86", osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64", diff --git a/cc/config/Android.bp b/cc/config/Android.bp index 3e8ee48ca..7b7ee2849 100644 --- a/cc/config/Android.bp +++ b/cc/config/Android.bp @@ -24,7 +24,7 @@ bootstrap_go_package { "x86_device.go", "x86_64_device.go", - "x86_darwin_host.go", + "darwin_host.go", "x86_linux_host.go", "x86_linux_bionic_host.go", "x86_windows_host.go", diff --git a/cc/config/x86_darwin_host.go b/cc/config/darwin_host.go index ad82b9476..318acb4e7 100644 --- a/cc/config/x86_darwin_host.go +++ b/cc/config/darwin_host.go @@ -53,9 +53,6 @@ var ( } darwinSupportedSdkVersions = []string{ - "10.13", - "10.14", - "10.15", "11", } @@ -174,19 +171,43 @@ type toolchainDarwin struct { toolchain64Bit } -func (t *toolchainDarwin) Name() string { +type toolchainDarwinX86 struct { + toolchainDarwin +} + +type toolchainDarwinArm struct { + toolchainDarwin +} + +func (t *toolchainDarwinArm) Name() string { + return "arm64" +} + +func (t *toolchainDarwinX86) Name() string { return "x86_64" } -func (t *toolchainDarwin) GccRoot() string { +func (t *toolchainDarwinArm) GccRoot() string { + panic("unimplemented") +} + +func (t *toolchainDarwinArm) GccTriple() string { + panic("unimplemented") +} + +func (t *toolchainDarwinArm) GccVersion() string { + panic("unimplemented") +} + +func (t *toolchainDarwinX86) GccRoot() string { return "${config.DarwinGccRoot}" } -func (t *toolchainDarwin) GccTriple() string { +func (t *toolchainDarwinX86) GccTriple() string { return "${config.DarwinGccTriple}" } -func (t *toolchainDarwin) GccVersion() string { +func (t *toolchainDarwinX86) GccVersion() string { return darwinGccVersion } @@ -194,7 +215,11 @@ func (t *toolchainDarwin) IncludeFlags() string { return "" } -func (t *toolchainDarwin) ClangTriple() string { +func (t *toolchainDarwinArm) ClangTriple() string { + return "aarch64-apple-darwin" +} + +func (t *toolchainDarwinX86) ClangTriple() string { return "x86_64-apple-darwin" } @@ -230,12 +255,18 @@ func (t *toolchainDarwin) ToolPath() string { return "${config.MacToolPath}" } -var toolchainDarwinSingleton Toolchain = &toolchainDarwin{} +var toolchainDarwinArmSingleton Toolchain = &toolchainDarwinArm{} +var toolchainDarwinX86Singleton Toolchain = &toolchainDarwinX86{} + +func darwinArmToolchainFactory(arch android.Arch) Toolchain { + return toolchainDarwinArmSingleton +} -func darwinToolchainFactory(arch android.Arch) Toolchain { - return toolchainDarwinSingleton +func darwinX86ToolchainFactory(arch android.Arch) Toolchain { + return toolchainDarwinX86Singleton } func init() { - registerToolchainFactory(android.Darwin, android.X86_64, darwinToolchainFactory) + registerToolchainFactory(android.Darwin, android.Arm64, darwinArmToolchainFactory) + registerToolchainFactory(android.Darwin, android.X86_64, darwinX86ToolchainFactory) } diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 8f18790ea..bfa683824 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -616,6 +616,8 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) // This is an exception to support end-to-end test for SdkExtensions, until such support exists. if android.InList("test_framework-sdkextensions", possibleUpdatableModules) { jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions") + } else if android.InList("test_framework-apexd", possibleUpdatableModules) { + jars = jars.Append("com.android.apex.test_package", "test_framework-apexd") } else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) { unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents) _, unknown = android.RemoveFromList("core-icu4j", unknown) diff --git a/java/robolectric.go b/java/robolectric.go index a3603adf8..16af546ba 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -212,13 +212,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) installDeps = append(installDeps, installedData) } - installed := ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...) - - if r.ExportedToMake() { - // Soong handles installation here, but Make is usually what creates the phony rule that atest - // uses to build the module. Create it here for now. - ctx.Phony(ctx.ModuleName(), installed) - } + r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...) } func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, @@ -282,6 +276,10 @@ func (r *robolectricTest) generateRoboSrcJar(ctx android.ModuleContext, outputFi func (r *robolectricTest) AndroidMkEntries() []android.AndroidMkEntries { entriesList := r.Library.AndroidMkEntries() entries := &entriesList[0] + entries.ExtraEntries = append(entries.ExtraEntries, + func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) + }) entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{ func(w io.Writer, name, prefix, moduleDir string) { diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index b5f52fd10..d75635c43 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -124,8 +124,15 @@ func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) // So ignore it even if it is not in PRODUCT_APEX_SYSTEM_SERVER_JARS. // TODO(b/203233647): Add better mechanism to make it optional. _, unknown = android.RemoveFromList("car-frameworks-service-module", unknown) - // For non test apexes, make sure that all contents are actually declared in make. - if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 && !android.IsModuleInVersionedSdk(ctx.Module()) { + + // TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths + // config. However, any test specific jars would not be present in ApexSystemServerJars. Instead, + // we should check if we are creating a config for apex_test via ApexInfo and amend the values. + // This is an exception to support end-to-end test for ApexdUnitTests, until such support exists. + if android.InList("test_service-apexd", possibleUpdatableModules) { + jars = jars.Append("com.android.apex.test_package", "test_service-apexd") + } else if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 && !android.IsModuleInVersionedSdk(ctx.Module()) { + // For non test apexes, make sure that all contents are actually declared in make. ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_SYSTEM_SERVER_JARS", unknown) } diff --git a/rust/binary.go b/rust/binary.go index 2c3f54835..7c18730c6 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -31,6 +31,11 @@ type BinaryCompilerProperties struct { Static_executable *bool `android:"arch_variant"` } +type binaryInterface interface { + binary() bool + staticallyLinked() bool +} + type binaryDecorator struct { *baseCompiler stripper Stripper @@ -155,3 +160,11 @@ func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage { } return binary.baseCompiler.stdLinkage(ctx) } + +func (binary *binaryDecorator) binary() bool { + return true +} + +func (binary *binaryDecorator) staticallyLinked() bool { + return Bool(binary.Properties.Static_executable) +} diff --git a/rust/config/Android.bp b/rust/config/Android.bp index 5b121c3aa..7757c79fc 100644 --- a/rust/config/Android.bp +++ b/rust/config/Android.bp @@ -16,7 +16,7 @@ bootstrap_go_package { "lints.go", "toolchain.go", "allowed_list.go", - "x86_darwin_host.go", + "darwin_host.go", "x86_linux_bionic_host.go", "x86_linux_host.go", "x86_device.go", diff --git a/rust/config/x86_darwin_host.go b/rust/config/darwin_host.go index 8ff0dd4be..03bea8274 100644 --- a/rust/config/x86_darwin_host.go +++ b/rust/config/darwin_host.go @@ -25,41 +25,64 @@ var ( DarwinRustLinkFlags = []string{ "-B${cc_config.MacToolPath}", } + darwinArm64Rustflags = []string{} + darwinArm64Linkflags = []string{} darwinX8664Rustflags = []string{} darwinX8664Linkflags = []string{} ) func init() { + registerToolchainFactory(android.Darwin, android.Arm64, darwinArm64ToolchainFactory) registerToolchainFactory(android.Darwin, android.X86_64, darwinX8664ToolchainFactory) + pctx.StaticVariable("DarwinToolchainRustFlags", strings.Join(DarwinRustFlags, " ")) pctx.StaticVariable("DarwinToolchainLinkFlags", strings.Join(DarwinRustLinkFlags, " ")) + + pctx.StaticVariable("DarwinToolchainArm64RustFlags", strings.Join(darwinArm64Rustflags, " ")) + pctx.StaticVariable("DarwinToolchainArm64LinkFlags", strings.Join(darwinArm64Linkflags, " ")) pctx.StaticVariable("DarwinToolchainX8664RustFlags", strings.Join(darwinX8664Rustflags, " ")) pctx.StaticVariable("DarwinToolchainX8664LinkFlags", strings.Join(darwinX8664Linkflags, " ")) } type toolchainDarwin struct { + toolchain64Bit toolchainRustFlags string toolchainLinkFlags string } +type toolchainDarwinArm64 struct { + toolchainDarwin +} + type toolchainDarwinX8664 struct { - toolchain64Bit toolchainDarwin } +func (toolchainDarwinArm64) Supported() bool { + return true +} + func (toolchainDarwinX8664) Supported() bool { return true } -func (toolchainDarwinX8664) Bionic() bool { +func (toolchainDarwin) Bionic() bool { return false } +func (t *toolchainDarwinArm64) Name() string { + return "arm64" +} + func (t *toolchainDarwinX8664) Name() string { return "x86_64" } +func (t *toolchainDarwinArm64) RustTriple() string { + return "aarch64-apple-darwin" +} + func (t *toolchainDarwinX8664) RustTriple() string { return "x86_64-apple-darwin" } @@ -76,6 +99,15 @@ func (t *toolchainDarwin) ProcMacroSuffix() string { return ".dylib" } +func (t *toolchainDarwinArm64) ToolchainLinkFlags() string { + // Prepend the lld flags from cc_config so we stay in sync with cc + return "${cc_config.DarwinLldflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainArm64LinkFlags}" +} + +func (t *toolchainDarwinArm64) ToolchainRustFlags() string { + return "${config.DarwinToolchainRustFlags} ${config.DarwinToolchainArm64RustFlags}" +} + func (t *toolchainDarwinX8664) ToolchainLinkFlags() string { // Prepend the lld flags from cc_config so we stay in sync with cc return "${cc_config.DarwinLldflags} ${config.DarwinToolchainLinkFlags} ${config.DarwinToolchainX8664LinkFlags}" @@ -85,8 +117,13 @@ func (t *toolchainDarwinX8664) ToolchainRustFlags() string { return "${config.DarwinToolchainRustFlags} ${config.DarwinToolchainX8664RustFlags}" } +func darwinArm64ToolchainFactory(arch android.Arch) Toolchain { + return toolchainDarwinArm64Singleton +} + func darwinX8664ToolchainFactory(arch android.Arch) Toolchain { return toolchainDarwinX8664Singleton } +var toolchainDarwinArm64Singleton Toolchain = &toolchainDarwinArm64{} var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{} diff --git a/rust/rust.go b/rust/rust.go index 13169f17e..c465cb609 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -261,10 +261,8 @@ func (mod *Module) Rlib() bool { } func (mod *Module) Binary() bool { - if mod.compiler != nil { - if _, ok := mod.compiler.(*binaryDecorator); ok { - return true - } + if binary, ok := mod.compiler.(binaryInterface); ok { + return binary.binary() } return false } @@ -273,7 +271,7 @@ func (mod *Module) StaticExecutable() bool { if !mod.Binary() { return false } - return Bool(mod.compiler.(*binaryDecorator).Properties.Static_executable) + return mod.StaticallyLinked() } func (mod *Module) Object() bool { @@ -1123,7 +1121,12 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if cc.IsWholeStaticLib(depTag) { // rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail // if the library is not prefixed by "lib". - if libName, ok := libNameFromFilePath(linkObject.Path()); ok { + if mod.Binary() { + // Binaries may sometimes need to link whole static libraries that don't start with 'lib'. + // Since binaries don't need to 'rebundle' these like libraries and only use these for the + // final linkage, pass the args directly to the linker to handle these cases. + depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...) + } else if libName, ok := libNameFromFilePath(linkObject.Path()); ok { depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName) } else { ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName()) diff --git a/rust/sanitize.go b/rust/sanitize.go index a4ba4bd33..baa383da6 100644 --- a/rust/sanitize.go +++ b/rust/sanitize.go @@ -311,8 +311,8 @@ func (mod *Module) SetSanitizeDep(b bool) { func (mod *Module) StaticallyLinked() bool { if lib, ok := mod.compiler.(libraryInterface); ok { return lib.rlib() || lib.static() - } else if binary, ok := mod.compiler.(*binaryDecorator); ok { - return Bool(binary.Properties.Static_executable) + } else if binary, ok := mod.compiler.(binaryInterface); ok { + return binary.staticallyLinked() } return false } diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt index b1b1e7e60..ed63651ef 100644 --- a/scripts/check_boot_jars/package_allowed_list.txt +++ b/scripts/check_boot_jars/package_allowed_list.txt @@ -69,6 +69,7 @@ javax\.xml\.transform\.sax javax\.xml\.transform\.stream javax\.xml\.validation javax\.xml\.xpath +jdk\.internal jdk\.internal\.math jdk\.internal\.misc jdk\.internal\.reflect diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py index b4936b865..8bed52a9f 100755 --- a/scripts/manifest_check.py +++ b/scripts/manifest_check.py @@ -84,6 +84,13 @@ def parse_args(): return parser.parse_args() +C_RED = "\033[1;31m" +C_GREEN = "\033[1;32m" +C_BLUE = "\033[1;34m" +C_OFF = "\033[0m" +C_BOLD = "\033[1m" + + def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path): """Verify that the <uses-library> tags in the manifest match those provided @@ -119,22 +126,21 @@ def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path): errmsg = ''.join([ 'mismatch in the <uses-library> tags between the build system and the ' 'manifest:\n', - '\t- required libraries in build system: [%s]\n' % ', '.join(required), - '\t vs. in the manifest: [%s]\n' % - ', '.join(manifest_required), - '\t- optional libraries in build system: [%s]\n' % ', '.join(optional), - '\t vs. in the manifest: [%s]\n' % - ', '.join(manifest_optional), + '\t- required libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(required), C_OFF), + '\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_required), C_OFF), + '\t- optional libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(optional), C_OFF), + '\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_optional), C_OFF), '\t- tags in the manifest (%s):\n' % path, '\t\t%s\n' % '\t\t'.join(tags), - 'note: the following options are available:\n', + '%snote:%s the following options are available:\n' % (C_BLUE, C_OFF), '\t- to temporarily disable the check on command line, rebuild with ', - 'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ', - 'and disable AOT-compilation in dexpreopt)\n', + '%sRELAX_USES_LIBRARY_CHECK=true%s' % (C_BOLD, C_OFF), + ' (this will set compiler filter "verify" and disable AOT-compilation in dexpreopt)\n', '\t- to temporarily disable the check for the whole product, set ', - 'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n', - '\t- to fix the check, make build system properties coherent with the ' - 'manifest\n', '\t- see build/make/Changes.md for details\n' + '%sPRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true%s in the product makefiles\n' % (C_BOLD, C_OFF), + '\t- to fix the check, make build system properties coherent with the manifest\n', + '\t- for details, see %sbuild/make/Changes.md%s' % (C_GREEN, C_OFF), + ' and %shttps://source.android.com/devices/tech/dalvik/art-class-loader-context%s\n' % (C_GREEN, C_OFF) ]) #pylint: enable=line-too-long @@ -380,7 +386,7 @@ def main(): # pylint: disable=broad-except except Exception as err: - print('error: ' + str(err), file=sys.stderr) + print('%serror:%s ' % (C_RED, C_OFF) + str(err), file=sys.stderr) sys.exit(-1) diff --git a/ui/build/soong.go b/ui/build/soong.go index a0f223b2c..1c7fbac7e 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -15,6 +15,7 @@ package build import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -43,6 +44,12 @@ const ( jsonModuleGraphTag = "modulegraph" queryviewTag = "queryview" soongDocsTag = "soong_docs" + + // bootstrapEpoch is used to determine if an incremental build is incompatible with the current + // version of bootstrap and needs cleaning before continuing the build. Increment this for + // incompatible changes, for example when moving the location of the bpglob binary that is + // executed during bootstrap before the primary builder has had a chance to update the path. + bootstrapEpoch = 0 ) func writeEnvironmentFile(ctx Context, envFile string, envDeps map[string]string) error { @@ -121,20 +128,31 @@ func environmentArgs(config Config, tag string) []string { } } -func writeEmptyGlobFile(ctx Context, path string) { +func writeEmptyFile(ctx Context, path string) { err := os.MkdirAll(filepath.Dir(path), 0777) if err != nil { - ctx.Fatalf("Failed to create parent directories of empty ninja glob file '%s': %s", path, err) + ctx.Fatalf("Failed to create parent directories of empty file '%s': %s", path, err) } - if _, err := os.Stat(path); os.IsNotExist(err) { + if exists, err := fileExists(path); err != nil { + ctx.Fatalf("Failed to check if file '%s' exists: %s", path, err) + } else if !exists { err = ioutil.WriteFile(path, nil, 0666) if err != nil { - ctx.Fatalf("Failed to create empty ninja glob file '%s': %s", path, err) + ctx.Fatalf("Failed to create empty file '%s': %s", path, err) } } } +func fileExists(path string) (bool, error) { + if _, err := os.Stat(path); os.IsNotExist(err) { + return false, nil + } else if err != nil { + return false, err + } + return true, nil +} + func primaryBuilderInvocation(config Config, name string, output string, specificArgs []string) bootstrap.PrimaryBuilderInvocation { commonArgs := make([]string, 0, 0) @@ -166,10 +184,45 @@ func primaryBuilderInvocation(config Config, name string, output string, specifi } } +// bootstrapEpochCleanup deletes files used by bootstrap during incremental builds across +// incompatible changes. Incompatible changes are marked by incrementing the bootstrapEpoch +// constant. A tree is considered out of date for the current epoch of the +// .soong.bootstrap.epoch.<epoch> file doesn't exist. +func bootstrapEpochCleanup(ctx Context, config Config) { + epochFile := fmt.Sprintf(".soong.bootstrap.epoch.%d", bootstrapEpoch) + epochPath := filepath.Join(config.SoongOutDir(), epochFile) + if exists, err := fileExists(epochPath); err != nil { + ctx.Fatalf("failed to check if bootstrap epoch file %q exists: %q", epochPath, err) + } else if !exists { + // The tree is out of date for the current epoch, delete files used by bootstrap + // and force the primary builder to rerun. + os.Remove(filepath.Join(config.SoongOutDir(), "build.ninja")) + for _, globFile := range bootstrapGlobFileList(config) { + os.Remove(globFile) + } + + // Mark the tree as up to date with the current epoch by writing the epoch marker file. + writeEmptyFile(ctx, epochPath) + } +} + +func bootstrapGlobFileList(config Config) []string { + return []string{ + config.NamedGlobFile(soongBuildTag), + config.NamedGlobFile(bp2buildTag), + config.NamedGlobFile(jsonModuleGraphTag), + config.NamedGlobFile(queryviewTag), + config.NamedGlobFile(soongDocsTag), + } +} + func bootstrapBlueprint(ctx Context, config Config) { ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap") defer ctx.EndTrace() + // Clean up some files for incremental builds across incompatible changes. + bootstrapEpochCleanup(ctx, config) + mainSoongBuildExtraArgs := []string{"-o", config.SoongNinjaFile()} if config.EmptyNinjaFile() { mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--empty-ninja-file") @@ -232,8 +285,8 @@ func bootstrapBlueprint(ctx Context, config Config) { // The glob .ninja files are subninja'd. However, they are generated during // the build itself so we write an empty file if the file does not exist yet // so that the subninja doesn't fail on clean builds - for _, globFile := range globFiles { - writeEmptyGlobFile(ctx, globFile) + for _, globFile := range bootstrapGlobFileList(config) { + writeEmptyFile(ctx, globFile) } var blueprintArgs bootstrap.Args @@ -342,7 +395,7 @@ func runSoong(ctx Context, config Config) { } }() - runMicrofactory(ctx, config, filepath.Join(config.HostToolDir(), "bpglob"), "github.com/google/blueprint/bootstrap/bpglob", + runMicrofactory(ctx, config, "bpglob", "github.com/google/blueprint/bootstrap/bpglob", map[string]string{"github.com/google/blueprint": "build/blueprint"}) ninja := func(name, ninjaFile string, targets ...string) { |