// Copyright 2023 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 cc import ( "testing" "strings" "android/soong/android" ) func TestOrderfileProfileSharedLibrary(t *testing.T) { t.Parallel() bp := ` cc_library_shared { name: "libTest", srcs: ["test.c"], orderfile : { instrumentation: true, load_order_file: false, order_file_path: "", }, } ` result := android.GroupFixturePreparers( prepareForCcTest, ).RunTestWithBp(t, bp) expectedCFlag := "-forder-file-instrumentation" libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") // Check cFlags of orderfile-enabled module cFlags := libTest.Rule("cc").Args["cFlags"] if !strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) } // Check ldFlags of orderfile-enabled module ldFlags := libTest.Rule("ld").Args["ldFlags"] if !strings.Contains(ldFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) } } func TestOrderfileLoadSharedLibrary(t *testing.T) { t.Parallel() bp := ` cc_library_shared { name: "libTest", srcs: ["test.c"], orderfile : { instrumentation: true, load_order_file: true, order_file_path: "libTest.orderfile", }, } ` result := android.GroupFixturePreparers( prepareForCcTest, android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/libTest.orderfile", "TEST"), ).RunTestWithBp(t, bp) expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/libTest.orderfile" libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") // Check ldFlags of orderfile-enabled module ldFlags := libTest.Rule("ld").Args["ldFlags"] if !strings.Contains(ldFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) } } func TestOrderfileProfileBinary(t *testing.T) { t.Parallel() bp := ` cc_binary { name: "test", srcs: ["test.c"], orderfile : { instrumentation: true, load_order_file: false, order_file_path: "", }, } ` result := android.GroupFixturePreparers( prepareForCcTest, ).RunTestWithBp(t, bp) expectedCFlag := "-forder-file-instrumentation" test := result.ModuleForTests("test", "android_arm64_armv8-a") // Check cFlags of orderfile-enabled module cFlags := test.Rule("cc").Args["cFlags"] if !strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'test' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) } // Check ldFlags of orderfile-enabled module ldFlags := test.Rule("ld").Args["ldFlags"] if !strings.Contains(ldFlags, expectedCFlag) { t.Errorf("Expected 'test' to enable orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) } } func TestOrderfileLoadBinary(t *testing.T) { t.Parallel() bp := ` cc_binary { name: "test", srcs: ["test.c"], orderfile : { instrumentation: true, load_order_file: true, order_file_path: "test.orderfile", }, } ` result := android.GroupFixturePreparers( prepareForCcTest, android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"), ).RunTestWithBp(t, bp) expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile" test := result.ModuleForTests("test", "android_arm64_armv8-a") // Check ldFlags of orderfile-enabled module ldFlags := test.Rule("ld").Args["ldFlags"] if !strings.Contains(ldFlags, expectedCFlag) { t.Errorf("Expected 'test' to load orderfile, but did not find %q in ldflags %q", expectedCFlag, ldFlags) } } // Profile flags should propagate through static libraries func TestOrderfileProfilePropagateStaticDeps(t *testing.T) { t.Parallel() bp := ` cc_library_shared { name: "libTest", srcs: ["test.c"], static_libs: ["libFoo"], orderfile : { instrumentation: true, load_order_file: false, order_file_path: "", }, } cc_library_static { name: "libFoo", srcs: ["foo.c"], static_libs: ["libBar"], } cc_library_static { name: "libBar", srcs: ["bar.c"], } ` result := android.GroupFixturePreparers( prepareForCcTest, ).RunTestWithBp(t, bp) expectedCFlag := "-forder-file-instrumentation" // Check cFlags of orderfile-enabled module libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") cFlags := libTest.Rule("cc").Args["cFlags"] if !strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) } // Check cFlags of orderfile variant static libraries libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile") libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile") cFlags = libFooOfVariant.Rule("cc").Args["cFlags"] if !strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libFooOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) } cFlags = libBarOfVariant.Rule("cc").Args["cFlags"] if !strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libBarOfVariant' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) } // Check dependency edge from orderfile-enabled module to orderfile variant static libraries if !hasDirectDep(result, libTest.Module(), libFooOfVariant.Module()) { t.Errorf("libTest missing dependency on orderfile variant of libFoo") } if !hasDirectDep(result, libFooOfVariant.Module(), libBarOfVariant.Module()) { t.Errorf("libTest missing dependency on orderfile variant of libBar") } // Check cFlags of the non-orderfile variant static libraries libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") cFlags = libFoo.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } cFlags = libBar.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } // Check no dependency edge from orderfile-enabled module to non-orderfile variant static libraries if hasDirectDep(result, libTest.Module(), libFoo.Module()) { t.Errorf("libTest has dependency on non-orderfile variant of libFoo") } if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { t.Errorf("libTest has dependency on non-orderfile variant of libBar") } } // Load flags should never propagate func TestOrderfileLoadPropagateStaticDeps(t *testing.T) { t.Parallel() bp := ` cc_library_shared { name: "libTest", srcs: ["test.c"], static_libs: ["libFoo"], orderfile : { instrumentation: true, load_order_file: true, order_file_path: "test.orderfile", }, } cc_library_static { name: "libFoo", srcs: ["foo.c"], static_libs: ["libBar"], } cc_library_static { name: "libBar", srcs: ["bar.c"], } ` result := android.GroupFixturePreparers( prepareForCcTest, android.FixtureAddTextFile("toolchain/pgo-profiles/orderfiles/test.orderfile", "TEST"), ).RunTestWithBp(t, bp) expectedCFlag := "-Wl,--symbol-ordering-file=toolchain/pgo-profiles/orderfiles/test.orderfile" // Check ldFlags of orderfile-enabled module libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") ldFlags := libTest.Rule("ld").Args["ldFlags"] if !strings.Contains(ldFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags) } libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") } if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { t.Errorf("libTest missing dependency on non-orderfile variant of libBar") } // Make sure no orderfile variants are created for static libraries because the flags were not propagated libFooVariants := result.ModuleVariantsForTests("libFoo") for _, v := range libFooVariants { if strings.Contains(v, "orderfile") { t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) } } libBarVariants := result.ModuleVariantsForTests("libBar") for _, v := range libBarVariants { if strings.Contains(v, "orderfile") { t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) } } } // Profile flags should not propagate through shared libraries func TestOrderfileProfilePropagateSharedDeps(t *testing.T) { t.Parallel() bp := ` cc_library_shared { name: "libTest", srcs: ["test.c"], shared_libs: ["libFoo"], orderfile : { instrumentation: true, load_order_file: false, order_file_path: "", }, } cc_library_shared { name: "libFoo", srcs: ["foo.c"], static_libs: ["libBar"], } cc_library_static { name: "libBar", srcs: ["bar.c"], } ` result := android.GroupFixturePreparers( prepareForCcTest, ).RunTestWithBp(t, bp) expectedCFlag := "-forder-file-instrumentation" // Check cFlags of orderfile-enabled module libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared") cFlags := libTest.Rule("cc").Args["cFlags"] if !strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to enable orderfile, but did not find %q in cflags %q", expectedCFlag, cFlags) } // Check cFlags of the static and shared libraries libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared") libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") cFlags = libFoo.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } cFlags = libBar.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } // Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") } if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { t.Errorf("libTest missing dependency on non-orderfile variant of libBar") } // Make sure no orderfile variants are created for libraries because the flags were not propagated libFooVariants := result.ModuleVariantsForTests("libFoo") for _, v := range libFooVariants { if strings.Contains(v, "orderfile") { t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) } } libBarVariants := result.ModuleVariantsForTests("libBar") for _, v := range libBarVariants { if strings.Contains(v, "orderfile") { t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) } } } // Profile flags should not work or be propagated if orderfile flags start at a static library func TestOrderfileProfileStaticLibrary(t *testing.T) { t.Parallel() bp := ` cc_library_static { name: "libTest", srcs: ["test.c"], static_libs: ["libFoo"], orderfile : { instrumentation: true, load_order_file: false, order_file_path: "", }, } cc_library_static { name: "libFoo", srcs: ["foo.c"], static_libs: ["libBar"], } cc_library_static { name: "libBar", srcs: ["bar.c"], } ` result := android.GroupFixturePreparers( prepareForCcTest, ).RunTestWithBp(t, bp) expectedCFlag := "-forder-file-instrumentation" // Check cFlags of module libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_static") cFlags := libTest.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libTest' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } // Check cFlags of the static libraries libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static") libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static") cFlags = libFoo.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libFoo' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } cFlags = libBar.Rule("cc").Args["cFlags"] if strings.Contains(cFlags, expectedCFlag) { t.Errorf("Expected 'libBar' to not enable orderfile, but did find %q in cflags %q", expectedCFlag, cFlags) } // Check dependency edge from orderfile-enabled module to non-orderfile variant libraries if !hasDirectDep(result, libTest.Module(), libFoo.Module()) { t.Errorf("libTest missing dependency on non-orderfile variant of libFoo") } if !hasDirectDep(result, libFoo.Module(), libBar.Module()) { t.Errorf("libTest missing dependency on non-orderfile variant of libBar") } // Make sure no orderfile variants are created for static libraries because the flags were not propagated libFooVariants := result.ModuleVariantsForTests("libFoo") for _, v := range libFooVariants { if strings.Contains(v, "orderfile") { t.Errorf("Expected variants for 'libFoo' to not contain 'orderfile', but found %q", v) } } libBarVariants := result.ModuleVariantsForTests("libBar") for _, v := range libBarVariants { if strings.Contains(v, "orderfile") { t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v) } } }