Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ada589f authored by Jingwen Chen's avatar Jingwen Chen
Browse files

Add support for nocrt by translating it to link_crt in bp2build.

If nocrt is true, then the compilation for cc_shared_library,
cc_binary (shared or static binaries) will _not_ link against their
respective crtbegin and crtend libraries.

nocrt is true only for the Bionic libraries themselves. For everything
else that links against the Bionic runtime, crtbegin and crtend
libraries are used. This makes the "nocrt: false" case the majority.
Hence, if nocrt is explicitly false, we omit the generating attribute in
bp2build.

If nocrt is explicitly true (link_crt is false), the Starlark macro will
disable the link_crt cc_toolchain feature.

Test: new tests
Test: CI
Fixes: 187928070
Fixes: 197946668
Change-Id: I8947789930e599dc802d8eae440859257d044475
parent 8f222742
Loading
Loading
Loading
Loading
+57 −16
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
package bp2build

import (
	"fmt"
	"testing"

	"android/soong/android"
@@ -1142,7 +1143,7 @@ cc_library {

func TestCCLibraryNoCrtTrue(t *testing.T) {
	runCcLibraryTestCase(t, bp2buildTestCase{
		description:                        "cc_library - simple example",
		description:                        "cc_library - nocrt: true emits attribute",
		moduleTypeUnderTest:                "cc_library",
		moduleTypeUnderTestFactory:         cc.LibraryFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
@@ -1150,23 +1151,23 @@ func TestCCLibraryNoCrtTrue(t *testing.T) {
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_headers { name: "some-headers" }
cc_library {
    name: "foo-lib",
    srcs: ["impl.cpp"],
    no_libcrt: true,
    nocrt: true,
    include_build_directory: false,
}
`,
		expectedBazelTargets: []string{`cc_library(
    name = "foo-lib",
    link_crt = False,
    srcs = ["impl.cpp"],
    use_libcrt = False,
)`}})
}

func TestCCLibraryNoCrtFalse(t *testing.T) {
	runCcLibraryTestCase(t, bp2buildTestCase{
		description:                        "cc_library - nocrt: false - does not emit attribute",
		moduleTypeUnderTest:                "cc_library",
		moduleTypeUnderTestFactory:         cc.LibraryFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
@@ -1174,23 +1175,22 @@ func TestCCLibraryNoCrtFalse(t *testing.T) {
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_headers { name: "some-headers" }
cc_library {
    name: "foo-lib",
    srcs: ["impl.cpp"],
    no_libcrt: false,
    nocrt: false,
    include_build_directory: false,
}
`,
		expectedBazelTargets: []string{`cc_library(
    name = "foo-lib",
    srcs = ["impl.cpp"],
    use_libcrt = True,
)`}})
}

func TestCCLibraryNoCrtArchVariant(t *testing.T) {
	runCcLibraryTestCase(t, bp2buildTestCase{
		description:                        "cc_library - nocrt in select",
		moduleTypeUnderTest:                "cc_library",
		moduleTypeUnderTestFactory:         cc.LibraryFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
@@ -1203,27 +1203,45 @@ cc_library {
    srcs: ["impl.cpp"],
    arch: {
        arm: {
            no_libcrt: true,
            nocrt: true,
        },
        x86: {
            no_libcrt: true,
            nocrt: false,
        },
    },
    include_build_directory: false,
}
`,
		expectedErr: fmt.Errorf("Android.bp:16:1: module \"foo-lib\": nocrt is not supported for arch variants"),
	})
}

func TestCCLibraryNoLibCrtTrue(t *testing.T) {
	runCcLibraryTestCase(t, bp2buildTestCase{
		description:                        "cc_library - simple example",
		moduleTypeUnderTest:                "cc_library",
		moduleTypeUnderTestFactory:         cc.LibraryFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
		filesystem: map[string]string{
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_headers { name: "some-headers" }
cc_library {
    name: "foo-lib",
    srcs: ["impl.cpp"],
    no_libcrt: true,
    include_build_directory: false,
}
`,
		expectedBazelTargets: []string{`cc_library(
    name = "foo-lib",
    srcs = ["impl.cpp"],
    use_libcrt = select({
        "//build/bazel/platforms/arch:arm": False,
        "//build/bazel/platforms/arch:x86": False,
        "//conditions:default": None,
    }),
    use_libcrt = False,
)`}})
}

func TestCCLibraryNoCrtArchVariantWithDefault(t *testing.T) {
func TestCCLibraryNoLibCrtFalse(t *testing.T) {
	runCcLibraryTestCase(t, bp2buildTestCase{
		moduleTypeUnderTest:                "cc_library",
		moduleTypeUnderTestFactory:         cc.LibraryFactory,
@@ -1232,10 +1250,33 @@ func TestCCLibraryNoCrtArchVariantWithDefault(t *testing.T) {
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_headers { name: "some-headers" }
cc_library {
    name: "foo-lib",
    srcs: ["impl.cpp"],
    no_libcrt: false,
    include_build_directory: false,
}
`,
		expectedBazelTargets: []string{`cc_library(
    name = "foo-lib",
    srcs = ["impl.cpp"],
    use_libcrt = True,
)`}})
}

func TestCCLibraryNoLibCrtArchVariant(t *testing.T) {
	runCcLibraryTestCase(t, bp2buildTestCase{
		moduleTypeUnderTest:                "cc_library",
		moduleTypeUnderTestFactory:         cc.LibraryFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
		filesystem: map[string]string{
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library {
    name: "foo-lib",
    srcs: ["impl.cpp"],
    arch: {
        arm: {
            no_libcrt: true,
@@ -1253,7 +1294,7 @@ cc_library {
    use_libcrt = select({
        "//build/bazel/platforms/arch:arm": False,
        "//build/bazel/platforms/arch:x86": False,
        "//conditions:default": True,
        "//conditions:default": None,
    }),
)`}})
}
+76 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
package bp2build

import (
	"fmt"
	"testing"

	"android/soong/android"
@@ -364,3 +365,78 @@ cc_library_shared {
)`},
	})
}

func TestCcLibrarySharedNoCrtTrue(t *testing.T) {
	runCcLibrarySharedTestCase(t, bp2buildTestCase{
		description:                        "cc_library_shared - nocrt: true emits attribute",
		moduleTypeUnderTest:                "cc_library_shared",
		moduleTypeUnderTestFactory:         cc.LibrarySharedFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
		filesystem: map[string]string{
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_shared {
    name: "foo_shared",
    srcs: ["impl.cpp"],
    nocrt: true,
    include_build_directory: false,
}
`,
		expectedBazelTargets: []string{`cc_library_shared(
    name = "foo_shared",
    link_crt = False,
    srcs = ["impl.cpp"],
)`}})
}

func TestCcLibrarySharedNoCrtFalse(t *testing.T) {
	runCcLibrarySharedTestCase(t, bp2buildTestCase{
		description:                        "cc_library_shared - nocrt: false doesn't emit attribute",
		moduleTypeUnderTest:                "cc_library_shared",
		moduleTypeUnderTestFactory:         cc.LibrarySharedFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
		filesystem: map[string]string{
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_shared {
    name: "foo_shared",
    srcs: ["impl.cpp"],
    nocrt: false,
    include_build_directory: false,
}
`,
		expectedBazelTargets: []string{`cc_library_shared(
    name = "foo_shared",
    srcs = ["impl.cpp"],
)`}})
}

func TestCcLibrarySharedNoCrtArchVariant(t *testing.T) {
	runCcLibrarySharedTestCase(t, bp2buildTestCase{
		description:                        "cc_library_shared - nocrt in select",
		moduleTypeUnderTest:                "cc_library_shared",
		moduleTypeUnderTestFactory:         cc.LibrarySharedFactory,
		moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
		filesystem: map[string]string{
			"impl.cpp": "",
		},
		blueprint: soongCcLibraryPreamble + `
cc_library_shared {
    name: "foo_shared",
    srcs: ["impl.cpp"],
    arch: {
        arm: {
            nocrt: true,
        },
        x86: {
            nocrt: false,
        },
    },
    include_build_directory: false,
}
`,
		expectedErr: fmt.Errorf("Android.bp:16:1: module \"foo_shared\": nocrt is not supported for arch variants"),
	})
}
+19 −0
Original line number Diff line number Diff line
@@ -364,6 +364,7 @@ type linkerAttributes struct {
	wholeArchiveDeps          bazel.LabelListAttribute
	systemDynamicDeps         bazel.LabelListAttribute

	linkCrt                       bazel.BoolAttribute
	useLibcrt                     bazel.BoolAttribute
	linkopts                      bazel.StringListAttribute
	versionScript                 bazel.LabelAttribute
@@ -398,6 +399,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module)

	var linkopts bazel.StringListAttribute
	var versionScript bazel.LabelAttribute
	var linkCrt bazel.BoolAttribute
	var useLibcrt bazel.BoolAttribute

	var stripKeepSymbols bazel.BoolAttribute
@@ -418,6 +420,9 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module)
		}
	}

	// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
	var disallowedArchVariantCrt bool

	for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
		for config, props := range configToProps {
			if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
@@ -457,9 +462,22 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module)
					versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
				}
				useLibcrt.SetSelectValue(axis, config, baseLinkerProps.libCrt())

				// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
				if baseLinkerProps.crt() != nil {
					if axis == bazel.NoConfigAxis {
						linkCrt.SetSelectValue(axis, config, baseLinkerProps.crt())
					} else if axis == bazel.ArchConfigurationAxis {
						disallowedArchVariantCrt = true
					}
				}
			}
		}
	}

	if disallowedArchVariantCrt {
		ctx.ModuleErrorf("nocrt is not supported for arch variants")
	}

	type productVarDep struct {
		// the name of the corresponding excludes field, if one exists
@@ -530,6 +548,7 @@ func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module)
		wholeArchiveDeps:          wholeArchiveDeps,
		systemDynamicDeps:         systemSharedDeps,

		linkCrt:       linkCrt,
		linkopts:      linkopts,
		useLibcrt:     useLibcrt,
		versionScript: versionScript,
+4 −0
Original line number Diff line number Diff line
@@ -252,6 +252,7 @@ type bazelCcLibraryAttributes struct {

	// This is shared only.
	Version_script bazel.LabelAttribute
	Link_crt       bazel.BoolAttribute

	// Common properties shared between both shared and static variants.
	Shared staticOrSharedAttributes
@@ -321,6 +322,7 @@ func CcLibraryBp2Build(ctx android.TopDownMutatorContext) {
		Local_includes:              compilerAttrs.localIncludes,
		Absolute_includes:           compilerAttrs.absoluteIncludes,
		Linkopts:                    linkerAttrs.linkopts,
		Link_crt:                    linkerAttrs.linkCrt,
		Use_libcrt:                  linkerAttrs.useLibcrt,
		Rtti:                        compilerAttrs.rtti,
		Stl:                         compilerAttrs.stl,
@@ -2415,6 +2417,7 @@ func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext,
			Asflags:    asFlags,
			Linkopts:   linkerAttrs.linkopts,

			Link_crt:   linkerAttrs.linkCrt,
			Use_libcrt: linkerAttrs.useLibcrt,
			Rtti:       compilerAttrs.rtti,
			Stl:        compilerAttrs.stl,
@@ -2472,6 +2475,7 @@ type bazelCcLibrarySharedAttributes struct {
	staticOrSharedAttributes

	Linkopts   bazel.StringListAttribute
	Link_crt   bazel.BoolAttribute // Only for linking shared library (and cc_binary)
	Use_libcrt bazel.BoolAttribute
	Rtti       bazel.BoolAttribute
	Stl        *string
+13 −0
Original line number Diff line number Diff line
@@ -238,6 +238,19 @@ func invertBoolPtr(value *bool) *bool {
	return &ret
}

func (blp *BaseLinkerProperties) crt() *bool {
	val := invertBoolPtr(blp.Nocrt)
	if val != nil && *val {
		// == True
		//
		// Since crt is enabled for almost every module compiling against the Bionic runtime,
		// use `nil` when it's enabled, and rely on the Starlark macro to set it to True by default.
		// This keeps the BUILD files clean.
		return nil
	}
	return val // can be False or nil
}

func (blp *BaseLinkerProperties) libCrt() *bool {
	return invertBoolPtr(blp.No_libcrt)
}