Set __<libname>_API__ macro when building against stubs
When building against libFoo#ver, __LIBFOO_API__ macro is set to ver so
that headers from libFoo can be conditionally compiled (e.g., hide APIs
that are not available for the version, etc.)
Bug: 112672359
Test: m (cc_test added)
Change-Id: I863ef95b385cdd842eec1bf34e81f44b5e3b58b3
diff --git a/cc/cc_test.go b/cc/cc_test.go
index fba38a2..e4904f2 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1738,13 +1738,16 @@
ctx := testCc(t, `
cc_library_shared {
name: "libFoo",
+ srcs: ["foo.c"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
+
cc_library_shared {
name: "libBar",
+ srcs: ["bar.c"],
shared_libs: ["libFoo#1"],
}`)
@@ -1786,4 +1789,11 @@
if !strings.Contains(libFlags, libFoo1StubPath) {
t.Errorf("%q is not found in %q", libFoo1StubPath, libFlags)
}
+
+ libBarCompileRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_core_shared").Rule("cc")
+ cFlags := libBarCompileRule.Args["cFlags"]
+ libFoo1VersioningMacro := "-D__LIBFOO_API__=1"
+ if !strings.Contains(cFlags, libFoo1VersioningMacro) {
+ t.Errorf("%q is not found in %q", libFoo1VersioningMacro, cFlags)
+ }
}
diff --git a/cc/library.go b/cc/library.go
index aafe365..975f325 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -15,7 +15,9 @@
package cc
import (
+ "regexp"
"strings"
+ "sync"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
@@ -443,6 +445,8 @@
return name + library.MutatedProperties.VariantName
}
+var versioningMacroNamesListMutex sync.Mutex
+
func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) {
location := InstallInSystem
if library.baseLinker.sanitize.inSanitizerDir() {
@@ -453,6 +457,18 @@
// Let baseLinker know whether this variant is for stubs or not, so that
// it can omit things that are not required for linking stubs.
library.baseLinker.dynamicProperties.BuildStubs = library.buildStubs()
+
+ if library.buildStubs() {
+ macroNames := versioningMacroNamesList(ctx.Config())
+ myName := versioningMacroName(ctx.ModuleName())
+ versioningMacroNamesListMutex.Lock()
+ defer versioningMacroNamesListMutex.Unlock()
+ if (*macroNames)[myName] == "" {
+ (*macroNames)[myName] = ctx.ModuleName()
+ } else if (*macroNames)[myName] != ctx.ModuleName() {
+ ctx.ModuleErrorf("Macro name %q for versioning conflicts with macro name from module %q ", myName, (*macroNames)[myName])
+ }
+ }
}
func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
@@ -715,6 +731,10 @@
library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
}
+ if library.buildStubs() {
+ library.reexportFlags([]string{"-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion()})
+ }
+
return out
}
@@ -823,6 +843,23 @@
return library.MutatedProperties.StubsVersion
}
+func versioningMacroNamesList(config android.Config) *map[string]string {
+ return config.Once("versioningMacroNamesList", func() interface{} {
+ m := make(map[string]string)
+ return &m
+ }).(*map[string]string)
+}
+
+// alphanumeric and _ characters are preserved.
+// other characters are all converted to _
+var charsNotForMacro = regexp.MustCompile("[^a-zA-Z0-9_]+")
+
+func versioningMacroName(moduleName string) string {
+ macroName := charsNotForMacro.ReplaceAllString(moduleName, "_")
+ macroName = strings.ToUpper(moduleName)
+ return "__" + macroName + "_API__"
+}
+
func NewLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module := newModule(hod, android.MultilibBoth)