Handle no_libcrt in bp2build.

Test: ci/bp2build.sh
Bug: 187928307
Change-Id: Ib80c4318169652b322e5d878c8784679e42f87dd
diff --git a/bazel/properties.go b/bazel/properties.go
index 99119cd..7093d6c 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -350,6 +350,83 @@
 	return keys
 }
 
+type configToBools map[string]bool
+
+func (ctb configToBools) setValue(config string, value *bool) {
+	if value == nil {
+		if _, ok := ctb[config]; ok {
+			delete(ctb, config)
+		}
+		return
+	}
+	ctb[config] = *value
+}
+
+type configurableBools map[ConfigurationAxis]configToBools
+
+func (cb configurableBools) setValueForAxis(axis ConfigurationAxis, config string, value *bool) {
+	if cb[axis] == nil {
+		cb[axis] = make(configToBools)
+	}
+	cb[axis].setValue(config, value)
+}
+
+// BoolAttribute represents an attribute whose value is a single bool but may be configurable..
+type BoolAttribute struct {
+	Value *bool
+
+	ConfigurableValues configurableBools
+}
+
+// HasConfigurableValues returns whether there are configurable values for this attribute.
+func (ba BoolAttribute) HasConfigurableValues() bool {
+	return len(ba.ConfigurableValues) > 0
+}
+
+// SetSelectValue sets value for the given axis/config.
+func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, value *bool) {
+	axis.validateConfig(config)
+	switch axis.configurationType {
+	case noConfig:
+		ba.Value = value
+	case arch, os, osArch, productVariables:
+		if ba.ConfigurableValues == nil {
+			ba.ConfigurableValues = make(configurableBools)
+		}
+		ba.ConfigurableValues.setValueForAxis(axis, config, value)
+	default:
+		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+	}
+}
+
+// SelectValue gets the value for the given axis/config.
+func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool {
+	axis.validateConfig(config)
+	switch axis.configurationType {
+	case noConfig:
+		return ba.Value
+	case arch, os, osArch, productVariables:
+		if v, ok := ba.ConfigurableValues[axis][config]; ok {
+			return &v
+		} else {
+			return nil
+		}
+	default:
+		panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+	}
+}
+
+// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
+func (ba *BoolAttribute) SortedConfigurationAxes() []ConfigurationAxis {
+	keys := make([]ConfigurationAxis, 0, len(ba.ConfigurableValues))
+	for k := range ba.ConfigurableValues {
+		keys = append(keys, k)
+	}
+
+	sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
+	return keys
+}
+
 // labelListSelectValues supports config-specific label_list typed Bazel attribute values.
 type labelListSelectValues map[string]LabelList
 
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 6bdfc0e..4de5aae 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -567,6 +567,10 @@
 		} else {
 			return true
 		}
