// 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() (&tc).moduleTypeUnderTest = "cc_object" (&tc).moduleTypeUnderTestFactory = cc.ObjectFactory runBp2BuildTestCase(t, registerCcObjectModuleTypes, tc) } func TestCcObjectSimple(t *testing.T) { runCcObjectTestCase(t, bp2buildTestCase{ description: "simple cc_object generates cc_object with include header dep", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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{ 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: [ "-Werror", ], } `, expectedBazelTargets: []string{ makeBazelTarget("cc_object", "foo", attrNameToString{ "copts": `[ "-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", 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{ makeBazelTarget("cc_object", "bar", attrNameToString{ "copts": `["-fno-addrsig"]`, "srcs": `["x/y/z.c"]`, "system_dynamic_deps": `[]`, }), makeBazelTarget("cc_object", "foo", attrNameToString{ "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", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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", blueprint: `cc_object { name: "foo", srcs: ["base.cpp"], linker_script: "bunny.lds", include_build_directory: false, } `, expectedBazelTargets: []string{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "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", 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{ makeBazelTarget("cc_object", "foo", attrNameToString{ "copts": `["-fno-addrsig"]`, "srcs": `["base.cpp"] + select({ "//build/bazel/platforms/os_arch:android_arm64": [ "linux_arm64.cpp", "bionic_arm64.cpp", ], "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"], "//build/bazel/platforms/os_arch:linux_bionic_arm64": [ "linux_arm64.cpp", "bionic_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": [], })`, }), }, }) }