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

Commit 6fd30471 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Support exporting device arch toolchain info"

parents 8f34b0e1 82ad8ccc
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