Express no{,_lib}crt via features vs attrs

Given that we can map them directly to disabling the
corresponding Bazel features: `-{link_,use_lib}crt`

Test: Existing (adapted) Unit Tests
Test: bp2build.sh
Change-Id: Ib502f6fb929ace8e86a1001e3cc21f399317500c
diff --git a/cc/binary.go b/cc/binary.go
index a04b174..532b42a 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -151,7 +151,7 @@
 // modules common to most binaries, such as bionic libraries.
 func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
 	deps = binary.baseLinker.linkerDeps(ctx, deps)
-	if !Bool(binary.baseLinker.Properties.Nocrt) {
+	if binary.baseLinker.Properties.crt() {
 		if binary.static() {
 			deps.CrtBegin = ctx.toolchain().CrtBeginStaticBinary()
 			deps.CrtEnd = ctx.toolchain().CrtEndStaticBinary()
@@ -630,8 +630,6 @@
 		Local_includes:    baseAttrs.localIncludes,
 		Absolute_includes: baseAttrs.absoluteIncludes,
 		Linkopts:          baseAttrs.linkopts,
-		Link_crt:          baseAttrs.linkCrt,
-		Use_libcrt:        baseAttrs.useLibcrt,
 		Use_version_lib:   baseAttrs.useVersionLib,
 		Rtti:              baseAttrs.rtti,
 		Stl:               baseAttrs.stl,
@@ -695,10 +693,7 @@
 
 	Linkopts                 bazel.StringListAttribute
 	Additional_linker_inputs bazel.LabelListAttribute
-
-	Link_crt        bazel.BoolAttribute
-	Use_libcrt      bazel.BoolAttribute
-	Use_version_lib bazel.BoolAttribute
+	Use_version_lib          bazel.BoolAttribute
 
 	Rtti    bazel.BoolAttribute
 	Stl     *string
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6c5505a..250241c 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -965,8 +965,6 @@
 	systemDynamicDeps                bazel.LabelListAttribute
 	usedSystemDynamicDepAsDynamicDep map[string]bool
 
-	linkCrt                       bazel.BoolAttribute
-	useLibcrt                     bazel.BoolAttribute
 	useVersionLib                 bazel.BoolAttribute
 	linkopts                      bazel.StringListAttribute
 	additionalLinkerInputs        bazel.LabelListAttribute
@@ -1138,6 +1136,13 @@
 		}
 	}
 
+	if !props.libCrt() {
+		axisFeatures = append(axisFeatures, "-use_libcrt")
+	}
+	if !props.crt() {
+		axisFeatures = append(axisFeatures, "-link_crt")
+	}
+
 	// This must happen before the addition of flags for Version Script and
 	// Dynamic List, as these flags must be split on spaces and those must not
 	linkerFlags = parseCommandLineFlags(linkerFlags, filterOutClangUnknownCflags)
@@ -1157,16 +1162,6 @@
 
 	la.additionalLinkerInputs.SetSelectValue(axis, config, additionalLinkerInputs)
 	la.linkopts.SetSelectValue(axis, config, linkerFlags)
-	la.useLibcrt.SetSelectValue(axis, config, props.libCrt())
-
-	// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
-	if props.crt() != nil {
-		if axis == bazel.NoConfigAxis {
-			la.linkCrt.SetSelectValue(axis, config, props.crt())
-		} else if axis == bazel.ArchConfigurationAxis {
-			ctx.ModuleErrorf("nocrt is not supported for arch variants")
-		}
-	}
 
 	if axisFeatures != nil {
 		la.features.SetSelectValue(axis, config, axisFeatures)
diff --git a/cc/library.go b/cc/library.go
index 9421007..f33f37e 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -243,7 +243,6 @@
 	Local_includes         bazel.StringListAttribute
 	Absolute_includes      bazel.StringListAttribute
 	Linkopts               bazel.StringListAttribute
-	Use_libcrt             bazel.BoolAttribute
 	Rtti                   bazel.BoolAttribute
 
 	Stl     *string
@@ -251,7 +250,6 @@
 	C_std   *string
 
 	// This is shared only.
-	Link_crt                 bazel.BoolAttribute
 	Additional_linker_inputs bazel.LabelListAttribute
 
 	// Common properties shared between both shared and static variants.
@@ -360,7 +358,6 @@
 		Export_system_includes:   exportedIncludes.SystemIncludes,
 		Local_includes:           compilerAttrs.localIncludes,
 		Absolute_includes:        compilerAttrs.absoluteIncludes,
-		Use_libcrt:               linkerAttrs.useLibcrt,
 		Rtti:                     compilerAttrs.rtti,
 		Stl:                      compilerAttrs.stl,
 		Cpp_std:                  compilerAttrs.cppStd,
@@ -381,8 +378,6 @@
 		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,
 		Cpp_std:                  compilerAttrs.cppStd,
@@ -1500,7 +1495,7 @@
 		deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, library.StaticProperties.Static.Export_shared_lib_headers...)
 		deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, library.StaticProperties.Static.Export_static_lib_headers...)
 	} else if library.shared() {
-		if !Bool(library.baseLinker.Properties.Nocrt) {
+		if library.baseLinker.Properties.crt() {
 			deps.CrtBegin = append(deps.CrtBegin, ctx.toolchain().CrtBeginSharedLibrary()...)
 			deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtEndSharedLibrary()...)
 		}
@@ -2884,13 +2879,10 @@
 		commonAttrs.Deps.Add(baseAttributes.protoDependency)
 		attrs = &bazelCcLibraryStaticAttributes{
 			staticOrSharedAttributes: commonAttrs,
-
-			Use_libcrt: linkerAttrs.useLibcrt,
-
-			Rtti:    compilerAttrs.rtti,
-			Stl:     compilerAttrs.stl,
-			Cpp_std: compilerAttrs.cppStd,
-			C_std:   compilerAttrs.cStd,
+			Rtti:                     compilerAttrs.rtti,
+			Stl:                      compilerAttrs.stl,
+			Cpp_std:                  compilerAttrs.cppStd,
+			C_std:                    compilerAttrs.cStd,
 
 			Export_includes:          exportedIncludes.Includes,
 			Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
@@ -2915,8 +2907,6 @@
 			Asflags:    asFlags,
 
 			Linkopts:        linkerAttrs.linkopts,
-			Link_crt:        linkerAttrs.linkCrt,
-			Use_libcrt:      linkerAttrs.useLibcrt,
 			Use_version_lib: linkerAttrs.useVersionLib,
 
 			Rtti:    compilerAttrs.rtti,
@@ -2974,13 +2964,11 @@
 type bazelCcLibraryStaticAttributes struct {
 	staticOrSharedAttributes
 
-	Use_libcrt      bazel.BoolAttribute
 	Use_version_lib bazel.BoolAttribute
-
-	Rtti    bazel.BoolAttribute
-	Stl     *string
-	Cpp_std *string
-	C_std   *string
+	Rtti            bazel.BoolAttribute
+	Stl             *string
+	Cpp_std         *string
+	C_std           *string
 
 	Export_includes          bazel.StringListAttribute
 	Export_absolute_includes bazel.StringListAttribute
@@ -3000,10 +2988,7 @@
 type bazelCcLibrarySharedAttributes struct {
 	staticOrSharedAttributes
 
-	Linkopts bazel.StringListAttribute
-	Link_crt bazel.BoolAttribute // Only for linking shared library (and cc_binary)
-
-	Use_libcrt      bazel.BoolAttribute
+	Linkopts        bazel.StringListAttribute
 	Use_version_lib bazel.BoolAttribute
 
 	Rtti    bazel.BoolAttribute
diff --git a/cc/linker.go b/cc/linker.go
index 371d78d..e49b97d 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -237,29 +237,14 @@
 	Exclude_shared_libs []string `android:"arch_variant"`
 }
 
-func invertBoolPtr(value *bool) *bool {
-	if value == nil {
-		return nil
-	}
-	ret := !(*value)
-	return &ret
+func (blp *BaseLinkerProperties) crt() bool {
+	// Since crt is enabled for almost every module compiling against the Bionic runtime,
+	// we interpret `nil` as  enabled.
+	return blp.Nocrt == nil || !*blp.Nocrt
 }
 
-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)
+func (blp *BaseLinkerProperties) libCrt() bool {
+	return blp.No_libcrt == nil || !*blp.No_libcrt
 }
 
 func NewBaseLinker(sanitize *sanitize) *baseLinker {
@@ -392,7 +377,7 @@
 
 	if ctx.toolchain().Bionic() {
 		// libclang_rt.builtins has to be last on the command line
-		if !Bool(linker.Properties.No_libcrt) && !ctx.header() {
+		if linker.Properties.libCrt() && !ctx.header() {
 			deps.UnexportedStaticLibs = append(deps.UnexportedStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
 		}
 
@@ -415,7 +400,7 @@
 			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
 		}
 	} else if ctx.toolchain().Musl() {
-		if !Bool(linker.Properties.No_libcrt) && !ctx.header() {
+		if linker.Properties.libCrt() && !ctx.header() {
 			deps.UnexportedStaticLibs = append(deps.UnexportedStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
 		}
 	}