Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  ravenwood.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2023 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 java

import (
 "fmt"
 "maps"
 "strings"

 "android/soong/aconfig"
 "android/soong/android"
 "android/soong/tradefed"

 "github.com/google/blueprint"
 "github.com/google/blueprint/proptools"
)

//go:generate go run ../../blueprint/gobtools/codegen

func init() {
 RegisterRavenwoodBuildComponents(android.InitRegistrationContext)
}

func RegisterRavenwoodBuildComponents(ctx android.RegistrationContext) {
 ctx.RegisterModuleType("android_ravenwood_test", ravenwoodTestFactory)
 ctx.RegisterModuleType("android_ravenwood_libgroup", ravenwoodLibgroupFactory)
}

var ravenwoodLibContentTag = dependencyTag{name: "ravenwoodlibcontent"}
var ravenwoodLibSubruntimeTag = dependencyTag{name: "ravenwoodlibsubruntime"}
var ravenwoodUtilsTag = dependencyTag{name: "ravenwoodutils"}
var ravenwoodRuntimeTag = dependencyTag{name: "ravenwoodruntime"}
var ravenwoodTargetResourceApkTag = dependencyTag{name: "ravenwood-target-res-apk"}
var allAconfigModuleTag = dependencyTag{name: "all_aconfig"}

const ravenwoodUtilsName = "ravenwood-utils"
const ravenwoodRuntimeName = "ravenwood-runtime"

// @auto-generate: gob
type ravenwoodLibgroupJniDepProviderInfo struct {
 // All the jni_libs module names with transient dependencies.
 names map[string]bool
}

var ravenwoodLibgroupJniDepProvider = blueprint.NewProvider[ravenwoodLibgroupJniDepProviderInfo]()

func getLibPath(archType android.ArchType) string {
 if archType.Multilib == "lib64" {
  return "lib64"
 }
 return "lib"
}

type ravenwoodTestProperties struct {
 // Specify the name of the Instrumentation subclass to use.
 // (e.g. "androidx.test.runner.AndroidJUnitRunner")
 Instrumentation_class *string

 // Specify the package name of the test target apk.
 // This will be set to the target Context's package name.
 // (i.e. Instrumentation.getTargetContext().getPackageName())
 // If this is omitted, Package_name will be used.
 Target_package_name *string

 // Specify another android_app module here to copy it to the test directory, so that
 // the ravenwood test can access it. This APK will be loaded as resources of the test
 // target app.
 Target_resource_apk *string

 // Specify whether to build resources.
 Build_resources *bool
}

type ravenwoodTest struct {
 Library
 aapt

 ravenwoodTestProperties ravenwoodTestProperties

 testProperties testProperties

 testConfig android.Path
 data       android.Paths

 forceOSType   android.OsType
 forceArchType android.ArchType
}

func ravenwoodTestFactory() android.Module {
 module := &ravenwoodTest{}

 module.addHostAndDeviceProperties()
 module.AddProperties(&module.aaptProperties, &module.testProperties, &module.ravenwoodTestProperties)

 module.Module.dexpreopter.isTest = true
 module.Module.linter.properties.Lint.Test_module_type = proptools.BoolPtr(true)

 module.testProperties.Test_suites = []string{
  "general-tests",
  "ravenwood-tests",
 }
 module.testProperties.Test_options.Unit_test = proptools.BoolPtr(false)
 module.Module.sourceProperties.Test_only = proptools.BoolPtr(true)
 module.Module.sourceProperties.Top_level_test_target = true

 InitJavaModule(module, android.DeviceSupported)
 android.InitDefaultableModule(module)

 return module
}

func (r *ravenwoodTest) InstallInTestcases() bool { return true }
func (r *ravenwoodTest) InstallForceOS() (*android.OsType, *android.ArchType) {
 return &r.forceOSType, &r.forceArchType
}
func (r *ravenwoodTest) TestSuites() []string {
 return r.testProperties.Test_suites
}