+	// Always print bools, if you want a bool attribute to be able to take the default value, use a
+	// bool pointer instead
+	case reflect.Bool:
+		return false
 	default:
 		if !value.IsValid() {
 			return true
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 6d0a9b2..33609af 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -23,12 +23,14 @@
 
 func TestGenerateSoongModuleTargets(t *testing.T) {
 	testCases := []struct {
+		description         string
 		bp                  string
 		expectedBazelTarget string
 	}{
 		{
+			description: "only name",
 			bp: `custom { name: "foo" }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -36,14 +38,16 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
+    bool_prop = False,
 )`,
 		},
 		{
+			description: "handles bool",
 			bp: `custom {
-	name: "foo",
-	ramdisk: true,
+  name: "foo",
+  bool_prop: true,
 }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -51,15 +55,16 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
-    ramdisk = True,
+    bool_prop = True,
 )`,
 		},
 		{
+			description: "string escaping",
 			bp: `custom {
-	name: "foo",
-	owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
+  name: "foo",
+  owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
 }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -67,15 +72,17 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
+    bool_prop = False,
     owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
 )`,
 		},
 		{
+			description: "single item string list",
 			bp: `custom {
-	name: "foo",
-	required: ["bar"],
+  name: "foo",
+  required: ["bar"],
 }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -83,15 +90,17 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
+    bool_prop = False,
     required = ["bar"],
 )`,
 		},
 		{
+			description: "list of strings",
 			bp: `custom {
-	name: "foo",
-	target_required: ["qux", "bazqux"],
+  name: "foo",
+  target_required: ["qux", "bazqux"],
 }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -99,6 +108,7 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
+    bool_prop = False,
     target_required = [
         "qux",
         "bazqux",
@@ -106,18 +116,19 @@
 )`,
 		},
 		{
+			description: "dist/dists",
 			bp: `custom {
-	name: "foo",
-	dist: {
-		targets: ["goal_foo"],
-		tag: ".foo",
-	},
-	dists: [{
-		targets: ["goal_bar"],
-		tag: ".bar",
-	}],
+  name: "foo",
+  dist: {
+    targets: ["goal_foo"],
+    tag: ".foo",
+  },
+  dists: [{
+    targets: ["goal_bar"],
+    tag: ".bar",
+  }],
 }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -125,6 +136,7 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
+    bool_prop = False,
     dist = {
         "tag": ".foo",
         "targets": ["goal_foo"],
@@ -136,20 +148,21 @@
 )`,
 		},
 		{
+			description: "put it together",
 			bp: `custom {
-	name: "foo",
-	required: ["bar"],
-	target_required: ["qux", "bazqux"],
-	ramdisk: true,
-	owner: "custom_owner",
-	dists: [
-		{
-			tag: ".tag",
-			targets: ["my_goal"],
-		},
-	],
+  name: "foo",
+  required: ["bar"],
+  target_required: ["qux", "bazqux"],
+  bool_prop: true,
+  owner: "custom_owner",
+  dists: [
+    {
+      tag: ".tag",
+      targets: ["my_goal"],
+    },
+  ],
 }
-		`,
+    `,
 			expectedBazelTarget: `soong_module(
     name = "foo",
     soong_module_name = "foo",
@@ -157,12 +170,12 @@
     soong_module_variant = "",
     soong_module_deps = [
     ],
+    bool_prop = True,
     dists = [{
         "tag": ".tag",
         "targets": ["my_goal"],
     }],
     owner = "custom_owner",
-    ramdisk = True,
     required = ["bar"],
     target_required = [
         "qux",
@@ -174,31 +187,33 @@
 
 	dir := "."
 	for _, testCase := range testCases {
-		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
-		ctx := android.NewTestContext(config)
+		t.Run(testCase.description, func(t *testing.T) {
+			config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+			ctx := android.NewTestContext(config)
 
-		ctx.RegisterModuleType("custom", customModuleFactory)
-		ctx.Register()
+			ctx.RegisterModuleType("custom", customModuleFactory)
+			ctx.Register()
 
-		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
-		android.FailIfErrored(t, errs)
-		_, errs = ctx.PrepareBuildActions(config)
-		android.FailIfErrored(t, errs)
+			_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+			android.FailIfErrored(t, errs)
+			_, errs = ctx.PrepareBuildActions(config)
+			android.FailIfErrored(t, errs)
 
-		codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
-		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
-		if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
-			t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
-		}
+			codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
+			bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+			if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
+				t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
+			}
 
-		actualBazelTarget := bazelTargets[0]
-		if actualBazelTarget.content != testCase.expectedBazelTarget {
-			t.Errorf(
-				"Expected generated Bazel target to be '%s', got '%s'",
-				testCase.expectedBazelTarget,
-				actualBazelTarget.content,
-			)
-		}
+			actualBazelTarget := bazelTargets[0]
+			if actualBazelTarget.content != testCase.expectedBazelTarget {
+				t.Errorf(
+					"Expected generated Bazel target to be '%s', got '%s'",
+					testCase.expectedBazelTarget,
+					actualBazelTarget.content,
+				)
+			}
+		})
 	}
 }
 
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index d84a7bb..c464cec 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -25,18 +25,18 @@
 	// See cc/testing.go for more context
 	soongCcLibraryPreamble = `
 cc_defaults {
-	name: "linux_bionic_supported",
+  name: "linux_bionic_supported",
 }
 
 toolchain_library {
-	name: "libclang_rt.builtins-x86_64-android",
-	defaults: ["linux_bionic_supported"],
-	vendor_available: true,
-	vendor_ramdisk_available: true,
-	product_available: true,
-	recovery_available: true,
-	native_bridge_supported: true,
-	src: "",
+  name: "libclang_rt.builtins-x86_64-android",
+  defaults: ["linux_bionic_supported"],
+  vendor_available: true,
+  vendor_ramdisk_available: true,
+  product_available: true,
+  recovery_available: true,
+  native_bridge_supported: true,
+  src: "",
 }`
 )
 
@@ -564,32 +564,32 @@
 cc_library {
     name: "a",
     srcs: [
-		"both_source.cpp",
-		"both_source.cc",
-		"both_source.c",
-		"both_source.s",
-		"both_source.S",
+    "both_source.cpp",
+    "both_source.cc",
+    "both_source.c",
+    "both_source.s",
+    "both_source.S",
         ":both_filegroup",
-	],
+  ],
     static: {
-		srcs: [
-			"static_source.cpp",
-			"static_source.cc",
-			"static_source.c",
-			"static_source.s",
-			"static_source.S",
-			":static_filegroup",
-		],
+    srcs: [
+      "static_source.cpp",
+      "static_source.cc",
+      "static_source.c",
+      "static_source.s",
+      "static_source.S",
+      ":static_filegroup",
+    ],
     },
     shared: {
-		srcs: [
-			"shared_source.cpp",
-			"shared_source.cc",
-			"shared_source.c",
-			"shared_source.s",
-			"shared_source.S",
-			":shared_filegroup",
-		],
+    srcs: [
+      "shared_source.cpp",
+      "shared_source.cc",
+      "shared_source.c",
+      "shared_source.s",
+      "shared_source.S",
+      ":shared_filegroup",
+    ],
     },
     bazel_module: { bp2build_available: true },
 }
@@ -598,21 +598,21 @@
     name: "both_filegroup",
     srcs: [
         // Not relevant, handled by filegroup macro
-	],
+  ],
 }
 
 filegroup {
     name: "shared_filegroup",
     srcs: [
         // Not relevant, handled by filegroup macro
-	],
+  ],
 }
 
 filegroup {
     name: "static_filegroup",
     srcs: [
         // Not relevant, handled by filegroup macro
-	],
+  ],
 }
 `,
 		},
@@ -710,21 +710,21 @@
 		dir:                                "foo/bar",
 		filesystem: map[string]string{
 			"foo/bar/Android.bp": `
