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

Commit 550ed750 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Support exporting device arch toolchain info" am: 6fd30471 am: 97cc383f

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1784827

Change-Id: Ia6e381669455b567356acf0d7350521c5cb42a01
parents 10e42b13 97cc383f
Loading
Loading
Loading
Loading
+12 −18
Original line number Diff line number Diff line
@@ -96,31 +96,25 @@ func init() {
	pctx.SourcePathVariable("Arm64GccRoot",
		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")

	pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
	pctx.StaticVariable("Arm64Lldflags", strings.Join(arm64Lldflags, " "))
	exportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
	exportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)

	pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
	pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
	exportStringListStaticVariable("Arm64Cflags", arm64Cflags)
	exportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)

	exportedStringListDictVars.Set("Arm64ArchVariantCflags", arm64ArchVariantCflags)
	exportedStringListDictVars.Set("Arm64CpuVariantCflags", arm64CpuVariantCflags)

	pctx.StaticVariable("Arm64Armv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
	pctx.StaticVariable("Arm64Armv8ABranchProtCflags", strings.Join(arm64ArchVariantCflags["armv8-a-branchprot"], " "))
	pctx.StaticVariable("Arm64Armv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
	pctx.StaticVariable("Arm64Armv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " "))

	pctx.StaticVariable("Arm64CortexA53Cflags",
		strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))

	pctx.StaticVariable("Arm64CortexA55Cflags",
		strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))

	pctx.StaticVariable("Arm64KryoCflags",
		strings.Join(arm64CpuVariantCflags["kryo"], " "))

	pctx.StaticVariable("Arm64ExynosM1Cflags",
		strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))

	pctx.StaticVariable("Arm64ExynosM2Cflags",
		strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
	pctx.StaticVariable("Arm64CortexA53Cflags", strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
	pctx.StaticVariable("Arm64CortexA55Cflags", strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
	pctx.StaticVariable("Arm64KryoCflags", strings.Join(arm64CpuVariantCflags["kryo"], " "))
	pctx.StaticVariable("Arm64ExynosM1Cflags", strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
	pctx.StaticVariable("Arm64ExynosM2Cflags", strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
}

var (
+3 −0
Original line number Diff line number Diff line
@@ -188,6 +188,9 @@ func init() {
	exportStringListStaticVariable("ArmArmCflags", armArmCflags)
	exportStringListStaticVariable("ArmThumbCflags", armThumbCflags)

	exportedStringListDictVars.Set("ArmArchVariantCflags", armArchVariantCflags)
	exportedStringListDictVars.Set("ArmCpuVariantCflags", armCpuVariantCflags)

	// Clang arch variant cflags
	exportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
	exportStringListStaticVariable("ArmArmv7ANeonCflags", armArchVariantCflags["armv7-a-neon"])
+131 −47
Original line number Diff line number Diff line
@@ -15,98 +15,182 @@
package config

import (
	"android/soong/android"
	"fmt"
	"regexp"
	"sort"
	"strings"
)

const (
	bazelIndent = 4
)

type bazelVarExporter interface {
	asBazel(exportedStringVariables, exportedStringListVariables) []bazelConstant
}

// Helpers for exporting cc configuration information to Bazel.
var (
	// Map containing toolchain variables that are independent of the
	// environment variables of the build.
	exportedStringListVars     = exportedStringListVariables{}
	exportedStringVars         = exportedStringVariables{}
	exportedStringListDictVars = exportedStringListDictVariables{}
)

// Ensure that string s has no invalid characters to be generated into the bzl file.
func validateCharacters(s string) string {
	for _, c := range []string{`\n`, `"`, `\`} {
		if strings.Contains(s, c) {
			panic(fmt.Errorf("%s contains illegal character %s", s, c))
		}
	}
	return s
}

type bazelConstant struct {
	variableName       string
	internalDefinition string
}

type exportedStringVariables map[string]string
type exportedStringListVariables map[string][]string

func (m exportedStringVariables) Set(k string, v string) {
	m[k] = v
}

func bazelIndention(level int) string {
	return strings.Repeat(" ", level*bazelIndent)
}

func printBazelList(items []string, indentLevel int) string {
	list := make([]string, 0, len(items)+2)
	list = append(list, "[")
	innerIndent := bazelIndention(indentLevel + 1)
	for _, item := range items {
		list = append(list, fmt.Sprintf(`%s"%s",`, innerIndent, item))
	}
	list = append(list, bazelIndention(indentLevel)+"]")
	return strings.Join(list, "\n")
}

func (m exportedStringVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
	ret := make([]bazelConstant, 0, len(m))
	for k, variableValue := range m {
		expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
		if len(expandedVar) > 1 {
			panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
		}
		ret = append(ret, bazelConstant{
			variableName:       k,
			internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVar[0])),
		})
	}
	return ret
}

// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
func exportStringStaticVariable(name string, value string) {
	pctx.StaticVariable(name, value)
	exportedStringVars.Set(name, value)
}

type exportedStringListVariables map[string][]string

func (m exportedStringListVariables) Set(k string, v []string) {
	m[k] = v
}

func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
	ret := make([]bazelConstant, 0, len(m))
	// For each exported variable, recursively expand elements in the variableValue
	// list to ensure that interpolated variables are expanded according to their values
	// in the variable scope.
	for k, variableValue := range m {
		var expandedVars []string
		for _, v := range variableValue {
			expandedVars = append(expandedVars, expandVar(v, stringScope, stringListScope)...)
		}
		// Assign the list as a bzl-private variable; this variable will be exported
		// out through a constants struct later.
		ret = append(ret, bazelConstant{
			variableName:       k,
			internalDefinition: printBazelList(expandedVars, 0),
		})
	}
	return ret
}

// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
func exportStringListStaticVariable(name string, value []string) {
	pctx.StaticVariable(name, strings.Join(value, " "))
	exportedStringListVars.Set(name, value)
}

// BazelCcToolchainVars generates bzl file content containing variables for
// Bazel's cc_toolchain configuration.
func BazelCcToolchainVars() string {
	ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n"
type exportedStringListDictVariables map[string]map[string][]string

	// Ensure that string s has no invalid characters to be generated into the bzl file.
	validateCharacters := func(s string) string {
		for _, c := range []string{`\n`, `"`, `\`} {
			if strings.Contains(s, c) {
				panic(fmt.Errorf("%s contains illegal character %s", s, c))
func (m exportedStringListDictVariables) Set(k string, v map[string][]string) {
	m[k] = v
}

func printBazelStringListDict(dict map[string][]string) string {
	bazelDict := make([]string, 0, len(dict)+2)
	bazelDict = append(bazelDict, "{")
	for k, v := range dict {
		bazelDict = append(bazelDict,
			fmt.Sprintf(`%s"%s": %s,`, bazelIndention(1), k, printBazelList(v, 1)))
	}
		return s
	bazelDict = append(bazelDict, "}")
	return strings.Join(bazelDict, "\n")
}

	// For each exported variable, recursively expand elements in the variableValue
	// list to ensure that interpolated variables are expanded according to their values
	// in the variable scope.
	for _, k := range android.SortedStringKeys(exportedStringListVars) {
		variableValue := exportedStringListVars[k]
		var expandedVars []string
		for _, v := range variableValue {
			expandedVars = append(expandedVars, expandVar(v, exportedStringVars, exportedStringListVars)...)
// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
func (m exportedStringListDictVariables) asBazel(_ exportedStringVariables, _ exportedStringListVariables) []bazelConstant {
	ret := make([]bazelConstant, 0, len(m))
	for k, dict := range m {
		ret = append(ret, bazelConstant{
			variableName:       k,
			internalDefinition: printBazelStringListDict(dict),
		})
	}
		// Build the list for this variable.
		list := "["
		for _, flag := range expandedVars {
			list += fmt.Sprintf("\n    \"%s\",", validateCharacters(flag))
	return ret
}
		list += "\n]"
		// Assign the list as a bzl-private variable; this variable will be exported
		// out through a constants struct later.
		ret += fmt.Sprintf("_%s = %s\n", k, list)
		ret += "\n"

// BazelCcToolchainVars generates bzl file content containing variables for
// Bazel's cc_toolchain configuration.
func BazelCcToolchainVars() string {
	return bazelToolchainVars(
		exportedStringListDictVars,
		exportedStringListVars,
		exportedStringVars)
}

	for _, k := range android.SortedStringKeys(exportedStringVars) {
		variableValue := exportedStringVars[k]
		expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
		if len(expandedVar) > 1 {
			panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
func bazelToolchainVars(vars ...bazelVarExporter) string {
	ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n"

	results := []bazelConstant{}
	for _, v := range vars {
		results = append(results, v.asBazel(exportedStringVars, exportedStringListVars)...)
	}
		ret += fmt.Sprintf("_%s = \"%s\"\n", k, validateCharacters(expandedVar[0]))
		ret += "\n"

	sort.Slice(results, func(i, j int) bool { return results[i].variableName < results[j].variableName })

	definitions := make([]string, 0, len(results))
	constants := make([]string, 0, len(results))
	for _, b := range results {
		definitions = append(definitions,
			fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
		constants = append(constants,
			fmt.Sprintf("%[1]s%[2]s = _%[2]s,", bazelIndention(1), b.variableName))
	}

	// Build the exported constants struct.
	ret += strings.Join(definitions, "\n\n")
	ret += "\n\n"
	ret += "constants = struct(\n"
	for _, k := range android.SortedStringKeys(exportedStringVars) {
		ret += fmt.Sprintf("    %s = _%s,\n", k, k)
	}
	for _, k := range android.SortedStringKeys(exportedStringListVars) {
		ret += fmt.Sprintf("    %s = _%s,\n", k, k)
	}
	ret += ")"
	ret += strings.Join(constants, "\n")
	ret += "\n)"

	return ret
}

+140 −0
Original line number Diff line number Diff line
@@ -115,3 +115,143 @@ func TestExpandVars(t *testing.T) {
		})
	}
}

func TestBazelToolchainVars(t *testing.T) {
	testCases := []struct {
		name        string
		vars        []bazelVarExporter
		expectedOut string
	}{
		{
			name: "exports strings",
			vars: []bazelVarExporter{
				exportedStringVariables{
					"a": "b",
					"c": "d",
				},
			},
			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.

_a = "b"

_c = "d"

constants = struct(
    a = _a,
    c = _c,
)`,
		},
		{
			name: "exports string lists",
			vars: []bazelVarExporter{
				exportedStringListVariables{
					"a": []string{"b1", "b2"},
					"c": []string{"d1", "d2"},
				},
			},
			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.

_a = [
    "b1",
    "b2",
]

_c = [
    "d1",
    "d2",
]

constants = struct(
    a = _a,
    c = _c,
)`,
		},
		{
			name: "exports string lists dicts",
			vars: []bazelVarExporter{
				exportedStringListDictVariables{
					"a": map[string][]string{"b1": []string{"b2"}},
					"c": map[string][]string{"d1": []string{"d2"}},
				},
			},
			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.

_a = {
    "b1": [
        "b2",
    ],
}

_c = {
    "d1": [
        "d2",
    ],
}

constants = struct(
    a = _a,
    c = _c,
)`,
		},
		{
			name: "sorts across types",
			vars: []bazelVarExporter{
				exportedStringVariables{
					"b": "b-val",
					"d": "d-val",
				},
				exportedStringListVariables{
					"c": []string{"c-val"},
					"e": []string{"e-val"},
				},
				exportedStringListDictVariables{
					"a": map[string][]string{"a1": []string{"a2"}},
					"f": map[string][]string{"f1": []string{"f2"}},
				},
			},
			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.

_a = {
    "a1": [
        "a2",
    ],
}

_b = "b-val"

_c = [
    "c-val",
]

_d = "d-val"

_e = [
    "e-val",
]

_f = {
    "f1": [
        "f2",
    ],
}

constants = struct(
    a = _a,
    b = _b,
    c = _c,
    d = _d,
    e = _e,
    f = _f,
)`,
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			out := bazelToolchainVars(tc.vars...)
			if out != tc.expectedOut {
				t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out)
			}
		})
	}
}
+24 −15
Original line number Diff line number Diff line
@@ -77,6 +77,14 @@ var (
		"popcnt": []string{"-mpopcnt"},
		"aes_ni": []string{"-maes"},
	}

	x86_64DefaultArchVariantFeatures = []string{
		"ssse3",
		"sse4",
		"sse4_1",
		"sse4_2",
		"popcnt",
	}
)

const (
@@ -84,37 +92,38 @@ const (
)

func init() {
	android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64,
		"ssse3",
		"sse4",
		"sse4_1",
		"sse4_2",
		"popcnt")
	android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64, x86_64DefaultArchVariantFeatures...)
	exportedStringListVars.Set("X86_64DefaultArchVariantFeatures", x86_64DefaultArchVariantFeatures)

	pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)

	pctx.SourcePathVariable("X86_64GccRoot",
		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")

	pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
	pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
	exportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
	exportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})

	pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
	pctx.StaticVariable("X86_64Lldflags", strings.Join(x86_64Ldflags, " "))
	exportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
	exportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags)

	// Clang cflags
	pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
	pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
	exportStringListStaticVariable("X86_64Cflags", x86_64Cflags)
	exportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)

	// Yasm flags
	pctx.StaticVariable("X86_64YasmFlags", "-f elf64 -m amd64")
	exportStringListStaticVariable("X86_64YasmFlags", []string{
		"-f elf64",
		"-m amd64",
	})

	// Extended cflags

	exportedStringListDictVars.Set("X86_64ArchVariantCflags", x86_64ArchVariantCflags)
	exportedStringListDictVars.Set("X86_64ArchFeatureCflags", x86_64ArchFeatureCflags)

	// Architecture variant cflags
	for variant, cflags := range x86_64ArchVariantCflags {
		pctx.StaticVariable("X86_64"+variant+"VariantCflags",
			strings.Join(cflags, " "))
		pctx.StaticVariable("X86_64"+variant+"VariantCflags", strings.Join(cflags, " "))
	}
}

Loading