func (r *ravenwoodTest) DepsMutator(ctx android.BottomUpMutatorContext) {
 r.Library.DepsMutator(ctx)

 // Generically depend on the runtime so that it's installed together with us
 ctx.AddVariationDependencies(nil, ravenwoodRuntimeTag, ravenwoodRuntimeName)

 // Directly depend on any utils so that we link against them
 utils := ctx.AddVariationDependencies(nil, ravenwoodUtilsTag, ravenwoodUtilsName)[0]
 if !utils.IsNil() {
  libgroupInfo := android.OtherModuleProviderOrDefault(ctx, utils, ravenwoodLibgroupInfoProvider)
  for _, lib := range libgroupInfo.libs {
   ctx.AddVariationDependencies(nil, libTag, lib)
  }
 }

 // Add jni libs
 for _, lib := range r.testProperties.Jni_libs.GetOrDefault(ctx, nil) {
  // ravenwood-runtime contains `libandroid_runtime_ravenwood`. Tests shouldn't
  // include it or the original one, as it'd break the environment.
  if lib == "libandroid_runtime" || lib == "libandroid_runtime_ravenwood" {
   ctx.PropertyErrorf("jni_libs", "Ravenwood test module shouldn't include \"%s\"", lib)
   continue
  }
  ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
 }

 // Resources APK
 if resourceApk := proptools.String(r.ravenwoodTestProperties.Target_resource_apk); resourceApk != "" {
  ctx.AddVariationDependencies(nil, ravenwoodTargetResourceApkTag, resourceApk)
 }

 sdkDep := decodeSdkDep(ctx, android.SdkContext(r))
 if sdkDep.hasFrameworkLibs() {
  r.aapt.deps(ctx, sdkDep)
 }

 for _, aconfig_declaration := range r.aaptProperties.Flags_packages {
  ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
 }
}