-		cc_library {
-		   name: "a",
-		   srcs: ["a.cpp"],
-		   arch: {
-		     arm: {
-		       version_script: "arm.map",
-		     },
-		     arm64: {
-		       version_script: "arm64.map",
-		     },
-		   },
+    cc_library {
+       name: "a",
+       srcs: ["a.cpp"],
+       arch: {
+         arm: {
+           version_script: "arm.map",
+         },
+         arm64: {
+           version_script: "arm64.map",
+         },
+       },
 
-		   bazel_module: { bp2build_available: true },
-		}
-		`,
+       bazel_module: { bp2build_available: true },
+    }
+    `,
 		},
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
@@ -805,8 +805,8 @@
     srcs: ["b.cpp"],
     arch: {
         x86_64: {
-		pack_relocations: false,
-	},
+    pack_relocations: false,
+  },
     },
     bazel_module: { bp2build_available: true },
 }
@@ -816,8 +816,8 @@
     srcs: ["c.cpp"],
     target: {
         darwin: {
-		pack_relocations: false,
-	},
+    pack_relocations: false,
+  },
     },
     bazel_module: { bp2build_available: true },
 }`,
@@ -900,22 +900,22 @@
     name: "a",
     srcs: ["a.cpp"],
     cflags: [
-		"-Wall",
-	],
+    "-Wall",
+  ],
     cppflags: [
         "-fsigned-char",
         "-pedantic",
-	],
+  ],
     arch: {
         arm64: {
             cppflags: ["-DARM64=1"],
-		},
-	},
+    },
+  },
     target: {
         android: {
             cppflags: ["-DANDROID=1"],
-		},
-	},
+    },
+  },
     bazel_module: { bp2build_available: true  },
 }
 `,
