Pass the name of Soong's checkbuild target for each module to Make so that it can depend on it from the main checkbuild rule. This will give better control over which files get built, allowing checkbuild to skip the jar combining step when transitive classpath jars are enabled. The per-module checkbuild targets are passed to make instead of added directly as a dependency of checkbuild in order to maintain the existing behavior of only building modules exposed to make in checkbuild. Also tweak the existing calls to CheckbuildFile and add InstallFileWithoutCheckbuild to match the files that are in the Make-based checkbuild. Bug: 308016794 Test: m checkbuild Change-Id: Ic5140819381d58f4d00f23a7a12447950c4cf268
317 lines
13 KiB
Go
317 lines
13 KiB
Go
// Copyright (C) 2019 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package apex
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"android/soong/android"
|
|
"android/soong/cc"
|
|
"android/soong/java"
|
|
"android/soong/rust"
|
|
)
|
|
|
|
func (a *apexBundle) AndroidMk() android.AndroidMkData {
|
|
if a.properties.HideFromMake {
|
|
return android.AndroidMkData{
|
|
Disabled: true,
|
|
}
|
|
}
|
|
return a.androidMkForType()
|
|
}
|
|
|
|
// nameInMake converts apexFileClass into the corresponding class name in Make.
|
|
func (class apexFileClass) nameInMake() string {
|
|
switch class {
|
|
case etc:
|
|
return "ETC"
|
|
case nativeSharedLib:
|
|
return "SHARED_LIBRARIES"
|
|
case nativeExecutable, shBinary:
|
|
return "EXECUTABLES"
|
|
case javaSharedLib:
|
|
return "JAVA_LIBRARIES"
|
|
case nativeTest:
|
|
return "NATIVE_TESTS"
|
|
case app, appSet:
|
|
// b/142537672 Why isn't this APP? We want to have full control over
|
|
// the paths and file names of the apk file under the flattend APEX.
|
|
// If this is set to APP, then the paths and file names are modified
|
|
// by the Make build system. For example, it is installed to
|
|
// /system/apex/<apexname>/app/<Appname>/<apexname>.<Appname>/ instead of
|
|
// /system/apex/<apexname>/app/<Appname> because the build system automatically
|
|
// appends module name (which is <apexname>.<Appname> to the path.
|
|
return "ETC"
|
|
default:
|
|
panic(fmt.Errorf("unknown class %d", class))
|
|
}
|
|
}
|
|
|
|
// Return the full module name for a dependency module, which appends the apex module name unless re-using a system lib.
|
|
func (a *apexBundle) fullModuleName(apexBundleName string, linkToSystemLib bool, fi *apexFile) string {
|
|
if linkToSystemLib {
|
|
return fi.androidMkModuleName
|
|
}
|
|
return fi.androidMkModuleName + "." + apexBundleName
|
|
}
|
|
|
|
// androidMkForFiles generates Make definitions for the contents of an
|
|
// apexBundle (apexBundle#filesInfo). The filesInfo structure can either be
|
|
// populated by Soong for unconverted APEXes, or Bazel in mixed mode. Use
|
|
// apexFile#isBazelPrebuilt to differentiate.
|
|
func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir string,
|
|
apexAndroidMkData android.AndroidMkData) []string {
|
|
|
|
// apexBundleName comes from the 'name' property or soong module.
|
|
// apexName comes from 'name' property of apex_manifest.
|
|
// An apex is installed to /system/apex/<apexBundleName> and is activated at /apex/<apexName>
|
|
// In many cases, the two names are the same, but could be different in general.
|
|
// However, symbol files for apex files are installed under /apex/<apexBundleName> to avoid
|
|
// conflicts between two apexes with the same apexName.
|
|
|
|
moduleNames := []string{}
|
|
|
|
for _, fi := range a.filesInfo {
|
|
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
|
|
moduleName := a.fullModuleName(apexBundleName, linkToSystemLib, &fi)
|
|
|
|
// This name will be added to LOCAL_REQUIRED_MODULES of the APEX. We need to be
|
|
// arch-specific otherwise we will end up installing both ABIs even when only
|
|
// either of the ABI is requested.
|
|
aName := moduleName
|
|
switch fi.multilib {
|
|
case "lib32":
|
|
aName = aName + ":32"
|
|
case "lib64":
|
|
aName = aName + ":64"
|
|
}
|
|
if !android.InList(aName, moduleNames) {
|
|
moduleNames = append(moduleNames, aName)
|
|
}
|
|
|
|
if linkToSystemLib {
|
|
// No need to copy the file since it's linked to the system file
|
|
continue
|
|
}
|
|
|
|
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle.files")
|
|
if fi.moduleDir != "" {
|
|
fmt.Fprintln(w, "LOCAL_PATH :=", fi.moduleDir)
|
|
} else {
|
|
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
|
}
|
|
fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName)
|
|
|
|
if fi.module != nil && fi.module.Owner() != "" {
|
|
fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", fi.module.Owner())
|
|
}
|
|
// /apex/<apexBundleName>/{lib|framework|...}
|
|
pathForSymbol := filepath.Join("$(PRODUCT_OUT)", "apex", apexBundleName, fi.installDir)
|
|
modulePath := pathForSymbol
|
|
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", modulePath)
|
|
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
|
|
for _, extra := range apexAndroidMkData.Extra {
|
|
extra(w, fi.builtFile)
|
|
}
|
|
|
|
// For non-flattend APEXes, the merged notice file is attached to the APEX itself.
|
|
// We don't need to have notice file for the individual modules in it. Otherwise,
|
|
// we will have duplicated notice entries.
|
|
fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
|
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", filepath.Join(modulePath, fi.stem()))
|
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", fi.builtFile.String()+":"+filepath.Join(modulePath, fi.stem()))
|
|
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
|
|
if fi.checkbuildTarget != nil {
|
|
fmt.Fprintln(w, "LOCAL_CHECKED_MODULE :=", fi.checkbuildTarget.String())
|
|
} else {
|
|
fmt.Fprintln(w, "LOCAL_CHECKED_MODULE :=", fi.builtFile.String())
|
|
}
|
|
fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.nameInMake())
|
|
if fi.module != nil {
|
|
// This apexFile's module comes from Soong
|
|
if fi.module.Target().Arch.ArchType != android.Common {
|
|
archStr := fi.module.Target().Arch.ArchType.String()
|
|
fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
|
|
}
|
|
}
|
|
if fi.jacocoReportClassesFile != nil {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
|
|
}
|
|
switch fi.class {
|
|
case javaSharedLib:
|
|
// 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.stem(), ".jar"))
|
|
if javaModule, ok := fi.module.(java.ApexDependency); ok {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
|
|
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
|
|
} else {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", fi.builtFile.String())
|
|
fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", fi.builtFile.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")
|
|
case app:
|
|
fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", fi.certificate.AndroidMkString())
|
|
// soong_app_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .apk Therefore
|
|
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
|
|
// we will have foo.apk.apk
|
|
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.stem(), ".apk"))
|
|
if app, ok := fi.module.(*java.AndroidApp); ok {
|
|
android.AndroidMkEmitAssignList(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE", app.JniCoverageOutputs().Strings())
|
|
if jniLibSymbols := app.JNISymbolsInstalls(modulePath); len(jniLibSymbols) > 0 {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_JNI_LIBS_SYMBOLS :=", jniLibSymbols.String())
|
|
}
|
|
}
|
|
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk")
|
|
case appSet:
|
|
as, ok := fi.module.(*java.AndroidAppSet)
|
|
if !ok {
|
|
panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
|
|
}
|
|
fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", as.PackedAdditionalOutputs().String())
|
|
fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", as.APKCertsFile().String())
|
|
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
|
|
case nativeSharedLib, nativeExecutable, nativeTest:
|
|
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.stem())
|
|
if ccMod, ok := fi.module.(*cc.Module); ok {
|
|
if ccMod.UnstrippedOutputFile() != nil {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
|
|
}
|
|
ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
|
|
if ccMod.CoverageOutputFile().Valid() {
|
|
fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
|
|
}
|
|
} else if rustMod, ok := fi.module.(*rust.Module); ok {
|
|
if rustMod.UnstrippedOutputFile() != nil {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
|
|
}
|
|
}
|
|
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
|
|
default:
|
|
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.stem())
|
|
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
|
}
|
|
|
|
// m <module_name> will build <module_name>.<apex_name> as well.
|
|
if fi.androidMkModuleName != moduleName {
|
|
fmt.Fprintf(w, ".PHONY: %s\n", fi.androidMkModuleName)
|
|
fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
|
|
}
|
|
}
|
|
return moduleNames
|
|
}
|
|
|
|
func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) {
|
|
var required []string
|
|
var targetRequired []string
|
|
var hostRequired []string
|
|
required = append(required, a.required...)
|
|
targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...)
|
|
hostRequired = append(hostRequired, a.HostRequiredModuleNames()...)
|
|
for _, fi := range a.filesInfo {
|
|
required = append(required, fi.requiredModuleNames...)
|
|
targetRequired = append(targetRequired, fi.targetRequiredModuleNames...)
|
|
hostRequired = append(hostRequired, fi.hostRequiredModuleNames...)
|
|
}
|
|
android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", moduleNames, a.makeModulesToInstall, required)
|
|
android.AndroidMkEmitAssignList(w, "LOCAL_TARGET_REQUIRED_MODULES", targetRequired)
|
|
android.AndroidMkEmitAssignList(w, "LOCAL_HOST_REQUIRED_MODULES", hostRequired)
|
|
}
|
|
|
|
func (a *apexBundle) androidMkForType() android.AndroidMkData {
|
|
return android.AndroidMkData{
|
|
// While we do not provide a value for `Extra`, AconfigUpdateAndroidMkData may add some, which we must honor.
|
|
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
|
|
moduleNames := []string{}
|
|
if a.installable() {
|
|
moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
|
|
}
|
|
|
|
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle")
|
|
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
|
|
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
|
|
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
|
|
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
|
|
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.String())
|
|
stemSuffix := imageApexSuffix
|
|
if a.isCompressed {
|
|
stemSuffix = imageCapexSuffix
|
|
}
|
|
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+stemSuffix)
|
|
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
|
|
if a.installable() {
|
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String())
|
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
|
|
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_SYMLINKS := ", strings.Join(a.compatSymlinks.Strings(), " "))
|
|
}
|
|
fmt.Fprintln(w, "LOCAL_APEX_KEY_PATH := ", a.apexKeysPath.String())
|
|
|
|
// Because apex writes .mk with Custom(), we need to write manually some common properties
|
|
// which are available via data.Entries
|
|
commonProperties := []string{
|
|
"LOCAL_FULL_INIT_RC", "LOCAL_FULL_VINTF_FRAGMENTS",
|
|
"LOCAL_PROPRIETARY_MODULE", "LOCAL_VENDOR_MODULE", "LOCAL_ODM_MODULE", "LOCAL_PRODUCT_MODULE", "LOCAL_SYSTEM_EXT_MODULE",
|
|
"LOCAL_MODULE_OWNER",
|
|
}
|
|
for _, name := range commonProperties {
|
|
if value, ok := data.Entries.EntryMap[name]; ok {
|
|
android.AndroidMkEmitAssignList(w, name, value)
|
|
}
|
|
}
|
|
|
|
android.AndroidMkEmitAssignList(w, "LOCAL_OVERRIDES_MODULES", a.overridableProperties.Overrides)
|
|
a.writeRequiredModules(w, moduleNames)
|
|
// AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
|
|
for _, extra := range data.Extra {
|
|
extra(w, a.outputFile)
|
|
}
|
|
|
|
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
|
|
fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
|
|
android.AndroidMkEmitAssignList(w, "ALL_MODULES.$(my_register_name).LINT_REPORTS", a.lintReports.Strings())
|
|
|
|
if a.installedFilesFile != nil {
|
|
goal := "checkbuild"
|
|
distFile := name + "-installed-files.txt"
|
|
fmt.Fprintln(w, ".PHONY:", goal)
|
|
fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
|
|
goal, a.installedFilesFile.String(), distFile)
|
|
fmt.Fprintf(w, "$(call declare-0p-target,%s)\n", a.installedFilesFile.String())
|
|
}
|
|
for _, dist := range data.Entries.GetDistForGoals(a) {
|
|
fmt.Fprintf(w, dist)
|
|
}
|
|
|
|
distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
|
|
distCoverageFiles(w, "ndk_apis_backedby_apex", a.nativeApisBackedByModuleFile.String())
|
|
distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
|
|
}}
|
|
}
|
|
|
|
func distCoverageFiles(w io.Writer, dir string, distfile string) {
|
|
if distfile != "" {
|
|
goal := "apps_only"
|
|
fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
|
|
" $(call dist-for-goals,%s,%s:%s/$(notdir %s))\n"+
|
|
"endif\n", goal, distfile, dir, distfile)
|
|
}
|
|
}
|