func (r *ravenwoodTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 r.forceOSType = ctx.Config().BuildOS
 r.forceArchType = ctx.Config().BuildArch

 r.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
  TestConfigProp:          r.testProperties.Test_config,
  TestConfigTemplateProp:  r.testProperties.Test_config_template,
  OptionsForAutogenerated: r.testProperties.Test_options.Tradefed_options,
  TestRunnerOptions:       r.testProperties.Test_options.Test_runner_options,
  TestSuites:              r.testProperties.Test_suites,

  // `auto_gen_config` should almost always be set to true, but let's still allow explicitly setting
  // it to false, which we might want use when testing a new config file.
  AutoGenConfig:  proptools.BoolPtr(proptools.BoolDefault(r.testProperties.Auto_gen_config, true)),
  DeviceTemplate: "${RavenwoodTestConfigTemplate}",
  HostTemplate:   "${RavenwoodTestConfigTemplate}",
 })
 r.data = android.PathsForModuleSrc(ctx, r.testProperties.Data.GetOrDefault(ctx, nil))
 r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...)
 r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_data)...)
 r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_prefer32_data)...)
 r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Host_common_data)...)
 r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Host_first_data)...)

 r.data = android.SortedUniquePaths(r.data)

 var testData []android.DataPath
 for _, data := range r.data {
  dataPath := android.DataPath{SrcPath: data}
  testData = append(testData, dataPath)
 }
 for _, d := range r.extraOutputFiles {
  testData = append(testData, android.DataPath{SrcPath: d})
 }

 // When setting the manifest property, we only want to set it for aaptProperties.
 // Explicitly remove it from the Module properties to prevent it from using
 // AndroidManifest.xml as JAR manifest, creating a malformed JAR file.
 r.Module.properties.Manifest = proptools.Configurable[string]{}

 // Build resources before Java sources.
 var resourceApk android.Path
 if proptools.Bool(r.ravenwoodTestProperties.Build_resources) {
  r.aaptBuildActions(ctx)
  resourceApk = r.aapt.exportPackage
 }

 // Always enable Ravenizer for ravenwood tests.
 r.Library.ravenizer.enabled = true

 r.Library.GenerateAndroidBuildActions(ctx)
 // r.Library.GenerateAndroidBuildActions() may fail, stop here to avoid overwriting its errors
 // with new ones.
 if ctx.Failed() {
  return
 }

 // Start by depending on all files installed by dependencies
 var installDeps android.InstallPaths

 // All JNI libraries included in the runtime
 var runtimeJniModuleNames map[string]bool

 utils := ctx.GetDirectDepsProxyWithTag(ravenwoodUtilsTag)[0]
 for _, installFile := range android.GetInstallFiles(
  ctx, utils).InstallFiles {
  installDeps = append(installDeps, installFile)
 }

 runtime := ctx.GetDirectDepsProxyWithTag(ravenwoodRuntimeTag)[0]
 for _, installFile := range android.GetInstallFiles(
  ctx, runtime).InstallFiles {
  installDeps = append(installDeps, installFile)
 }
 jniDeps, ok := android.OtherModuleProvider(ctx, runtime, ravenwoodLibgroupJniDepProvider)
 if ok {
  runtimeJniModuleNames = jniDeps.names
 }

 // Also remember what JNI libs are in the runtime.

 // Also depend on our config
 installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
 installConfig := ctx.InstallFile(installPath, ctx.ModuleName()+".config", r.testConfig)
 installDeps = append(installDeps, installConfig)

 // Depend on the JNI libraries, but don't install the ones that the runtime already
 // contains.
 soInstallPath := installPath.Join(ctx, getLibPath(r.forceArchType))
 for _, jniLib := range collectTransitiveJniDeps(ctx) {
  if _, ok := runtimeJniModuleNames[jniLib.name]; ok {
   continue // Runtime already includes it.
  }
  installJni := ctx.InstallFile(soInstallPath, jniLib.path.Base(), jniLib.path)
  installDeps = append(installDeps, installJni)
 }

 resPath := "ravenwood-res-apks"
 resApkInstallPath := installPath.Join(ctx, resPath)

 var resApkName string
 var targetResApkName string

 if resourceApk != nil {
  installResApk := ctx.InstallFile(resApkInstallPath, "ravenwood-res.apk", resourceApk)
  installDeps = append(installDeps, installResApk)
  resApkName = "ravenwood-res.apk"
 }

 if resApk := ctx.GetDirectDepsProxyWithTag(ravenwoodTargetResourceApkTag); len(resApk) > 0 {
  installFile := android.OutputFileForModule(ctx, resApk[0], "")
  installResApk := ctx.InstallFile(resApkInstallPath, "ravenwood-target-res.apk", installFile)
  installDeps = append(installDeps, installResApk)
  targetResApkName = "ravenwood-target-res.apk"
 }

 // Generate manifest properties
 propertiesOutputPath := android.PathForModuleGen(ctx, "ravenwood.properties")

 targetSdkVersion := proptools.StringDefault(r.deviceProperties.Target_sdk_version, "")
 targetSdkVersionInt := r.TargetSdkVersion(ctx).FinalOrFutureInt() // FinalOrFutureInt may be 10000.
 packageName := r.aapt.aaptProperties.Package_name.GetOrDefault(ctx, "")
 targetPackageName := proptools.StringDefault(r.ravenwoodTestProperties.Target_package_name, "")
 instClassName := proptools.StringDefault(r.ravenwoodTestProperties.Instrumentation_class, "")

 resApkPath := ""
 if resApkName != "" {
  resApkPath = resPath + "/" + resApkName
 }
 targetResApkPath := ""
 if targetResApkName != "" {
  targetResApkPath = resPath + "/" + targetResApkName
 }

 propertiesContents := fmt.Sprintf(`
targetSdkVersionInt=%d
targetSdkVersionRaw=%s
packageName=%s
targetPackageName=%s
instrumentationClass=%s
moduleName=%s
resourceApk=%s
targetResourceApk=%s
`, targetSdkVersionInt, targetSdkVersion, packageName, targetPackageName, instClassName, ctx.ModuleName(), resApkPath, targetResApkPath)

 propertiesContents = strings.TrimPrefix(propertiesContents, "\n")

 android.WriteFileRule(ctx, propertiesOutputPath, propertiesContents)

 installProps := ctx.InstallFile(installPath, "ravenwood.properties", propertiesOutputPath)
 installDeps = append(installDeps, installProps)

 // Copy data files
 for _, data := range r.data {
  installedData := ctx.InstallFile(installPath, data.Rel(), data)
  installDeps = append(installDeps, installedData)
 }

 // Install our JAR with all dependencies
 ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.outputFile, installDeps...)

 moduleInfoJSON := ctx.ModuleInfoJSON()
 if _, ok := r.testConfig.(android.WritablePath); ok {
  moduleInfoJSON.AutoTestConfig = []string{"true"}
 }
 if r.testConfig != nil {
  moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, r.testConfig.String())
 }
 moduleInfoJSON.CompatibilitySuites = []string{"general-tests", "ravenwood-tests"}

 android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
  TestSuites: r.TestSuites(),
 })
}