@@ -953,21 +953,21 @@
 		dir:                                "foo/bar",
 		filesystem: map[string]string{
 			"foo/bar/Android.bp": `
-		cc_library {
-		   name: "a",
-		   srcs: ["a.cpp"],
-		   target: {
-		     android_arm: {
-		       version_script: "android_arm.map",
-		     },
-		     linux_bionic_arm64: {
-		       version_script: "linux_bionic_arm64.map",
-		     },
-		   },
+    cc_library {
+       name: "a",
+       srcs: ["a.cpp"],
+       target: {
+         android_arm: {
+           version_script: "android_arm.map",
+         },
+         linux_bionic_arm64: {
+           version_script: "linux_bionic_arm64.map",
+         },
+       },
 
-		   bazel_module: { bp2build_available: true },
-		}
-		`,
+       bazel_module: { bp2build_available: true },
+    }
+    `,
 		},
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
@@ -1099,3 +1099,135 @@
 		},
 	})
 }
+
+func TestCCLibraryNoCrtTrue(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,
+}
+`,
+		expectedBazelTargets: []string{`cc_library(
+    name = "foo-lib",
+    copts = [
+        "-I.",
+        "-I$(BINDIR)/.",
+    ],
+    srcs = ["impl.cpp"],
+    use_libcrt = False,
+)`}})
+}
+
+func TestCCLibraryNoCrtFalse(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_headers { name: "some-headers" }
+cc_library {
+    name: "foo-lib",
+    srcs: ["impl.cpp"],
+    no_libcrt: false,
+}
+`,
+		expectedBazelTargets: []string{`cc_library(
+    name = "foo-lib",
+    copts = [
+        "-I.",
+        "-I$(BINDIR)/.",
+    ],
+    srcs = ["impl.cpp"],
+    use_libcrt = True,
+)`}})
+}
+
+func TestCCLibraryNoCrtArchVariant(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_headers { name: "some-headers" }
+cc_library {
+    name: "foo-lib",
+    srcs: ["impl.cpp"],
+    arch: {
+        arm: {
+            no_libcrt: true,
+        },
+        x86: {
+            no_libcrt: true,
+        },
+    },
+}
+`,
+		expectedBazelTargets: []string{`cc_library(
+    name = "foo-lib",
+    copts = [
+        "-I.",
+        "-I$(BINDIR)/.",
+    ],
+    srcs = ["impl.cpp"],
+    use_libcrt = select({
+        "//build/bazel/platforms/arch:arm": False,
+        "//build/bazel/platforms/arch:x86": False,
+        "//conditions:default": None,
+    }),
+)`}})
+}
+
+func TestCCLibraryNoCrtArchVariantWithDefault(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_headers { name: "some-headers" }
+cc_library {
+    name: "foo-lib",
+    srcs: ["impl.cpp"],
+    no_libcrt: false,
+    arch: {
+        arm: {
+            no_libcrt: true,
+        },
+        x86: {
+            no_libcrt: true,
+        },
+    },
+}
+`,
+		expectedBazelTargets: []string{`cc_library(
+    name = "foo-lib",
+    copts = [
+        "-I.",
+        "-I$(BINDIR)/.",
+    ],
+    srcs = ["impl.cpp"],
+    use_libcrt = select({
+        "//build/bazel/platforms/arch:arm": False,
+        "//build/bazel/platforms/arch:x86": False,
+        "//conditions:default": True,
+    }),
+)`}})
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 264ba6b..db344de 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -374,3 +374,39 @@
 )`},
 	})
 }
