Versioned CRT objects are built with correct __ANDROID_API__

Background: `min_sdk_version` of a crt object is the oldest SDK version
that the crt object supports. When it's set to for example 16, Soong
creates a number of versioned variants of the crt object starting from
16 to the latest version. The variant for version X is provided to NDK
clients having `min_sdk_version` set to X.

Problem: all versioned variants of a crt object were built with `-target
<arch>-linux-android16`. Therefore they all have been with `#define __ANDROID_API__
16`.  This is because the mutated variants still have the same
min_sdk_version property and the clang triple follows min_sdk_version,
not sdk_version. This is too conservative and against our intention to
provide the latest crt object that matches with the min_sdk_version of
the client.

In the other hand, the platform(non-sdk) variant of the crt object
doesn't have such a problem. min_sdk_version is completely ignored.
However, this is a bug and will be fixed by aosp/1640364. As a side
effect of the fixing, the platform variant will begin to built with a
very old __ANDROID_API__ which unnecessarily turns off the new platform
features like the TLS segment over-alignment.

This change fixes the problems:

* For the versioned variants of crt objects, we set both
`min_sdk_version` and `sdk_versio` to the version that the variant is
created for.

* For the platform variant of crt objects, `min_sdk_version` is force
reset to "current".

Bug: 183191008
Test: m

Change-Id: I8c9d0fcea816de8cd1532dac4a47eee4f726c037
This commit is contained in:
Jiyong Park 2021-03-19 22:18:04 +09:00
parent a008fb08cf
commit fdaa5f7164
5 changed files with 78 additions and 1 deletions

View File

@ -1363,6 +1363,19 @@ func (ctx *moduleContextImpl) minSdkVersion() string {
if ver == "apex_inherit" || ver == "" {
ver = ctx.sdkVersion()
}
// For crt objects, the meaning of min_sdk_version is very different from other types of
// module. For them, min_sdk_version defines the oldest version that the build system will
// create versioned variants for. For example, if min_sdk_version is 16, then sdk variant of
// the crt object has local variants of 16, 17, ..., up to the latest version. sdk_version
// and min_sdk_version properties of the variants are set to the corresponding version
// numbers. However, the platform (non-sdk) variant of the crt object is left untouched.
// min_sdk_version: 16 doesn't actually mean that the platform variant has to support such
// an old version. Since the variant is for the platform, it's preferred to target the
// latest version.
if ctx.mod.SplitPerApiLevel() && !ctx.isSdkVariant() {
ver = strconv.Itoa(android.FutureApiLevelInt)
}
// Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers
sdkVersionInt, err := strconv.Atoi(ctx.sdkVersion())
minSdkVersionInt, err2 := strconv.Atoi(ver)
@ -1933,9 +1946,14 @@ func GetCrtVariations(ctx android.BottomUpMutatorContext,
return nil
}
if m.UseSdk() {
// Choose the CRT that best satisfies the min_sdk_version requirement of this module
minSdkVersion := m.MinSdkVersion()
if minSdkVersion == "" || minSdkVersion == "apex_inherit" {
minSdkVersion = m.SdkVersion()
}
return []blueprint.Variation{
{Mutator: "sdk", Variation: "sdk"},
{Mutator: "version", Variation: m.SdkVersion()},
{Mutator: "version", Variation: minSdkVersion},
}
}
return []blueprint.Variation{

View File

@ -3640,6 +3640,59 @@ func TestMinSdkVersionInClangTriple(t *testing.T) {
android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android29")
}
func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
ctx := testCc(t, `
cc_object {
name: "crt_foo",
srcs: ["foo.c"],
crt: true,
stl: "none",
min_sdk_version: "28",
}`)
arch := "android_arm64_armv8-a"
for _, v := range []string{"", "28", "29", "30", "current"} {
var variant string
if v == "" {
variant = arch
} else {
variant = arch + "_sdk_" + v
}
cflags := ctx.ModuleForTests("crt_foo", variant).Rule("cc").Args["cFlags"]
vNum := v
if v == "current" || v == "" {
vNum = "10000"
}
expected := "-target aarch64-linux-android" + vNum + " "
android.AssertStringDoesContain(t, "cflag", cflags, expected)
}
}
func TestUseCrtObjectOfCorrectVersion(t *testing.T) {
ctx := testCc(t, `
cc_binary {
name: "bin",
srcs: ["foo.c"],
stl: "none",
min_sdk_version: "29",
sdk_version: "current",
}
`)
// Sdk variant uses the crt object of the matching min_sdk_version
variant := "android_arm64_armv8-a_sdk"
crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
variant+"_29/crtbegin_dynamic.o")
// platform variant uses the crt object built for platform
variant = "android_arm64_armv8-a"
crt = ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
android.AssertStringDoesContain(t, "crt dep of platform variant", crt,
variant+"/crtbegin_dynamic.o")
}
type MemtagNoteType int
const (

View File

@ -1914,6 +1914,7 @@ func createPerApiVersionVariations(mctx android.BottomUpMutatorContext, minSdkVe
for i, module := range modules {
module.(*Module).Properties.Sdk_version = StringPtr(versionStrs[i])
module.(*Module).Properties.Min_sdk_version = StringPtr(versionStrs[i])
}
}

View File

@ -111,6 +111,7 @@ type LinkableInterface interface {
InProduct() bool
SdkVersion() string
MinSdkVersion() string
AlwaysSdk() bool
IsSdkVariant() bool

View File

@ -256,6 +256,10 @@ func (mod *Module) SdkVersion() string {
return ""
}
func (mod *Module) MinSdkVersion() string {
return ""
}
func (mod *Module) AlwaysSdk() bool {
return false
}