func (r *ravenwoodTest) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) {
 r.Library.IDEInfo(ctx, dpInfo)
 r.aapt.IDEInfo(ctx, dpInfo)
}

// This method is adapted from AndroidApp.aaptBuildActions() in app.go, with changes
// irrelevant to RavenwoodTest removed.
func (r *ravenwoodTest) aaptBuildActions(ctx android.ModuleContext) {
 usePlatformAPI := proptools.Bool(r.Module.deviceProperties.Platform_apis)
 if ctx.Module().(android.SdkContext).SdkVersion(ctx).Kind == android.SdkModule {
  usePlatformAPI = true
 }
 r.aapt.usesNonSdkApis = usePlatformAPI

 aconfigTextFilePaths := getAconfigFilePaths(ctx)

 r.aapt.buildActions(ctx,
  aaptBuildActionOptions{
   sdkContext:                     android.SdkContext(r),
   enforceDefaultTargetSdkVersion: true,
   forceNonFinalResourceIDs:       true,
   aconfigTextFiles:               aconfigTextFilePaths,
   usesLibrary:                    &r.usesLibrary,
  },
 )

 android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{
  AconfigTextFiles: aconfigTextFilePaths,
 })

 // Add R classes into classpath
 if r.useResourceProcessorBusyBox(ctx) {
  // When building an app with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox has already
  // created R.class files that provide IDs for resources in busybox/R.jar.  Pass that file in the
  // classpath when compiling everything else, and add it to the final classes jar.
  r.extraClasspathJars = append(r.extraClasspathJars, r.aapt.rJar)
  r.extraCombinedJars = append(r.extraCombinedJars, r.aapt.rJar)
 } else {
  // When building an app without ResourceProcessorBusyBox the aapt2 rule creates R.srcjar containing
  // R.java files for the app's package and the packages from all transitive static android_library
  // dependencies.  Compile the srcjar alongside the rest of the sources.
  r.extraSrcJars = append(r.extraSrcJars, r.aapt.aaptSrcJar)
 }
}

type ravenwoodDataProperties struct {
 // The name of the subdirectory under the ravenwood runtime directory to install the files.
 Path string

 // The files to install.
 Srcs []string `android:"path,arch_variant"`
}

type ravenwoodLibgroupProperties struct {
 Libs []string

 Jni_libs proptools.Configurable[[]string]

 // We use this to copy various data files to the ravenwood runtime directory.
 Data []ravenwoodDataProperties

 // "ravenwood-runtime" uses it to specify "sub" runtimes,
 // which allows partially updating ravenwood-runtime without
 // rebuilding the downstream modules.
 Subruntimes []string

 // Subruntimes msut set it to "ravenwood-runtime" so that
 // the output files will be installed in "ravenwood-runtime/".
 Install_name *string
}

