diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index 0ee0f0556..1cd48296c 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -34,6 +34,13 @@ var ( CommandDeps: []string{"$versionerCmd"}, }, "depsPath", "srcDir", "outDir") + + preprocessNdkHeader = pctx.AndroidStaticRule("preprocessNdkHeader", + blueprint.RuleParams{ + Command: "$preprocessor -o $out $in", + CommandDeps: []string{"$preprocessor"}, + }, + "preprocessor") ) func init() { @@ -279,3 +286,87 @@ func versionedNdkHeadersFactory() android.Module { return module } + +// preprocessed_ndk_header { +// name: "foo", +// preprocessor: "foo.sh", +// srcs: [...], +// to: "android", +// } +// +// Will invoke the preprocessor as: +// $preprocessor -o $SYSROOT/usr/include/android/needs_preproc.h $src +// For each src in srcs. +type preprocessedHeadersProperties struct { + // The preprocessor to run. Must be a program inside the source directory + // with no dependencies. + Preprocessor *string + + // Source path to the files to be preprocessed. + Srcs []string + + // Source paths that should be excluded from the srcs glob. + Exclude_srcs []string + + // Install path within the sysroot. This is relative to usr/include. + To *string + + // Path to the NOTICE file associated with the headers. + License *string +} + +type preprocessedHeadersModule struct { + android.ModuleBase + + properties preprocessedHeadersProperties + + installPaths android.Paths + licensePath android.ModuleSrcPath +} + +func (m *preprocessedHeadersModule) DepsMutator(ctx android.BottomUpMutatorContext) { +} + +func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + if String(m.properties.License) == "" { + ctx.PropertyErrorf("license", "field is required") + } + + preprocessor := android.PathForModuleSrc(ctx, String(m.properties.Preprocessor)) + m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License)) + + srcFiles := ctx.ExpandSources(m.properties.Srcs, m.properties.Exclude_srcs) + installDir := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To)) + for _, src := range srcFiles { + installPath := installDir.Join(ctx, src.Base()) + m.installPaths = append(m.installPaths, installPath) + + ctx.Build(pctx, android.BuildParams{ + Rule: preprocessNdkHeader, + Description: "preprocess " + src.Rel(), + Input: src, + Output: installPath, + Args: map[string]string{ + "preprocessor": preprocessor.String(), + }, + }) + } + + if len(m.installPaths) == 0 { + ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs) + } +} + +func preprocessedNdkHeadersFactory() android.Module { + module := &preprocessedHeadersModule{} + + module.AddProperties(&module.properties) + + // Host module rather than device module because device module install steps + // do not get run when embedded in make. We're not any of the existing + // module types that can be exposed via the Android.mk exporter, so just use + // a host module. + android.InitAndroidArchModule(module, android.HostSupportedNoCross, android.MultilibFirst) + + return module +} diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index 1a467028e..144fc09f9 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -60,6 +60,7 @@ func init() { android.RegisterModuleType("ndk_headers", ndkHeadersFactory) android.RegisterModuleType("ndk_library", ndkLibraryFactory) android.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory) + android.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) android.RegisterSingletonType("ndk", NdkSingleton) pctx.Import("android/soong/common") @@ -112,6 +113,11 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { licensePaths = append(licensePaths, m.licensePath) } + if m, ok := module.(*preprocessedHeadersModule); ok { + installPaths = append(installPaths, m.installPaths...) + licensePaths = append(licensePaths, m.licensePath) + } + if m, ok := module.(*Module); ok { if installer, ok := m.installer.(*stubDecorator); ok { installPaths = append(installPaths, installer.installPath)