+
+func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) {
+	runCcLibraryHeadersTestCase(t, bp2buildTestCase{
+		description:                        "cc_library_headers test",
+		moduleTypeUnderTest:                "cc_library_headers",
+		moduleTypeUnderTestFactory:         cc.LibraryHeaderFactory,
+		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
+		filesystem: map[string]string{
+			"lib-1/lib1a.h":                        "",
+			"lib-1/lib1b.h":                        "",
+			"lib-2/lib2a.h":                        "",
+			"lib-2/lib2b.h":                        "",
+			"dir-1/dir1a.h":                        "",
+			"dir-1/dir1b.h":                        "",
+			"dir-2/dir2a.h":                        "",
+			"dir-2/dir2b.h":                        "",
+			"arch_arm64_exported_include_dir/a.h":  "",
+			"arch_x86_exported_include_dir/b.h":    "",
+			"arch_x86_64_exported_include_dir/c.h": "",
+		},
+		blueprint: soongCcLibraryHeadersPreamble + `
+cc_library_headers {
+    name: "lib-1",
+    export_include_dirs: ["lib-1"],
+    no_libcrt: true,
+}`,
+		expectedBazelTargets: []string{`cc_library_headers(
+    name = "lib-1",
+    copts = [
+        "-I.",
+        "-I$(BINDIR)/.",
+    ],
+    includes = ["lib-1"],
+)`},
+	})
+}
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 60f6330..c8105eb 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -51,6 +51,28 @@
 	return value, []selects{ret}
 }
 
+func getBoolValue(boolAttr bazel.BoolAttribute) (reflect.Value, []selects) {
+	value := reflect.ValueOf(boolAttr.Value)
+	if !boolAttr.HasConfigurableValues() {
+		return value, []selects{}
+	}
+
+	ret := selects{}
+	for _, axis := range boolAttr.SortedConfigurationAxes() {
+		configToBools := boolAttr.ConfigurableValues[axis]
+		for config, bools := range configToBools {
+			selectKey := axis.SelectKey(config)
+			ret[selectKey] = reflect.ValueOf(bools)
+		}
+	}
+	// if there is a select, use the base value as the conditions default value
+	if len(ret) > 0 {
+		ret[bazel.ConditionsDefaultSelectKey] = value
+		value = reflect.Zero(value.Type())
+	}
+
+	return value, []selects{ret}
+}
 func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {
 	value := reflect.ValueOf(list.Value.Includes)
 	var ret []selects
@@ -85,22 +107,30 @@
 	return false, reflect.Zero(reflect.TypeOf([]string{}))
 }
 
+var (
+	emptyBazelList = "[]"
+	bazelNone      = "None"
+)
+
 // prettyPrintAttribute converts an Attribute to its Bazel syntax. May contain
 // select statements.
 func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
 	var value reflect.Value
 	var configurableAttrs []selects
-	var defaultSelectValue string
+	var defaultSelectValue *string
 	switch list := v.(type) {
 	case bazel.StringListAttribute:
 		value, configurableAttrs = getStringListValues(list)
-		defaultSelectValue = "[]"
+		defaultSelectValue = &emptyBazelList
 	case bazel.LabelListAttribute:
 		value, configurableAttrs = getLabelListValues(list)
-		defaultSelectValue = "[]"
+		defaultSelectValue = &emptyBazelList
 	case bazel.LabelAttribute:
 		value, configurableAttrs = getLabelValue(list)
-		defaultSelectValue = "None"
+		defaultSelectValue = &bazelNone
+	case bazel.BoolAttribute:
+		value, configurableAttrs = getBoolValue(list)
+		defaultSelectValue = &bazelNone
 	default:
 		return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
 	}
@@ -116,7 +146,7 @@
 		ret += s
 	}
 	// Convenience function to append selects components to an attribute value.