type ravenwoodLibgroup struct {
 android.ModuleBase
 // TODO(b/461815001): remove this and replace usage of WalkDepsProxy with
 //  VisitDirectDepsProxy and DepSets.
 blueprint.ModuleUsesIncrementalWalkDeps

 ravenwoodLibgroupProperties ravenwoodLibgroupProperties

 forceOSType   android.OsType
 forceArchType android.ArchType
}

func ravenwoodLibgroupFactory() android.Module {
 module := &ravenwoodLibgroup{}
 module.AddProperties(&module.ravenwoodLibgroupProperties)

 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
 return module
}

// @auto-generate: gob
type ravenwoodLibgroupInfo struct {
 libs []string
}

var ravenwoodLibgroupInfoProvider = blueprint.NewMutatorProvider[ravenwoodLibgroupInfo]("deps")

func (r *ravenwoodLibgroup) InstallInTestcases() bool { return true }
func (r *ravenwoodLibgroup) InstallForceOS() (*android.OsType, *android.ArchType) {
 return &r.forceOSType, &r.forceArchType
}
func (r *ravenwoodLibgroup) TestSuites() []string {
 return []string{
  "general-tests",
  "ravenwood-tests",
 }
}

func (r *ravenwoodLibgroup) installName() string {
 return proptools.StringDefault(r.ravenwoodLibgroupProperties.Install_name, r.BaseModuleName())
}

func (r *ravenwoodLibgroup) DepsMutator(ctx android.BottomUpMutatorContext) {
 // Always depends on our underlying libs
 for _, lib := range r.ravenwoodLibgroupProperties.Libs {
  ctx.AddVariationDependencies(nil, ravenwoodLibContentTag, lib)
 }
 for _, lib := range r.ravenwoodLibgroupProperties.Jni_libs.GetOrDefault(ctx, nil) {
  ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniLibTag, lib)
 }
 for _, lib := range r.ravenwoodLibgroupProperties.Subruntimes {
  ctx.AddVariationDependencies(nil, ravenwoodLibSubruntimeTag, lib)
 }

 if r.Name() == ravenwoodRuntimeName {
  ctx.AddVariationDependencies(nil, allAconfigModuleTag, aconfig.AllAconfigModule)
 }

 android.SetProvider(ctx, ravenwoodLibgroupInfoProvider, ravenwoodLibgroupInfo{
  libs: r.ravenwoodLibgroupProperties.Libs,
 })
}

