Merge "Merge Android 12"
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 6648a2f..974f8f5 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -587,13 +587,11 @@
%s
def get_arch(target):
- # TODO(b/199363072): filegroups and file targets aren't associated with any
- # specific platform architecture in mixed builds. This is consistent with how
- # Soong treats filegroups, but it may not be the case with manually-written
- # filegroup BUILD targets.
- if target.kind in ["filegroup", ""]:
- return "common"
buildoptions = build_options(target)
+ if buildoptions == None:
+ # File targets do not have buildoptions. File targets aren't associated with
+ # any specific platform architecture in mixed builds.
+ return "common"
platforms = build_options(target)["//command_line_option:platforms"]
if len(platforms) != 1:
# An individual configured target should have only one platform architecture.
diff --git a/android/filegroup.go b/android/filegroup.go
index 2cf5567..f8f0955 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -112,15 +112,22 @@
return module
}
-func (fg *fileGroup) GenerateBazelBuildActions(ctx ModuleContext) bool {
+func (fg *fileGroup) maybeGenerateBazelBuildActions(ctx ModuleContext) {
if !fg.MixedBuildsEnabled(ctx) {
- return false
+ return
+ }
+
+ archVariant := ctx.Arch().ArchType
+ if len(fg.Srcs()) == 1 && fg.Srcs()[0].Base() == fg.Name() {
+ // This will be a regular file target, not filegroup, in Bazel.
+ // See FilegroupBp2Build for more information.
+ archVariant = Common
}
bazelCtx := ctx.Config().BazelContext
- filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), Common)
+ filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), archVariant)
if !ok {
- return false
+ return
}
bazelOuts := make(Paths, 0, len(filePaths))
@@ -130,19 +137,15 @@
}
fg.srcs = bazelOuts
-
- return true
}
func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
- if fg.GenerateBazelBuildActions(ctx) {
- return
- }
-
fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs)
if fg.properties.Path != nil {
fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
}
+
+ fg.maybeGenerateBazelBuildActions(ctx)
}
func (fg *fileGroup) Srcs() Paths {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 0d65822..bfe88f5 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -15,6 +15,7 @@
package bp2build
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -1142,6 +1143,81 @@
func TestCCLibraryNoCrtTrue(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library - nocrt: true emits attribute",
+ 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"],
+ nocrt: true,
+ include_build_directory: false,
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo-lib",
+ link_crt = False,
+ srcs = ["impl.cpp"],
+)`}})
+}
+
+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,
+ filesystem: map[string]string{
+ "impl.cpp": "",
+ },
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "foo-lib",
+ srcs: ["impl.cpp"],
+ nocrt: false,
+ include_build_directory: false,
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo-lib",
+ srcs = ["impl.cpp"],
+)`}})
+}
+
+func TestCCLibraryNoCrtArchVariant(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library - nocrt in select",
+ 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: {
+ nocrt: true,
+ },
+ x86: {
+ 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,
@@ -1165,7 +1241,7 @@
)`}})
}
-func TestCCLibraryNoCrtFalse(t *testing.T) {
+func TestCCLibraryNoLibCrtFalse(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
@@ -1189,7 +1265,7 @@
)`}})
}
-func TestCCLibraryNoCrtArchVariant(t *testing.T) {
+func TestCCLibraryNoLibCrtArchVariant(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
moduleTypeUnderTest: "cc_library",
moduleTypeUnderTestFactory: cc.LibraryFactory,
@@ -1223,41 +1299,6 @@
)`}})
}
-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 {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- no_libcrt: false,
- arch: {
- arm: {
- no_libcrt: true,
- },
- x86: {
- 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": True,
- }),
-)`}})
-}
-
func TestCcLibraryStrip(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
description: "cc_library strip args",
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 3dcfbd7..b272067 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -15,6 +15,7 @@
package bp2build
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -364,3 +365,78 @@
)`},
})
}
+
+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"),
+ })
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 22bd90b..ebba9d1 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -364,6 +364,7 @@
wholeArchiveDeps bazel.LabelListAttribute
systemDynamicDeps bazel.LabelListAttribute
+ linkCrt bazel.BoolAttribute
useLibcrt bazel.BoolAttribute
linkopts bazel.StringListAttribute
versionScript bazel.LabelAttribute
@@ -398,6 +399,7 @@
var linkopts bazel.StringListAttribute
var versionScript bazel.LabelAttribute
+ var linkCrt bazel.BoolAttribute
var useLibcrt bazel.BoolAttribute
var stripKeepSymbols bazel.BoolAttribute
@@ -418,6 +420,9 @@
}
}
+ // 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,10 +462,23 @@
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
excludesField string
@@ -530,6 +548,7 @@
wholeArchiveDeps: wholeArchiveDeps,
systemDynamicDeps: systemSharedDeps,
+ linkCrt: linkCrt,
linkopts: linkopts,
useLibcrt: useLibcrt,
versionScript: versionScript,
diff --git a/cc/library.go b/cc/library.go
index 77eddbf..58e0e21 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -252,6 +252,7 @@
// 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 @@
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 @@
Asflags: asFlags,
Linkopts: linkerAttrs.linkopts,
+ Link_crt: linkerAttrs.linkCrt,
Use_libcrt: linkerAttrs.useLibcrt,
Rtti: compilerAttrs.rtti,
Stl: compilerAttrs.stl,
@@ -2472,6 +2475,7 @@
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
diff --git a/cc/linker.go b/cc/linker.go
index 0d612b5..20e377c 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -238,6 +238,19 @@
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)
}
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index 1bdd040..658e8e2 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -598,11 +598,18 @@
func toJsonClassLoaderContextRec(clcs []*ClassLoaderContext) []*jsonClassLoaderContext {
jClcs := make([]*jsonClassLoaderContext, len(clcs))
for i, clc := range clcs {
+ var host string
+ if clc.Host == nil {
+ // Defer build failure to when this CLC is actually used.
+ host = fmt.Sprintf("implementation-jar-for-%s-is-not-available.jar", clc.Name)
+ } else {
+ host = clc.Host.String()
+ }
jClcs[i] = &jsonClassLoaderContext{
Name: clc.Name,
Optional: clc.Optional,
Implicit: clc.Implicit,
- Host: clc.Host.String(),
+ Host: host,
Device: clc.Device,
Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 7fd88fc..0c66ccf 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -25,6 +25,9 @@
"android/soong/remoteexec"
)
+// The values allowed for Droidstubs' Api_levels_sdk_type
+var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib"}
+
func init() {
RegisterStubsBuildComponents(android.InitRegistrationContext)
}
@@ -134,7 +137,7 @@
// the dirs which Metalava extracts API levels annotations from.
Api_levels_annotations_dirs []string
- // the sdk kind which Metalava extracts API levels annotations from. Supports 'public' and 'system' for now; defaults to public.
+ // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system' and 'module-lib' for now; defaults to public.
Api_levels_sdk_type *string
// the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
@@ -404,19 +407,24 @@
// When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
// an actual file present on disk (in the order the patterns were passed). For system APIs for
// privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
- // for older releases.
- if sdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public"); sdkType != "public" {
- if sdkType != "system" {
- ctx.PropertyErrorf("api_levels_sdk_type", "only 'public' and 'system' are supported")
- }
- // If building non public stubs, add all sdkType patterns first...
- for _, dir := range dirs {
- cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkType, filename))
- }
+ // for older releases. Similarly, module-lib falls back to system API.
+ var sdkDirs []string
+ switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
+ case "module-lib":
+ sdkDirs = []string{"module-lib", "system", "public"}
+ case "system":
+ sdkDirs = []string{"system", "public"}
+ case "public":
+ sdkDirs = []string{"public"}
+ default:
+ ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
+ return
}
- for _, dir := range dirs {
- // ... and fallback to public ones, for Metalava to use if needed.
- cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, "public", filename))
+
+ for _, sdkDir := range sdkDirs {
+ for _, dir := range dirs {
+ cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
+ }
}
}
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 60d0bea..10d99f3 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"reflect"
"regexp"
"strings"
@@ -82,8 +83,10 @@
}
}
-func TestSystemDroidstubs(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
+// runs a test for droidstubs with a customizable sdkType argument and returns
+// the list of jar patterns that is passed as `--android-jar-pattern`
+func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string {
+ ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
droiddoc_exported_dir {
name: "some-exported-dir",
path: "somedir",
@@ -102,9 +105,9 @@
"some-other-exported-dir",
],
api_levels_annotations_enabled: true,
- api_levels_sdk_type: "system",
+ api_levels_sdk_type: "%s",
}
- `,
+ `, sdkType),
map[string][]byte{
"foo-doc/a.java": nil,
})
@@ -113,13 +116,40 @@
manifest := m.Output("metalava.sbox.textproto")
cmd := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
- matches := r.FindAllString(cmd, -1)
+ return r.FindAllString(cmd, -1)
+}
+
+func TestPublicDroidstubs(t *testing.T) {
+ patterns := getAndroidJarPatternsForDroidstubs(t, "public")
+
+ android.AssertArrayString(t, "order of patterns", []string{
+ "--android-jar-pattern somedir/%/public/android.jar",
+ "--android-jar-pattern someotherdir/%/public/android.jar",
+ }, patterns)
+}
+
+func TestSystemDroidstubs(t *testing.T) {
+ patterns := getAndroidJarPatternsForDroidstubs(t, "system")
+
android.AssertArrayString(t, "order of patterns", []string{
"--android-jar-pattern somedir/%/system/android.jar",
"--android-jar-pattern someotherdir/%/system/android.jar",
"--android-jar-pattern somedir/%/public/android.jar",
"--android-jar-pattern someotherdir/%/public/android.jar",
- }, matches)
+ }, patterns)
+}
+
+func TestModuleLibDroidstubs(t *testing.T) {
+ patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib")
+
+ android.AssertArrayString(t, "order of patterns", []string{
+ "--android-jar-pattern somedir/%/module-lib/android.jar",
+ "--android-jar-pattern someotherdir/%/module-lib/android.jar",
+ "--android-jar-pattern somedir/%/system/android.jar",
+ "--android-jar-pattern someotherdir/%/system/android.jar",
+ "--android-jar-pattern somedir/%/public/android.jar",
+ "--android-jar-pattern someotherdir/%/public/android.jar",
+ }, patterns)
}
func TestDroidstubsSandbox(t *testing.T) {
diff --git a/rust/project_json.go b/rust/project_json.go
index faa7db5..ae48312 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -51,6 +51,7 @@
Deps []rustProjectDep `json:"deps"`
Cfg []string `json:"cfg"`
Env map[string]string `json:"env"`
+ ProcMacro bool `json:"is_proc_macro"`
}
type rustProjectJson struct {
@@ -208,6 +209,8 @@
comp = c.baseCompiler
case *testDecorator:
comp = c.binaryDecorator.baseCompiler
+ case *procMacroDecorator:
+ comp = c.baseCompiler
default:
return nil, nil, false
}
@@ -224,6 +227,8 @@
return 0, false
}
+ _, procMacro := rModule.compiler.(*procMacroDecorator)
+
crate := rustProjectCrate{
DisplayName: rModule.Name(),
RootModule: rootModule,
@@ -231,6 +236,7 @@
Deps: make([]rustProjectDep, 0),
Cfg: make([]string, 0),
Env: make(map[string]string),
+ ProcMacro: procMacro,
}
if comp.CargoOutDir().Valid() {
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index f7b6681..255b2e5 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -117,6 +117,58 @@
validateJsonCrates(t, jsonContent)
}
+func TestProjectJsonProcMacroDep(t *testing.T) {
+ bp := `
+ rust_proc_macro {
+ name: "libproc_macro",
+ srcs: ["a/src/lib.rs"],
+ crate_name: "proc_macro"
+ }
+ rust_library {
+ name: "librust",
+ srcs: ["b/src/lib.rs"],
+ crate_name: "rust",
+ proc_macros: ["libproc_macro"],
+ }
+ `
+ jsonContent := testProjectJson(t, bp)
+ crates := validateJsonCrates(t, jsonContent)
+ libproc_macro_count := 0
+ librust_count := 0
+ for _, c := range crates {
+ crate := validateCrate(t, c)
+ procMacro, ok := crate["is_proc_macro"].(bool)
+ if !ok {
+ t.Fatalf("Unexpected type for is_proc_macro: %v", crate["is_proc_macro"])
+ }
+
+ name, ok := crate["display_name"].(string)
+ if !ok {
+ t.Fatalf("Unexpected type for display_name: %v", crate["display_name"])
+ }
+
+ switch name {
+ case "libproc_macro":
+ libproc_macro_count += 1
+ if !procMacro {
+ t.Fatalf("'libproc_macro' is marked with is_proc_macro=false")
+ }
+ case "librust":
+ librust_count += 1
+ if procMacro {
+ t.Fatalf("'librust' is not a proc macro crate, but is marked with is_proc_macro=true")
+ }
+ default:
+ break
+ }
+ }
+
+ if libproc_macro_count != 1 || librust_count != 1 {
+ t.Fatalf("Unexpected crate counts: libproc_macro_count: %v, librust_count: %v",
+ libproc_macro_count, librust_count)
+ }
+}
+
func TestProjectJsonFeature(t *testing.T) {
bp := `
rust_library {