// Copyright 2021 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package bp2build import ( "testing" "android/soong/android" "android/soong/cc" ) func registerCcObjectModuleTypes(ctx android.RegistrationContext) { // Always register cc_defaults module factory ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() }) } func runCcObjectTestCase(t *testing.T, tc bp2buildTestCase) { t.Helper() runBp2BuildTestCase(t, registerCcObjectModuleTypes, tc) } func TestCcObjectSimple(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "simple cc_object generates cc_object with include header dep", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, filesystem: map[string]string{ "a/b/foo.h": "", "a/b/bar.h": "", "a/b/exclude.c": "", "a/b/c.c": "", }, blueprint: `cc_object { name: "foo", local_include_dirs: ["include"], system_shared_libs: [], cflags: [ "-Wno-gcc-compat", "-Wall", "-Werror", ], srcs: [ "a/b/*.c" ], exclude_srcs: ["a/b/exclude.c"], } `, expectedBazelTargets: []string{`cc_object( name = "foo", copts = [ "-fno-addrsig", "-Wno-gcc-compat", "-Wall", "-Werror", ], local_includes = [ "include", ".", ], srcs = ["a/b/c.c"], system_dynamic_deps = [], )`, }, }) } func TestCcObjectDefaults(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", system_shared_libs: [], srcs: [ "a/b/*.h", "a/b/c.c" ], defaults: ["foo_defaults"], } cc_defaults { name: "foo_defaults", defaults: ["foo_bar_defaults"], } cc_defaults { name: "foo_bar_defaults", cflags: [ "-Wno-gcc-compat", "-Wall", "-Werror", ], } `, expectedBazelTargets: []string{`cc_object( name = "foo", copts = [ "-Wno-gcc-compat", "-Wall", "-Werror", "-fno-addrsig", ], local_includes = ["."], srcs = ["a/b/c.c"], system_dynamic_deps = [], )`, }}) } func TestCcObjectCcObjetDepsInObjs(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object with cc_object deps in objs props", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, filesystem: map[string]string{ "a/b/c.c": "", "x/y/z.c": "", }, blueprint: `cc_object { name: "foo", system_shared_libs: [], srcs: ["a/b/c.c"], objs: ["bar"], include_build_directory: false, } cc_object { name: "bar", system_shared_libs: [], srcs: ["x/y/z.c"], include_build_directory: false, } `, expectedBazelTargets: []string{`cc_object( name = "bar", copts = ["-fno-addrsig"], srcs = ["x/y/z.c"], system_dynamic_deps = [], )`, `cc_object( name = "foo", copts = ["-fno-addrsig"], deps = [":bar"], srcs = ["a/b/c.c"], system_dynamic_deps = [], )`, }, }) } func TestCcObjectIncludeBuildDirFalse(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object with include_build_dir: false", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, filesystem: map[string]string{ "a/b/c.c": "", "x/y/z.c": "", }, blueprint: `cc_object { name: "foo", system_shared_libs: [], srcs: ["a/b/c.c"], include_build_directory: false, } `, expectedBazelTargets: []string{`cc_object( name = "foo", copts = ["-fno-addrsig"], srcs = ["a/b/c.c"], system_dynamic_deps = [], )`, }, }) } func TestCcObjectProductVariable(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object with product variable", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", system_shared_libs: [], include_build_directory: false, product_variables: { platform_sdk_version: { asflags: ["-DPLATFORM_SDK_VERSION=%d"], }, }, srcs: ["src.S"], } `, expectedBazelTargets: []string{`cc_object( name = "foo", asflags = select({ "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"], "//conditions:default": [], }), copts = ["-fno-addrsig"], srcs_as = ["src.S"], system_dynamic_deps = [], )`, }, }) } func TestCcObjectCflagsOneArch(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object setting cflags for one arch", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", system_shared_libs: [], srcs: ["a.cpp"], arch: { x86: { cflags: ["-fPIC"], // string list }, arm: { srcs: ["arch/arm/file.cpp"], // label list }, }, include_build_directory: false, } `, expectedBazelTargets: []string{ `cc_object( name = "foo", copts = ["-fno-addrsig"] + select({ "//build/bazel/platforms/arch:x86": ["-fPIC"], "//conditions:default": [], }), srcs = ["a.cpp"] + select({ "//build/bazel/platforms/arch:arm": ["arch/arm/file.cpp"], "//conditions:default": [], }), system_dynamic_deps = [], )`, }, }) } func TestCcObjectCflagsFourArch(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object setting cflags for 4 architectures", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", system_shared_libs: [], srcs: ["base.cpp"], arch: { x86: { srcs: ["x86.cpp"], cflags: ["-fPIC"], }, x86_64: { srcs: ["x86_64.cpp"], cflags: ["-fPIC"], }, arm: { srcs: ["arm.cpp"], cflags: ["-Wall"], }, arm64: { srcs: ["arm64.cpp"], cflags: ["-Wall"], }, }, include_build_directory: false, } `, expectedBazelTargets: []string{ `cc_object( name = "foo", copts = ["-fno-addrsig"] + select({ "//build/bazel/platforms/arch:arm": ["-Wall"], "//build/bazel/platforms/arch:arm64": ["-Wall"], "//build/bazel/platforms/arch:x86": ["-fPIC"], "//build/bazel/platforms/arch:x86_64": ["-fPIC"], "//conditions:default": [], }), srcs = ["base.cpp"] + select({ "//build/bazel/platforms/arch:arm": ["arm.cpp"], "//build/bazel/platforms/arch:arm64": ["arm64.cpp"], "//build/bazel/platforms/arch:x86": ["x86.cpp"], "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"], "//conditions:default": [], }), system_dynamic_deps = [], )`, }, }) } func TestCcObjectLinkerScript(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object setting linker_script", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", srcs: ["base.cpp"], linker_script: "bunny.lds", include_build_directory: false, } `, expectedBazelTargets: []string{ `cc_object( name = "foo", copts = ["-fno-addrsig"], linker_script = "bunny.lds", srcs = ["base.cpp"], )`, }, }) } func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object setting deps and linker_script across archs", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", srcs: ["base.cpp"], arch: { x86: { objs: ["x86_obj"], linker_script: "x86.lds", }, x86_64: { objs: ["x86_64_obj"], linker_script: "x86_64.lds", }, arm: { objs: ["arm_obj"], linker_script: "arm.lds", }, }, include_build_directory: false, } cc_object { name: "x86_obj", system_shared_libs: [], srcs: ["x86.cpp"], include_build_directory: false, bazel_module: { bp2build_available: false }, } cc_object { name: "x86_64_obj", system_shared_libs: [], srcs: ["x86_64.cpp"], include_build_directory: false, bazel_module: { bp2build_available: false }, } cc_object { name: "arm_obj", system_shared_libs: [], srcs: ["arm.cpp"], include_build_directory: false, bazel_module: { bp2build_available: false }, } `, expectedBazelTargets: []string{ `cc_object( name = "foo", copts = ["-fno-addrsig"], deps = select({ "//build/bazel/platforms/arch:arm": [":arm_obj"], "//build/bazel/platforms/arch:x86": [":x86_obj"], "//build/bazel/platforms/arch:x86_64": [":x86_64_obj"], "//conditions:default": [], }), linker_script = select({ "//build/bazel/platforms/arch:arm": "arm.lds", "//build/bazel/platforms/arch:x86": "x86.lds", "//build/bazel/platforms/arch:x86_64": "x86_64.lds", "//conditions:default": None, }), srcs = ["base.cpp"], )`, }, }) } func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "cc_object setting srcs based on linux and bionic archs", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", srcs: ["base.cpp"], target: { linux_arm64: { srcs: ["linux_arm64.cpp",] }, linux_x86: { srcs: ["linux_x86.cpp",] }, bionic_arm64: { srcs: ["bionic_arm64.cpp",] }, }, include_build_directory: false, } `, expectedBazelTargets: []string{ `cc_object( name = "foo", copts = ["-fno-addrsig"], srcs = ["base.cpp"] + select({ "//build/bazel/platforms/os_arch:android_arm64": [ "bionic_arm64.cpp", "linux_arm64.cpp", ], "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"], "//build/bazel/platforms/os_arch:linux_bionic_arm64": [ "bionic_arm64.cpp", "linux_arm64.cpp", ], "//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"], "//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"], "//conditions:default": [], }), )`, }, }) }