func (r *ravenwoodLibgroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 r.forceOSType = ctx.Config().BuildOS
 r.forceArchType = ctx.Config().BuildArch

 jniDepNames := make(map[string]bool)

 // We need to build subruntimes too, so collect their install files.
 var installDeps android.InstallPaths
 for _, subruntime := range ctx.GetDirectDepsProxyWithTag(ravenwoodLibSubruntimeTag) {
  jniDeps, ok := android.OtherModuleProvider(ctx, subruntime, ravenwoodLibgroupJniDepProvider)
  if ok {
   maps.Copy(jniDepNames, jniDeps.names)
  }
  for _, installFile := range android.GetInstallFiles(
   ctx, subruntime).InstallFiles {
   installDeps = append(installDeps, installFile)
  }
 }

 // Collect the JNI dependencies, including the transitive deps.
 jniLibs := collectTransitiveJniDeps(ctx)

 for _, jni := range jniLibs {
  jniDepNames[jni.name] = true
 }
 android.SetProvider(ctx, ravenwoodLibgroupJniDepProvider, ravenwoodLibgroupJniDepProviderInfo{
  names: jniDepNames,
 })

 install := func(to android.InstallPath, srcs ...android.Path) {
  for _, s := range srcs {
   ctx.InstallFile(to, s.Base(), s, installDeps...)
  }
 }

 // Install our runtime into expected location for packaging
 installPath := android.PathForModuleInstall(ctx, r.installName())
 for _, lib := range r.ravenwoodLibgroupProperties.Libs {
  libModule := ctx.GetDirectDepProxyWithTag(lib, ravenwoodLibContentTag)

  reportMissing := func() {
   if ctx.Config().AllowMissingDependencies() {
    ctx.AddMissingDependencies([]string{lib})
   } else {
    ctx.PropertyErrorf("lib", "missing dependency %q", lib)
   }
  }

  if libModule.IsNil() {
   reportMissing()
   continue
  }
  if dep, ok := android.OtherModuleProvider(ctx, libModule, JavaInfoProvider); ok {
   if len(dep.ImplementationAndResourcesJars) > 1 {
    jarName := android.OutputFileForModule(ctx, libModule, "").Base()
    outputFile := android.PathForModuleOut(ctx, "combined", jarName)
    TransformJarsToJar(ctx, outputFile, "combine", dep.ImplementationAndResourcesJars,
     android.OptionalPath{}, false, nil, nil)
    install(installPath, outputFile)
   } else if len(dep.ImplementationAndResourcesJars) == 1 {
    install(installPath, dep.ImplementationAndResourcesJars[0])
   } else {
    reportMissing()
   }
  } else {
   reportMissing()
  }
 }

 soInstallPath := android.PathForModuleInstall(ctx, r.installName()).Join(ctx, getLibPath(r.forceArchType))
 for _, jniLib := range jniLibs {
  install(soInstallPath, jniLib.path)
 }

 for _, data := range r.ravenwoodLibgroupProperties.Data {
  dataInstallPath := installPath.Join(ctx, data.Path)
  dataSrcs := android.PathsForModuleSrc(ctx, data.Srcs)
  for _, file := range dataSrcs {
   install(dataInstallPath, file)
  }
 }

 // Copy aconfig flag storage files.
 if r.Name() == ravenwoodRuntimeName {
  allAconfigFound := false
  if allAconfig := ctx.GetDirectDepProxyWithTag(aconfig.AllAconfigModule, allAconfigModuleTag); !allAconfig.IsNil() {
   aadi, ok := android.OtherModuleProvider(ctx, allAconfig, aconfig.AllAconfigDeclarationsInfoProvider)
   if ok {
    // Binary proto file and the text proto.
    // We don't really use the text proto file, but having this would make debugging easier.
    install(installPath.Join(ctx, "aconfig/metadata/aconfig/etc"), aadi.ParsedFlagsFile, aadi.TextProtoFlagsFile)

    // The "new" storage files.
    install(installPath.Join(ctx, "aconfig/metadata/aconfig/maps"), aadi.StoragePackageMap, aadi.StorageFlagMap)
    install(installPath.Join(ctx, "aconfig/metadata/aconfig/boot"), aadi.StorageFlagVal, aadi.StorageFlagInfo)

    allAconfigFound = true
   }
  }
  if !allAconfigFound {
   if ctx.Config().AllowMissingDependencies() {
    ctx.AddMissingDependencies([]string{aconfig.AllAconfigModule})
   } else {
    ctx.ModuleErrorf("missing dependency %q", aconfig.AllAconfigModule)
   }
  }
 }

 // Normal build should perform install steps
 ctx.Phony(r.BaseModuleName(), android.PathForPhony(ctx, r.BaseModuleName()+"-install"))

 android.SetProvider(ctx, android.TestSuiteInfoProvider, android.TestSuiteInfo{
  TestSuites: r.TestSuites(),
 })
}

// collectTransitiveJniDeps returns all JNI dependencies, including transitive
// ones, including NDK / stub libs. (Because Ravenwood has no "preinstalled" libraries)
func collectTransitiveJniDeps(ctx android.ModuleContext) []jniLib {
 libs, _ := collectJniDeps(ctx, true, false, nil)
 return libs
}

[Dauer der Verarbeitung: 0.24 Sekunden, vorverarbeitet 2026-06-28]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik