Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1227b20 authored by Alex Márquez Pérez Muñíz Díaz Púras Thaureaux's avatar Alex Márquez Pérez Muñíz Díaz Púras Thaureaux Committed by Gerrit Code Review
Browse files

Merge "libclang_rt_prebuilt_library_shared mixed builds"

parents c85964a7 c3b97c35
Loading
Loading
Loading
Loading
+41 −18
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ var (
type CcInfo struct {
	OutputFiles          []string
	CcObjectFiles        []string
	CcSharedLibraryFiles []string
	CcStaticLibraryFiles []string
	Includes             []string
	SystemIncludes       []string
@@ -128,28 +129,43 @@ else:
        if linker_input.owner == target.label:
          rootStaticArchives.append(library.static_library.path)

rootDynamicLibraries = []
sharedLibraries = []
rootSharedLibraries = []

shared_info_tag = "@rules_cc//examples:experimental_cc_shared_library.bzl%CcSharedLibraryInfo"
if shared_info_tag in providers(target):
  shared_info = providers(target)[shared_info_tag]
  for lib in shared_info.linker_input.libraries:
    rootDynamicLibraries += [lib.dynamic_library.path]
    path = lib.dynamic_library.path
    rootSharedLibraries += [path]
    sharedLibraries.append(path)
else:
  for linker_input in linker_inputs:
    for library in linker_input.libraries:
      if library.dynamic_library:
        path = library.dynamic_library.path
        sharedLibraries.append(path)
        if linker_input.owner == target.label:
          rootSharedLibraries.append(path)

toc_file = ""
toc_file_tag = "//build/bazel/rules:generate_toc.bzl%CcTocInfo"
if toc_file_tag in providers(target):
  toc_file = providers(target)[toc_file_tag].toc.path
else:
  # NOTE: It's OK if there's no ToC, as Soong just uses it for optimization
  pass

returns = [
  outputFiles,
  staticLibraries,
  ccObjectFiles,
  sharedLibraries,
  staticLibraries,
  includes,
  system_includes,
  headers,
  rootStaticArchives,
  rootDynamicLibraries,
  rootSharedLibraries,
  [toc_file]
]

@@ -160,28 +176,35 @@ return "|".join([", ".join(r) for r in returns])`
// The given rawString must correspond to the string output which was created by evaluating the
// Starlark given in StarlarkFunctionBody.
func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
	var outputFiles []string
	var ccObjects []string

	const expectedLen = 10
	splitString := strings.Split(rawString, "|")
	if expectedLen := 9; len(splitString) != expectedLen {
	if len(splitString) != expectedLen {
		return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
	}
	outputFilesString := splitString[0]
	ccStaticLibrariesString := splitString[1]
	ccObjectsString := splitString[2]
	outputFiles = splitOrEmpty(outputFilesString, ", ")
	ccObjectsString := splitString[1]
	ccSharedLibrariesString := splitString[2]
	ccStaticLibrariesString := splitString[3]
	includesString := splitString[4]
	systemIncludesString := splitString[5]
	headersString := splitString[6]
	rootStaticArchivesString := splitString[7]
	rootDynamicLibrariesString := splitString[8]
	tocFile := splitString[9] // NOTE: Will be the empty string if there wasn't

	outputFiles := splitOrEmpty(outputFilesString, ", ")
	ccObjects := splitOrEmpty(ccObjectsString, ", ")
	ccSharedLibraries := splitOrEmpty(ccSharedLibrariesString, ", ")
	ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ")
	ccObjects = splitOrEmpty(ccObjectsString, ", ")
	includes := splitOrEmpty(splitString[3], ", ")
	systemIncludes := splitOrEmpty(splitString[4], ", ")
	headers := splitOrEmpty(splitString[5], ", ")
	rootStaticArchives := splitOrEmpty(splitString[6], ", ")
	rootDynamicLibraries := splitOrEmpty(splitString[7], ", ")
	tocFile := splitString[8] // NOTE: Will be the empty string if there wasn't
	includes := splitOrEmpty(includesString, ", ")
	systemIncludes := splitOrEmpty(systemIncludesString, ", ")
	headers := splitOrEmpty(headersString, ", ")
	rootStaticArchives := splitOrEmpty(rootStaticArchivesString, ", ")
	rootDynamicLibraries := splitOrEmpty(rootDynamicLibrariesString, ", ")
	return CcInfo{
		OutputFiles:          outputFiles,
		CcObjectFiles:        ccObjects,
		CcSharedLibraryFiles: ccSharedLibraries,
		CcStaticLibraryFiles: ccStaticLibraries,
		Includes:             includes,
		SystemIncludes:       systemIncludes,
+38 −8
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ func TestGetPythonBinaryParseResults(t *testing.T) {
}

func TestGetCcInfoParseResults(t *testing.T) {
	const expectedSplits = 10
	noResult := strings.Repeat("|", expectedSplits-1)
	testCases := []struct {
		description          string
		input                string
@@ -71,10 +73,11 @@ func TestGetCcInfoParseResults(t *testing.T) {
	}{
		{
			description: "no result",
			input:       "||||||||",
			input:       noResult,
			expectedOutput: CcInfo{
				OutputFiles:          []string{},
				CcObjectFiles:        []string{},
				CcSharedLibraryFiles: []string{},
				CcStaticLibraryFiles: []string{},
				Includes:             []string{},
				SystemIncludes:       []string{},
@@ -86,10 +89,11 @@ func TestGetCcInfoParseResults(t *testing.T) {
		},
		{
			description: "only output",
			input:       "test||||||||",
			input:       "test" + noResult,
			expectedOutput: CcInfo{
				OutputFiles:          []string{"test"},
				CcObjectFiles:        []string{},
				CcSharedLibraryFiles: []string{},
				CcStaticLibraryFiles: []string{},
				Includes:             []string{},
				SystemIncludes:       []string{},
@@ -99,12 +103,38 @@ func TestGetCcInfoParseResults(t *testing.T) {
				TocFile:              "",
			},
		},
		{
			description: "only ToC",
			input:       noResult + "test",
			expectedOutput: CcInfo{
				OutputFiles:          []string{},
				CcObjectFiles:        []string{},
				CcSharedLibraryFiles: []string{},
				CcStaticLibraryFiles: []string{},
				Includes:             []string{},
				SystemIncludes:       []string{},
				Headers:              []string{},
				RootStaticArchives:   []string{},
				RootDynamicLibraries: []string{},
				TocFile:              "test",
			},
		},
		{
			description: "all items set",
			input:       "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|dir/subdir/hdr.h|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc",
			input: "out1, out2" +
				"|object1, object2" +
				"|shared_lib1, shared_lib2" +
				"|static_lib1, static_lib2" +
				"|., dir/subdir" +
				"|system/dir, system/other/dir" +
				"|dir/subdir/hdr.h" +
				"|rootstaticarchive1" +
				"|rootdynamiclibrary1" +
				"|lib.so.toc",
			expectedOutput: CcInfo{
				OutputFiles:          []string{"out1", "out2"},
				CcObjectFiles:        []string{"object1", "object2"},
				CcSharedLibraryFiles: []string{"shared_lib1", "shared_lib2"},
				CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
				Includes:             []string{".", "dir/subdir"},
				SystemIncludes:       []string{"system/dir", "system/other/dir"},
@@ -118,22 +148,22 @@ func TestGetCcInfoParseResults(t *testing.T) {
			description:          "too few result splits",
			input:                "|",
			expectedOutput:       CcInfo{},
			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, []string{"", ""}),
			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, []string{"", ""}),
		},
		{
			description:          "too many result splits",
			input:                strings.Repeat("|", 50),
			input:                strings.Repeat("|", expectedSplits+1), // 2 too many
			expectedOutput:       CcInfo{},
			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, make([]string, 51)),
			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)),
		},
	}
	for _, tc := range testCases {
		actualOutput, err := GetCcInfo.ParseResult(tc.input)
		if (err == nil && tc.expectedErrorMessage != "") ||
			(err != nil && err.Error() != tc.expectedErrorMessage) {
			t.Errorf("%q: expected Error %s, got %s", tc.description, tc.expectedErrorMessage, err)
			t.Errorf("%q:\nexpected Error %s\n, got %s", tc.description, tc.expectedErrorMessage, err)
		} else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
			t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
			t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput)
		}
	}
}
+1 −1
Original line number Diff line number Diff line
@@ -241,7 +241,7 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries
		entries.Class = "SHARED_LIBRARIES"
		entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
			entries.SetString("LOCAL_SOONG_TOC", library.toc().String())
			if !library.buildStubs() {
			if !library.buildStubs() && library.unstrippedOutputFile != nil {
				entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String())
			}
			if len(library.Properties.Overrides) > 0 {
+64 −0
Original line number Diff line number Diff line
@@ -298,6 +298,7 @@ func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libr
	module, library := NewPrebuiltLibrary(hod, "srcs")
	library.BuildOnlyShared()
	module.bazelable = true
	module.bazelHandler = &prebuiltSharedLibraryBazelHandler{module: module, library: library}

	// Prebuilt shared libraries can be included in APEXes
	android.InitApexModule(module)
@@ -426,6 +427,69 @@ func (h *prebuiltStaticLibraryBazelHandler) GenerateBazelBuildActions(ctx androi
	return true
}

type prebuiltSharedLibraryBazelHandler struct {
	android.BazelHandler

	module  *Module
	library *libraryDecorator
}

func (h *prebuiltSharedLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
	bazelCtx := ctx.Config().BazelContext
	ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx))
	if err != nil {
		ctx.ModuleErrorf("Error getting Bazel CcInfo for %s: %s", label, err)
	}
	if !ok {
		return false
	}
	sharedLibs := ccInfo.CcSharedLibraryFiles
	if len(sharedLibs) != 1 {
		ctx.ModuleErrorf("expected 1 shared library from bazel target %s, got %q", label, sharedLibs)
		return false
	}

	// TODO(b/184543518): cc_prebuilt_library_shared may have properties for re-exporting flags

	// TODO(eakammer):Add stub-related flags if this library is a stub library.
	// h.library.exportVersioningMacroIfNeeded(ctx)

	// Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
	// validation will fail. For now, set this to an empty list.
	// TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
	h.library.collectedSnapshotHeaders = android.Paths{}

	if len(sharedLibs) == 0 {
		h.module.outputFile = android.OptionalPath{}
		return true
	}

	out := android.PathForBazelOut(ctx, sharedLibs[0])
	h.module.outputFile = android.OptionalPathForPath(out)

	// FIXME(b/214600441): We don't yet strip prebuilt shared libraries
	h.library.unstrippedOutputFile = out

	var toc android.Path
	if len(ccInfo.TocFile) > 0 {
		toc = android.PathForBazelOut(ctx, ccInfo.TocFile)
	} else {
		toc = out // Just reuse `out` so ninja still gets an input but won't matter
	}

	info := SharedLibraryInfo{
		SharedLibrary:   out,
		TableOfContents: android.OptionalPathForPath(toc),
		Target:          ctx.Target(),
	}
	ctx.SetProvider(SharedLibraryInfoProvider, info)

	h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
	h.module.maybeUnhideFromMake()

	return true
}

func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
	return &p.Prebuilt
}
+72 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ import (
	"testing"

	"android/soong/android"

	"android/soong/bazel/cquery"
	"github.com/google/blueprint"
)

@@ -378,3 +378,74 @@ func TestPrebuiltLibrarySanitized(t *testing.T) {
	static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
	assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
}

func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) {
	const bp = `
cc_prebuilt_library_shared {
	name: "foo",
	srcs: ["foo.so"],
	bazel_module: { label: "//foo/bar:bar" },
}`
	outBaseDir := "outputbase"
	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
	config.BazelContext = android.MockBazelContext{
		OutputBaseDir: outBaseDir,
		LabelToCcInfo: map[string]cquery.CcInfo{
			"//foo/bar:bar": cquery.CcInfo{
				CcSharedLibraryFiles: []string{"foo.so"},
			},
		},
	}
	ctx := testCcWithConfig(t, config)
	sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
	pathPrefix := outBaseDir + "/execroot/__main__/"

	info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
		pathPrefix+"foo.so", info.SharedLibrary)
	android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC",
		pathPrefix+"foo.so", info.TableOfContents.Path())

	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
	if err != nil {
		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
	}
	expectedOutputFiles := []string{pathPrefix + "foo.so"}
	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
}

func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) {
	const bp = `
cc_prebuilt_library_shared {
	name: "foo",
	srcs: ["foo.so"],
	bazel_module: { label: "//foo/bar:bar" },
}`
	outBaseDir := "outputbase"
	config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
	config.BazelContext = android.MockBazelContext{
		OutputBaseDir: outBaseDir,
		LabelToCcInfo: map[string]cquery.CcInfo{
			"//foo/bar:bar": cquery.CcInfo{
				CcSharedLibraryFiles: []string{"foo.so"},
				TocFile:              "toc",
			},
		},
	}
	ctx := testCcWithConfig(t, config)
	sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
	pathPrefix := outBaseDir + "/execroot/__main__/"

	info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC",
		pathPrefix+"toc", info.TableOfContents.Path())
	android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
		pathPrefix+"foo.so", info.SharedLibrary)

	outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
	if err != nil {
		t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
	}
	expectedOutputFiles := []string{pathPrefix + "foo.so"}
	android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
}