-	appendSelects := func(selectsData selects, defaultValue, s string) (string, error) {
+	appendSelects := func(selectsData selects, defaultValue *string, s string) (string, error) {
 		selectMap, err := prettyPrintSelectMap(selectsData, defaultValue, indent)
 		if err != nil {
 			return "", err
@@ -141,13 +171,11 @@
 
 // prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
 // to construct a select map for any kind of attribute type.
-func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue string, indent int) (string, error) {
+func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue *string, indent int) (string, error) {
 	if selectMap == nil {
 		return "", nil
 	}
 
-	// addConditionsDefault := false
-
 	var selects string
 	for _, selectKey := range android.SortedStringKeys(selectMap) {
 		if selectKey == bazel.ConditionsDefaultSelectKey {
@@ -184,14 +212,14 @@
 	if err != nil {
 		return "", err
 	}
-	if s == "" {
-		// Print an explicit empty list (the default value) even if the value is
-		// empty, to avoid errors about not finding a configuration that matches.
-		ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), bazel.ConditionsDefaultSelectKey, defaultValue)
-	} else {
+	if s != "" {
 		// Print the custom default value.
 		ret += s
 		ret += ",\n"
+	} else if defaultValue != nil {
+		// Print an explicit empty list (the default value) even if the value is
+		// empty, to avoid errors about not finding a configuration that matches.
+		ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), bazel.ConditionsDefaultSelectKey, *defaultValue)
 	}
 
 	ret += makeIndent(indent)
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 752d43b..211fe5e 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -489,6 +489,7 @@
 	dynamicDeps      bazel.LabelListAttribute
 	wholeArchiveDeps bazel.LabelListAttribute
 	exportedDeps     bazel.LabelListAttribute
+	useLibcrt        bazel.BoolAttribute
 	linkopts         bazel.StringListAttribute
 	versionScript    bazel.LabelAttribute
 }
@@ -512,6 +513,7 @@
 	var wholeArchiveDeps bazel.LabelListAttribute
 	var linkopts bazel.StringListAttribute
 	var versionScript bazel.LabelAttribute
+	var useLibcrt bazel.BoolAttribute
 
 	for _, linkerProps := range module.linker.linkerProps() {
 		if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
@@ -535,6 +537,7 @@
 			if baseLinkerProps.Version_script != nil {
 				versionScript.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
 			}
+			useLibcrt.Value = baseLinkerProps.libCrt()
 
 			break
 		}
@@ -559,6 +562,7 @@
 				if baseLinkerProps.Version_script != nil {
 					versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
 				}
+				useLibcrt.SetSelectValue(axis, config, baseLinkerProps.libCrt())
 			}
 		}
 	}
@@ -624,6 +628,7 @@
 		dynamicDeps:      dynamicDeps,
 		wholeArchiveDeps: wholeArchiveDeps,
 		linkopts:         linkopts,
+		useLibcrt:        useLibcrt,
 		versionScript:    versionScript,
 	}
 }
diff --git a/cc/library.go b/cc/library.go
index c88c29a..5995e98 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -234,6 +234,7 @@
 	Whole_archive_deps  bazel.LabelListAttribute
 	Includes            bazel.StringListAttribute
 	Linkopts            bazel.StringListAttribute
+	Use_libcrt          bazel.BoolAttribute
 
 	// Attributes pertaining to shared variant.
 	Shared_srcs    bazel.LabelListAttribute
@@ -320,6 +321,7 @@
 		Whole_archive_deps:  linkerAttrs.wholeArchiveDeps,
 		Includes:            exportedIncludes,
 		Linkopts:            linkerAttrs.linkopts,
+		Use_libcrt:          linkerAttrs.useLibcrt,
 
 		Shared_srcs:                   sharedAttrs.srcs,
 		Shared_srcs_c:                 sharedAttrs.srcs_c,
@@ -2262,6 +2264,7 @@
 	Whole_archive_deps  bazel.LabelListAttribute
 	Linkopts            bazel.StringListAttribute
 	Linkstatic          bool
+	Use_libcrt          bazel.BoolAttribute
 	Includes            bazel.StringListAttribute
 	Hdrs                bazel.LabelListAttribute
 
@@ -2298,6 +2301,7 @@
 
 		Linkopts:   linkerAttrs.linkopts,
 		Linkstatic: true,
+		Use_libcrt: linkerAttrs.useLibcrt,
 		Includes:   exportedIncludes,
 
 		Cppflags:   compilerAttrs.cppFlags,
diff --git a/cc/linker.go b/cc/linker.go
index 1d8c649..895931a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -200,6 +200,18 @@
 	Exclude_shared_libs []string `android:"arch_variant"`
 }
 
+func invertBoolPtr(value *bool) *bool {
+	if value == nil {
+		return nil
+	}
+	ret := !(*value)
+	return &ret
+}
+
+func (blp *BaseLinkerProperties) libCrt() *bool {
+	return invertBoolPtr(blp.No_libcrt)
+}
+
 func NewBaseLinker(sanitize *sanitize) *baseLinker {
 	return &baseLinker{sanitize: sanitize}
 }