| /* |
| Package crosstooltostarlarklib provides the Transform method |
| for conversion of a CROSSTOOL file to a Starlark rule. |
| |
| https://github.com/bazelbuild/bazel/issues/5380 |
| */ |
| package crosstooltostarlarklib |
| |
| import ( |
| "bytes" |
| "errors" |
| "fmt" |
| "sort" |
| "strings" |
| |
| crosstoolpb "third_party/com/github/bazelbuild/bazel/src/main/protobuf/crosstool_config_go_proto" |
| ) |
| |
| // CToolchainIdentifier is what we'll use to differ between CToolchains |
| // If a CToolchain can be distinguished from the other CToolchains |
| // by only one of the fields (eg if cpu is different for each CToolchain |
| // then only that field will be set. |
| type CToolchainIdentifier struct { |
| cpu string |
| compiler string |
| } |
| |
| // Writes the load statement for the cc_toolchain_config_lib |
| func getCcToolchainConfigHeader() string { |
| return `load("@rules_cc//cc:cc_toolchain_config_lib.bzl", |
| "action_config", |
| "artifact_name_pattern", |
| "env_entry", |
| "env_set", |
| "feature", |
| "feature_set", |
| "flag_group", |
| "flag_set", |
| "make_variable", |
| "tool", |
| "tool_path", |
| "variable_with_value", |
| "with_feature_set", |
| ) |
| ` |
| } |
| |
| var allCompileActions = []string{ |
| "c-compile", |
| "c++-compile", |
| "linkstamp-compile", |
| "assemble", |
| "preprocess-assemble", |
| "c++-header-parsing", |
| "c++-module-compile", |
| "c++-module-codegen", |
| "clif-match", |
| "lto-backend", |
| } |
| |
| var allCppCompileActions = []string{ |
| "c++-compile", |
| "linkstamp-compile", |
| "c++-header-parsing", |
| "c++-module-compile", |
| "c++-module-codegen", |
| "clif-match", |
| } |
| |
| var preprocessorCompileActions = []string{ |
| "c-compile", |
| "c++-compile", |
| "linkstamp-compile", |
| "preprocess-assemble", |
| "c++-header-parsing", |
| "c++-module-compile", |
| "clif-match", |
| } |
| |
| var codegenCompileActions = []string{ |
| "c-compile", |
| "c++-compile", |
| "linkstamp-compile", |
| "assemble", |
| "preprocess-assemble", |
| "c++-module-codegen", |
| "lto-backend", |
| } |
| |
| var allLinkActions = []string{ |
| "c++-link-executable", |
| "c++-link-dynamic-library", |
| "c++-link-nodeps-dynamic-library", |
| } |
| |
| var actionNames = map[string]string{ |
| "c-compile": "ACTION_NAMES.c_compile", |
| "c++-compile": "ACTION_NAMES.cpp_compile", |
| "linkstamp-compile": "ACTION_NAMES.linkstamp_compile", |
| "cc-flags-make-variable": "ACTION_NAMES.cc_flags_make_variable", |
| "c++-module-codegen": "ACTION_NAMES.cpp_module_codegen", |
| "c++-header-parsing": "ACTION_NAMES.cpp_header_parsing", |
| "c++-module-compile": "ACTION_NAMES.cpp_module_compile", |
| "assemble": "ACTION_NAMES.assemble", |
| "preprocess-assemble": "ACTION_NAMES.preprocess_assemble", |
| "lto-indexing": "ACTION_NAMES.lto_indexing", |
| "lto-backend": "ACTION_NAMES.lto_backend", |
| "c++-link-executable": "ACTION_NAMES.cpp_link_executable", |
| "c++-link-dynamic-library": "ACTION_NAMES.cpp_link_dynamic_library", |
| "c++-link-nodeps-dynamic-library": "ACTION_NAMES.cpp_link_nodeps_dynamic_library", |
| "c++-link-static-library": "ACTION_NAMES.cpp_link_static_library", |
| "strip": "ACTION_NAMES.strip", |
| "objc-compile": "ACTION_NAMES.objc_compile", |
| "objc++-compile": "ACTION_NAMES.objcpp_compile", |
| "clif-match": "ACTION_NAMES.clif_match", |
| // "objcopy_embed_data": "ACTION_NAMES.objcopy_embed_data", // copybara-comment-this-out-please |
| // "ld_embed_data": "ACTION_NAMES.ld_embed_data", // copybara-comment-this-out-please |
| } |
| |
| func getLoadActionsStmt() string { |
| return "load(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\n\n" |
| } |
| |
| // Returns a map {toolchain_identifier : CToolchainIdentifier} |
| func toolchainToCToolchainIdentifier( |
| crosstool *crosstoolpb.CrosstoolRelease) map[string]CToolchainIdentifier { |
| cpuToCompiler := make(map[string][]string) |
| compilerToCPU := make(map[string][]string) |
| var cpus []string |
| var compilers []string |
| var identifiers []string |
| res := make(map[string]CToolchainIdentifier) |
| for _, cToolchain := range crosstool.GetToolchain() { |
| cpu := cToolchain.GetTargetCpu() |
| compiler := cToolchain.GetCompiler() |
| |
| cpuToCompiler[cpu] = append(cpuToCompiler[cpu], compiler) |
| compilerToCPU[compiler] = append(compilerToCPU[compiler], cpu) |
| |
| cpus = append(cpus, cToolchain.GetTargetCpu()) |
| compilers = append(compilers, cToolchain.GetCompiler()) |
| identifiers = append(identifiers, cToolchain.GetToolchainIdentifier()) |
| } |
| |
| for i := range cpus { |
| if len(cpuToCompiler[cpus[i]]) == 1 { |
| // if cpu is unique among CToolchains, we don't need the compiler field |
| res[identifiers[i]] = CToolchainIdentifier{cpu: cpus[i], compiler: ""} |
| } else { |
| res[identifiers[i]] = CToolchainIdentifier{ |
| cpu: cpus[i], |
| compiler: compilers[i], |
| } |
| } |
| } |
| return res |
| } |
| |
| func getConditionStatementForCToolchainIdentifier(identifier CToolchainIdentifier) string { |
| if identifier.compiler != "" { |
| return fmt.Sprintf( |
| "ctx.attr.cpu == \"%s\" and ctx.attr.compiler == \"%s\"", |
| identifier.cpu, |
| identifier.compiler) |
| } |
| return fmt.Sprintf("ctx.attr.cpu == \"%s\"", identifier.cpu) |
| } |
| |
| func isArrayPrefix(prefix []string, arr []string) bool { |
| if len(prefix) > len(arr) { |
| return false |
| } |
| for i := 0; i < len(prefix); i++ { |
| if arr[i] != prefix[i] { |
| return false |
| } |
| } |
| return true |
| } |
| |
| func isAllCompileActions(actions []string) (bool, []string) { |
| if isArrayPrefix(allCompileActions, actions) { |
| return true, actions[len(allCompileActions):] |
| } |
| return false, actions |
| } |
| |
| func isAllCppCompileActions(actions []string) (bool, []string) { |
| if isArrayPrefix(allCppCompileActions, actions) { |
| return true, actions[len(allCppCompileActions):] |
| } |
| return false, actions |
| } |
| |
| func isPreprocessorCompileActions(actions []string) (bool, []string) { |
| if isArrayPrefix(preprocessorCompileActions, actions) { |
| return true, actions[len(preprocessorCompileActions):] |
| } |
| return false, actions |
| } |
| |
| func isCodegenCompileActions(actions []string) (bool, []string) { |
| if isArrayPrefix(codegenCompileActions, actions) { |
| return true, actions[len(codegenCompileActions):] |
| } |
| return false, actions |
| } |
| |
| func isAllLinkActions(actions []string) (bool, []string) { |
| if isArrayPrefix(allLinkActions, actions) { |
| return true, actions[len(allLinkActions):] |
| } |
| return false, actions |
| } |
| |
| func getActionNames(actions []string) []string { |
| var res []string |
| for _, el := range actions { |
| if name, ok := actionNames[el]; ok { |
| res = append(res, name) |
| } else { |
| res = append(res, "\""+el+"\"") |
| } |
| } |
| return res |
| } |
| |
| func getListOfActions(name string, depth int) string { |
| var res []string |
| if name == "all_compile_actions" { |
| res = getActionNames(allCompileActions) |
| } else if name == "all_cpp_compile_actions" { |
| res = getActionNames(allCppCompileActions) |
| } else if name == "preprocessor_compile_actions" { |
| res = getActionNames(preprocessorCompileActions) |
| } else if name == "codegen_compile_actions" { |
| res = getActionNames(codegenCompileActions) |
| } else if name == "all_link_actions" { |
| res = getActionNames(allLinkActions) |
| } |
| stmt := fmt.Sprintf("%s%s = %s\n\n", getTabs(depth), |
| name, makeStringArr(res, depth /* isPlainString= */, false)) |
| return stmt |
| } |
| |
| func processActions(actions []string, depth int) []string { |
| var res []string |
| var ok bool |
| initLen := len(actions) |
| if ok, actions = isAllCompileActions(actions); ok { |
| res = append(res, "all_compile_actions") |
| } |
| if ok, actions = isAllCppCompileActions(actions); ok { |
| res = append(res, "all_cpp_compile_actions") |
| } |
| if ok, actions = isPreprocessorCompileActions(actions); ok { |
| res = append(res, "preprocessor_compile_actions") |
| } |
| if ok, actions = isCodegenCompileActions(actions); ok { |
| res = append(res, "codegen_actions") |
| } |
| if ok, actions = isAllLinkActions(actions); ok { |
| res = append(res, "all_link_actions") |
| } |
| if len(actions) != 0 { |
| actions = getActionNames(actions) |
| newDepth := depth + 1 |
| if len(actions) != initLen { |
| newDepth++ |
| } |
| res = append(res, makeStringArr(actions, newDepth /* isPlainString= */, false)) |
| } |
| return res |
| } |
| |
| func getUniqueValues(arr []string) []string { |
| valuesSet := make(map[string]bool) |
| for _, val := range arr { |
| valuesSet[val] = true |
| } |
| var uniques []string |
| for val, _ := range valuesSet { |
| uniques = append(uniques, val) |
| } |
| sort.Strings(uniques) |
| return uniques |
| } |
| |
| func getRule(cToolchainIdentifiers map[string]CToolchainIdentifier, |
| allowedCompilers []string) string { |
| cpus := make(map[string]bool) |
| shouldUseCompilerAttribute := false |
| for _, val := range cToolchainIdentifiers { |
| cpus[val.cpu] = true |
| if val.compiler != "" { |
| shouldUseCompilerAttribute = true |
| } |
| } |
| |
| var cpuValues []string |
| for cpu := range cpus { |
| cpuValues = append(cpuValues, cpu) |
| } |
| |
| var args []string |
| sort.Strings(cpuValues) |
| args = append(args, |
| fmt.Sprintf( |
| `"cpu": attr.string(mandatory=True, values=["%s"]),`, |
| strings.Join(cpuValues, "\", \""))) |
| if shouldUseCompilerAttribute { |
| // If there are two CToolchains that share the cpu we need the compiler attribute |
| // for our cc_toolchain_config rule. |
| allowedCompilers = getUniqueValues(allowedCompilers) |
| args = append(args, |
| fmt.Sprintf(`"compiler": attr.string(mandatory=True, values=["%s"]),`, |
| strings.Join(allowedCompilers, "\", \""))) |
| } |
| return fmt.Sprintf(`cc_toolchain_config = rule( |
| implementation = _impl, |
| attrs = { |
| %s |
| }, |
| provides = [CcToolchainConfigInfo], |
| executable = True, |
| ) |
| `, strings.Join(args, "\n ")) |
| } |
| |
| func getImplHeader() string { |
| return "def _impl(ctx):\n" |
| } |
| |
| func getStringStatement(crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, field string, |
| depth int) string { |
| |
| identifiers := getToolchainIdentifiers(crosstool) |
| var fieldValues []string |
| if field == "toolchain_identifier" { |
| fieldValues = getToolchainIdentifiers(crosstool) |
| } else if field == "host_system_name" { |
| fieldValues = getHostSystemNames(crosstool) |
| } else if field == "target_system_name" { |
| fieldValues = getTargetSystemNames(crosstool) |
| } else if field == "target_cpu" { |
| fieldValues = getTargetCpus(crosstool) |
| } else if field == "target_libc" { |
| fieldValues = getTargetLibcs(crosstool) |
| } else if field == "compiler" { |
| fieldValues = getCompilers(crosstool) |
| } else if field == "abi_version" { |
| fieldValues = getAbiVersions(crosstool) |
| } else if field == "abi_libc_version" { |
| fieldValues = getAbiLibcVersions(crosstool) |
| } else if field == "cc_target_os" { |
| fieldValues = getCcTargetOss(crosstool) |
| } else if field == "builtin_sysroot" { |
| fieldValues = getBuiltinSysroots(crosstool) |
| } |
| |
| mappedValuesToIds := getMappedStringValuesToIdentifiers(identifiers, fieldValues) |
| return getAssignmentStatement(field, mappedValuesToIds, crosstool, |
| cToolchainIdentifiers, depth /* isPlainString= */, true /* shouldFail= */, true) |
| } |
| |
| func getFeatures(crosstool *crosstoolpb.CrosstoolRelease) ( |
| map[string][]string, map[string]map[string][]string, error) { |
| featureNameToFeature := make(map[string]map[string][]string) |
| toolchainToFeatures := make(map[string][]string) |
| for _, toolchain := range crosstool.GetToolchain() { |
| id := toolchain.GetToolchainIdentifier() |
| if len(toolchain.GetFeature()) == 0 { |
| toolchainToFeatures[id] = []string{} |
| } |
| for _, feature := range toolchain.GetFeature() { |
| featureName := strings.ToLower(feature.GetName()) + "_feature" |
| featureName = strings.Replace(featureName, "+", "p", -1) |
| featureName = strings.Replace(featureName, ".", "_", -1) |
| featureName = strings.Replace(featureName, "-", "_", -1) |
| stringFeature, err := parseFeature(feature, 1) |
| if err != nil { |
| return nil, nil, fmt.Errorf( |
| "Error in feature '%s': %v", feature.GetName(), err) |
| } |
| if _, ok := featureNameToFeature[featureName]; !ok { |
| featureNameToFeature[featureName] = make(map[string][]string) |
| } |
| featureNameToFeature[featureName][stringFeature] = append( |
| featureNameToFeature[featureName][stringFeature], id) |
| toolchainToFeatures[id] = append(toolchainToFeatures[id], featureName) |
| } |
| } |
| return toolchainToFeatures, featureNameToFeature, nil |
| } |
| |
| func getFeaturesDeclaration(crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, |
| featureNameToFeature map[string]map[string][]string, depth int) string { |
| var res []string |
| for featureName, featureStringToID := range featureNameToFeature { |
| res = append(res, |
| getAssignmentStatement( |
| featureName, |
| featureStringToID, |
| crosstool, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false, |
| /* shouldFail= */ false)) |
| } |
| return strings.Join(res, "") |
| } |
| |
| func getFeaturesStmt(cToolchainIdentifiers map[string]CToolchainIdentifier, |
| toolchainToFeatures map[string][]string, depth int) string { |
| var res []string |
| arrToIdentifier := make(map[string][]string) |
| for id, features := range toolchainToFeatures { |
| arrayString := strings.Join(features, "{arrayFieldDelimiter}") |
| arrToIdentifier[arrayString] = append(arrToIdentifier[arrayString], id) |
| } |
| res = append(res, |
| getStringArrStatement( |
| "features", |
| arrToIdentifier, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false)) |
| return strings.Join(res, "\n") |
| } |
| |
| func getActions(crosstool *crosstoolpb.CrosstoolRelease) ( |
| map[string][]string, map[string]map[string][]string, error) { |
| actionNameToAction := make(map[string]map[string][]string) |
| toolchainToActions := make(map[string][]string) |
| for _, toolchain := range crosstool.GetToolchain() { |
| id := toolchain.GetToolchainIdentifier() |
| var actionName string |
| if len(toolchain.GetActionConfig()) == 0 { |
| toolchainToActions[id] = []string{} |
| } |
| for _, action := range toolchain.GetActionConfig() { |
| if aName, ok := actionNames[action.GetActionName()]; ok { |
| actionName = aName |
| } else { |
| actionName = strings.ToLower(action.GetActionName()) |
| actionName = strings.Replace(actionName, "+", "p", -1) |
| actionName = strings.Replace(actionName, ".", "_", -1) |
| actionName = strings.Replace(actionName, "-", "_", -1) |
| } |
| stringAction, err := parseAction(action, 1) |
| if err != nil { |
| return nil, nil, fmt.Errorf( |
| "Error in action_config '%s': %v", action.GetActionName(), err) |
| } |
| if _, ok := actionNameToAction[actionName]; !ok { |
| actionNameToAction[actionName] = make(map[string][]string) |
| } |
| actionNameToAction[actionName][stringAction] = append( |
| actionNameToAction[actionName][stringAction], id) |
| toolchainToActions[id] = append( |
| toolchainToActions[id], |
| strings.TrimPrefix(strings.ToLower(actionName), "action_names.")+"_action") |
| } |
| } |
| return toolchainToActions, actionNameToAction, nil |
| } |
| |
| func getActionConfigsDeclaration( |
| crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, |
| actionNameToAction map[string]map[string][]string, depth int) string { |
| var res []string |
| for actionName, actionStringToID := range actionNameToAction { |
| variableName := strings.TrimPrefix(strings.ToLower(actionName), "action_names.") + "_action" |
| res = append(res, |
| getAssignmentStatement( |
| variableName, |
| actionStringToID, |
| crosstool, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false, |
| /* shouldFail= */ false)) |
| } |
| return strings.Join(res, "") |
| } |
| |
| func getActionConfigsStmt( |
| cToolchainIdentifiers map[string]CToolchainIdentifier, |
| toolchainToActions map[string][]string, depth int) string { |
| var res []string |
| arrToIdentifier := make(map[string][]string) |
| for id, actions := range toolchainToActions { |
| var arrayString string |
| arrayString = strings.Join(actions, "{arrayFieldDelimiter}") |
| arrToIdentifier[arrayString] = append(arrToIdentifier[arrayString], id) |
| } |
| res = append(res, |
| getStringArrStatement( |
| "action_configs", |
| arrToIdentifier, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false)) |
| return strings.Join(res, "\n") |
| } |
| |
| func parseAction(action *crosstoolpb.CToolchain_ActionConfig, depth int) (string, error) { |
| actionName := action.GetActionName() |
| aName := "" |
| if val, ok := actionNames[actionName]; ok { |
| aName = val |
| } else { |
| aName = "\"" + action.GetActionName() + "\"" |
| } |
| name := fmt.Sprintf("action_name = %s", aName) |
| fields := []string{name} |
| if action.GetEnabled() { |
| fields = append(fields, "enabled = True") |
| } |
| if len(action.GetFlagSet()) != 0 { |
| flagSets, err := parseFlagSets(action.GetFlagSet(), depth+1) |
| if err != nil { |
| return "", err |
| } |
| fields = append(fields, "flag_sets = "+flagSets) |
| } |
| if len(action.GetImplies()) != 0 { |
| implies := "implies = " + |
| makeStringArr(action.GetImplies(), depth+1 /* isPlainString= */, true) |
| fields = append(fields, implies) |
| } |
| if len(action.GetTool()) != 0 { |
| tools := "tools = " + parseTools(action.GetTool(), depth+1) |
| fields = append(fields, tools) |
| } |
| return createObject("action_config", fields, depth), nil |
| } |
| |
| func getStringArrStatement(attr string, arrValToIds map[string][]string, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, depth int, plainString bool) string { |
| var b bytes.Buffer |
| if len(arrValToIds) == 0 { |
| b.WriteString(fmt.Sprintf("%s%s = []\n", getTabs(depth), attr)) |
| } else if len(arrValToIds) == 1 { |
| for value := range arrValToIds { |
| var arr []string |
| if value == "" { |
| arr = []string{} |
| } else if value == "None" { |
| b.WriteString(fmt.Sprintf("%s%s = None\n", getTabs(depth), attr)) |
| break |
| } else { |
| arr = strings.Split(value, "{arrayFieldDelimiter}") |
| } |
| b.WriteString( |
| fmt.Sprintf( |
| "%s%s = %s\n", |
| getTabs(depth), |
| attr, |
| makeStringArr(arr, depth+1, plainString))) |
| break |
| } |
| } else { |
| first := true |
| var keys []string |
| for k := range arrValToIds { |
| keys = append(keys, k) |
| } |
| sort.Strings(keys) |
| for _, value := range keys { |
| ids := arrValToIds[value] |
| branch := "elif" |
| if first { |
| branch = "if" |
| } |
| first = false |
| var arr []string |
| if value == "" { |
| arr = []string{} |
| } else if value == "None" { |
| b.WriteString( |
| getIfStatement( |
| branch, ids, attr, "None", cToolchainIdentifiers, |
| depth /* isPlainString= */, true)) |
| continue |
| } else { |
| arr = strings.Split(value, "{arrayFieldDelimiter}") |
| } |
| b.WriteString( |
| getIfStatement(branch, ids, attr, |
| makeStringArr(arr, depth+1, plainString), |
| cToolchainIdentifiers, depth /* isPlainString= */, false)) |
| } |
| b.WriteString(fmt.Sprintf("%selse:\n%sfail(\"Unreachable\")\n", getTabs(depth), getTabs(depth+1))) |
| } |
| b.WriteString("\n") |
| return b.String() |
| } |
| |
| func getStringArr(crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, attr string, depth int) string { |
| var res []string |
| arrToIdentifier := make(map[string][]string) |
| for _, toolchain := range crosstool.GetToolchain() { |
| id := toolchain.GetToolchainIdentifier() |
| arrayString := strings.Join(getArrField(attr, toolchain), "{arrayFieldDelimiter}") |
| arrToIdentifier[arrayString] = append(arrToIdentifier[arrayString], id) |
| } |
| statement := getStringArrStatement(attr, arrToIdentifier, cToolchainIdentifiers, depth /* isPlainString= */, true) |
| res = append(res, statement) |
| return strings.Join(res, "\n") |
| } |
| |
| func getArrField(attr string, toolchain *crosstoolpb.CToolchain) []string { |
| var arr []string |
| if attr == "cxx_builtin_include_directories" { |
| arr = toolchain.GetCxxBuiltinIncludeDirectory() |
| } |
| return arr |
| } |
| |
| func getTabs(depth int) string { |
| var res string |
| for i := 0; i < depth; i++ { |
| res = res + " " |
| } |
| return res |
| } |
| |
| func createObject(objtype string, fields []string, depth int) string { |
| if len(fields) == 0 { |
| return objtype + "()" |
| } |
| singleLine := objtype + "(" + strings.Join(fields, ", ") + ")" |
| if len(singleLine) < 60 { |
| return singleLine |
| } |
| return objtype + |
| "(\n" + |
| getTabs(depth+1) + |
| strings.Join(fields, ",\n"+getTabs(depth+1)) + |
| ",\n" + getTabs(depth) + |
| ")" |
| } |
| |
| func getArtifactNamePatterns(crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, depth int) string { |
| var res []string |
| artifactToIds := make(map[string][]string) |
| for _, toolchain := range crosstool.GetToolchain() { |
| artifactNamePatterns := parseArtifactNamePatterns( |
| toolchain.GetArtifactNamePattern(), |
| depth) |
| artifactToIds[artifactNamePatterns] = append( |
| artifactToIds[artifactNamePatterns], |
| toolchain.GetToolchainIdentifier()) |
| } |
| res = append(res, |
| getAssignmentStatement( |
| "artifact_name_patterns", |
| artifactToIds, |
| crosstool, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false, |
| /* shouldFail= */ true)) |
| return strings.Join(res, "\n") |
| } |
| |
| func parseArtifactNamePatterns( |
| artifactNamePatterns []*crosstoolpb.CToolchain_ArtifactNamePattern, depth int) string { |
| var res []string |
| for _, pattern := range artifactNamePatterns { |
| res = append(res, parseArtifactNamePattern(pattern, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseArtifactNamePattern( |
| artifactNamePattern *crosstoolpb.CToolchain_ArtifactNamePattern, depth int) string { |
| categoryName := fmt.Sprintf("category_name = \"%s\"", artifactNamePattern.GetCategoryName()) |
| prefix := fmt.Sprintf("prefix = \"%s\"", artifactNamePattern.GetPrefix()) |
| extension := fmt.Sprintf("extension = \"%s\"", artifactNamePattern.GetExtension()) |
| fields := []string{categoryName, prefix, extension} |
| return createObject("artifact_name_pattern", fields, depth) |
| } |
| |
| func parseFeature(feature *crosstoolpb.CToolchain_Feature, depth int) (string, error) { |
| name := fmt.Sprintf("name = \"%s\"", feature.GetName()) |
| |
| fields := []string{name} |
| if feature.GetEnabled() { |
| fields = append(fields, "enabled = True") |
| } |
| |
| if len(feature.GetFlagSet()) > 0 { |
| flagSets, err := parseFlagSets(feature.GetFlagSet(), depth+1) |
| if err != nil { |
| return "", err |
| } |
| fields = append(fields, "flag_sets = "+flagSets) |
| } |
| if len(feature.GetEnvSet()) > 0 { |
| envSets := "env_sets = " + parseEnvSets(feature.GetEnvSet(), depth+1) |
| fields = append(fields, envSets) |
| } |
| if len(feature.GetRequires()) > 0 { |
| requires := "requires = " + parseFeatureSets(feature.GetRequires(), depth+1) |
| fields = append(fields, requires) |
| } |
| if len(feature.GetImplies()) > 0 { |
| implies := "implies = " + |
| makeStringArr(feature.GetImplies(), depth+1 /* isPlainString= */, true) |
| fields = append(fields, implies) |
| } |
| if len(feature.GetProvides()) > 0 { |
| provides := "provides = " + |
| makeStringArr(feature.GetProvides(), depth+1 /* isPlainString= */, true) |
| fields = append(fields, provides) |
| } |
| return createObject("feature", fields, depth), nil |
| } |
| |
| func parseFlagSets(flagSets []*crosstoolpb.CToolchain_FlagSet, depth int) (string, error) { |
| var res []string |
| for _, flagSet := range flagSets { |
| parsedFlagset, err := parseFlagSet(flagSet, depth+1) |
| if err != nil { |
| return "", err |
| } |
| res = append(res, parsedFlagset) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false), nil |
| } |
| |
| func parseFlagSet(flagSet *crosstoolpb.CToolchain_FlagSet, depth int) (string, error) { |
| var fields []string |
| if len(flagSet.GetAction()) > 0 { |
| actionArr := processActions(flagSet.GetAction(), depth) |
| actions := "actions = " + strings.Join(actionArr, " +\n"+getTabs(depth+2)) |
| fields = append(fields, actions) |
| } |
| if len(flagSet.GetFlagGroup()) > 0 { |
| flagGroups, err := parseFlagGroups(flagSet.GetFlagGroup(), depth+1) |
| if err != nil { |
| return "", err |
| } |
| fields = append(fields, "flag_groups = "+flagGroups) |
| } |
| if len(flagSet.GetWithFeature()) > 0 { |
| withFeatures := "with_features = " + |
| parseWithFeatureSets(flagSet.GetWithFeature(), depth+1) |
| fields = append(fields, withFeatures) |
| } |
| return createObject("flag_set", fields, depth), nil |
| } |
| |
| func parseFlagGroups(flagGroups []*crosstoolpb.CToolchain_FlagGroup, depth int) (string, error) { |
| var res []string |
| for _, flagGroup := range flagGroups { |
| flagGroupString, err := parseFlagGroup(flagGroup, depth+1) |
| if err != nil { |
| return "", err |
| } |
| res = append(res, flagGroupString) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false), nil |
| } |
| |
| func parseFlagGroup(flagGroup *crosstoolpb.CToolchain_FlagGroup, depth int) (string, error) { |
| var res []string |
| if len(flagGroup.GetFlag()) != 0 { |
| res = append(res, "flags = "+makeStringArr(flagGroup.GetFlag(), depth+1, true)) |
| } |
| if flagGroup.GetIterateOver() != "" { |
| res = append(res, fmt.Sprintf("iterate_over = \"%s\"", flagGroup.GetIterateOver())) |
| } |
| if len(flagGroup.GetFlagGroup()) != 0 { |
| flagGroupString, err := parseFlagGroups(flagGroup.GetFlagGroup(), depth+1) |
| if err != nil { |
| return "", err |
| } |
| res = append(res, "flag_groups = "+flagGroupString) |
| } |
| if len(flagGroup.GetExpandIfAllAvailable()) > 1 { |
| return "", errors.New("Flag group must not have more than one 'expand_if_all_available' field") |
| } |
| if len(flagGroup.GetExpandIfAllAvailable()) != 0 { |
| res = append(res, |
| fmt.Sprintf( |
| "expand_if_available = \"%s\"", |
| flagGroup.GetExpandIfAllAvailable()[0])) |
| } |
| if len(flagGroup.GetExpandIfNoneAvailable()) > 1 { |
| return "", errors.New("Flag group must not have more than one 'expand_if_none_available' field") |
| } |
| if len(flagGroup.GetExpandIfNoneAvailable()) != 0 { |
| res = append(res, |
| fmt.Sprintf( |
| "expand_if_not_available = \"%s\"", |
| flagGroup.GetExpandIfNoneAvailable()[0])) |
| } |
| if flagGroup.GetExpandIfTrue() != "" { |
| res = append(res, fmt.Sprintf("expand_if_true = \"%s\"", |
| flagGroup.GetExpandIfTrue())) |
| } |
| if flagGroup.GetExpandIfFalse() != "" { |
| res = append(res, fmt.Sprintf("expand_if_false = \"%s\"", |
| flagGroup.GetExpandIfFalse())) |
| } |
| if flagGroup.GetExpandIfEqual() != nil { |
| res = append(res, |
| "expand_if_equal = "+parseVariableWithValue( |
| flagGroup.GetExpandIfEqual(), depth+1)) |
| } |
| return createObject("flag_group", res, depth), nil |
| } |
| |
| func parseVariableWithValue(variable *crosstoolpb.CToolchain_VariableWithValue, depth int) string { |
| variableName := fmt.Sprintf("name = \"%s\"", variable.GetVariable()) |
| value := fmt.Sprintf("value = \"%s\"", variable.GetValue()) |
| return createObject("variable_with_value", []string{variableName, value}, depth) |
| } |
| |
| func getToolPaths(crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, depth int) string { |
| var res []string |
| toolPathsToIds := make(map[string][]string) |
| for _, toolchain := range crosstool.GetToolchain() { |
| toolPaths := parseToolPaths(toolchain.GetToolPath(), depth) |
| toolPathsToIds[toolPaths] = append( |
| toolPathsToIds[toolPaths], |
| toolchain.GetToolchainIdentifier()) |
| } |
| res = append(res, |
| getAssignmentStatement( |
| "tool_paths", |
| toolPathsToIds, |
| crosstool, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false, |
| /* shouldFail= */ true)) |
| return strings.Join(res, "\n") |
| } |
| |
| func parseToolPaths(toolPaths []*crosstoolpb.ToolPath, depth int) string { |
| var res []string |
| for _, toolPath := range toolPaths { |
| res = append(res, parseToolPath(toolPath, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseToolPath(toolPath *crosstoolpb.ToolPath, depth int) string { |
| name := fmt.Sprintf("name = \"%s\"", toolPath.GetName()) |
| path := toolPath.GetPath() |
| if path == "" { |
| path = "NOT_USED" |
| } |
| path = fmt.Sprintf("path = \"%s\"", path) |
| return createObject("tool_path", []string{name, path}, depth) |
| } |
| |
| func getMakeVariables(crosstool *crosstoolpb.CrosstoolRelease, |
| cToolchainIdentifiers map[string]CToolchainIdentifier, depth int) string { |
| var res []string |
| makeVariablesToIds := make(map[string][]string) |
| for _, toolchain := range crosstool.GetToolchain() { |
| makeVariables := parseMakeVariables(toolchain.GetMakeVariable(), depth) |
| makeVariablesToIds[makeVariables] = append( |
| makeVariablesToIds[makeVariables], |
| toolchain.GetToolchainIdentifier()) |
| } |
| res = append(res, |
| getAssignmentStatement( |
| "make_variables", |
| makeVariablesToIds, |
| crosstool, |
| cToolchainIdentifiers, |
| depth, |
| /* isPlainString= */ false, |
| /* shouldFail= */ true)) |
| return strings.Join(res, "\n") |
| } |
| |
| func parseMakeVariables(makeVariables []*crosstoolpb.MakeVariable, depth int) string { |
| var res []string |
| for _, makeVariable := range makeVariables { |
| res = append(res, parseMakeVariable(makeVariable, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseMakeVariable(makeVariable *crosstoolpb.MakeVariable, depth int) string { |
| name := fmt.Sprintf("name = \"%s\"", makeVariable.GetName()) |
| value := fmt.Sprintf("value = \"%s\"", makeVariable.GetValue()) |
| return createObject("make_variable", []string{name, value}, depth) |
| } |
| |
| func parseTools(tools []*crosstoolpb.CToolchain_Tool, depth int) string { |
| var res []string |
| for _, tool := range tools { |
| res = append(res, parseTool(tool, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseTool(tool *crosstoolpb.CToolchain_Tool, depth int) string { |
| toolPath := "path = \"NOT_USED\"" |
| if tool.GetToolPath() != "" { |
| toolPath = fmt.Sprintf("path = \"%s\"", tool.GetToolPath()) |
| } |
| fields := []string{toolPath} |
| if len(tool.GetWithFeature()) != 0 { |
| withFeatures := "with_features = " + parseWithFeatureSets(tool.GetWithFeature(), depth+1) |
| fields = append(fields, withFeatures) |
| } |
| if len(tool.GetExecutionRequirement()) != 0 { |
| executionRequirements := "execution_requirements = " + |
| makeStringArr(tool.GetExecutionRequirement(), depth+1 /* isPlainString= */, true) |
| fields = append(fields, executionRequirements) |
| } |
| return createObject("tool", fields, depth) |
| } |
| |
| func parseEnvEntries(envEntries []*crosstoolpb.CToolchain_EnvEntry, depth int) string { |
| var res []string |
| for _, envEntry := range envEntries { |
| res = append(res, parseEnvEntry(envEntry, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseEnvEntry(envEntry *crosstoolpb.CToolchain_EnvEntry, depth int) string { |
| key := fmt.Sprintf("key = \"%s\"", envEntry.GetKey()) |
| value := fmt.Sprintf("value = \"%s\"", envEntry.GetValue()) |
| return createObject("env_entry", []string{key, value}, depth) |
| } |
| |
| func parseWithFeatureSets(withFeatureSets []*crosstoolpb.CToolchain_WithFeatureSet, |
| depth int) string { |
| var res []string |
| for _, withFeature := range withFeatureSets { |
| res = append(res, parseWithFeatureSet(withFeature, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseWithFeatureSet(withFeature *crosstoolpb.CToolchain_WithFeatureSet, |
| depth int) string { |
| var fields []string |
| if len(withFeature.GetFeature()) != 0 { |
| features := "features = " + |
| makeStringArr(withFeature.GetFeature(), depth+1 /* isPlainString= */, true) |
| fields = append(fields, features) |
| } |
| if len(withFeature.GetNotFeature()) != 0 { |
| notFeatures := "not_features = " + |
| makeStringArr(withFeature.GetNotFeature(), depth+1 /* isPlainString= */, true) |
| fields = append(fields, notFeatures) |
| } |
| return createObject("with_feature_set", fields, depth) |
| } |
| |
| func parseEnvSets(envSets []*crosstoolpb.CToolchain_EnvSet, depth int) string { |
| var res []string |
| for _, envSet := range envSets { |
| envSetString := parseEnvSet(envSet, depth+1) |
| res = append(res, envSetString) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseEnvSet(envSet *crosstoolpb.CToolchain_EnvSet, depth int) string { |
| actionsStatement := processActions(envSet.GetAction(), depth) |
| actions := "actions = " + strings.Join(actionsStatement, " +\n"+getTabs(depth+2)) |
| fields := []string{actions} |
| if len(envSet.GetEnvEntry()) != 0 { |
| envEntries := "env_entries = " + parseEnvEntries(envSet.GetEnvEntry(), depth+1) |
| fields = append(fields, envEntries) |
| } |
| if len(envSet.GetWithFeature()) != 0 { |
| withFeatures := "with_features = " + parseWithFeatureSets(envSet.GetWithFeature(), depth+1) |
| fields = append(fields, withFeatures) |
| } |
| return createObject("env_set", fields, depth) |
| } |
| |
| func parseFeatureSets(featureSets []*crosstoolpb.CToolchain_FeatureSet, depth int) string { |
| var res []string |
| for _, featureSet := range featureSets { |
| res = append(res, parseFeatureSet(featureSet, depth+1)) |
| } |
| return makeStringArr(res, depth /* isPlainString= */, false) |
| } |
| |
| func parseFeatureSet(featureSet *crosstoolpb.CToolchain_FeatureSet, depth int) string { |
| features := "features = " + |
| makeStringArr(featureSet.GetFeature(), depth+1 /* isPlainString= */, true) |
| return createObject("feature_set", []string{features}, depth) |
| } |
| |
| // Takes in a list of string elements and returns a string that represents |
| // an array : |
| // [ |
| // "element1", |
| // "element2", |
| // ] |
| // The isPlainString argument tells us whether the input elements should be |
| // treated as string (eg, flags), or not (eg, variable names) |
| func makeStringArr(arr []string, depth int, isPlainString bool) string { |
| if len(arr) == 0 { |
| return "[]" |
| } |
| var escapedArr []string |
| for _, el := range arr { |
| if isPlainString { |
| escapedArr = append(escapedArr, strings.Replace(el, "\"", "\\\"", -1)) |
| } else { |
| escapedArr = append(escapedArr, el) |
| } |
| } |
| addQuote := "" |
| if isPlainString { |
| addQuote = "\"" |
| } |
| singleLine := "[" + addQuote + strings.Join(escapedArr, addQuote+", "+addQuote) + addQuote + "]" |
| if len(singleLine) < 60 { |
| return singleLine |
| } |
| return "[\n" + |
| getTabs(depth+1) + |
| addQuote + |
| strings.Join(escapedArr, addQuote+",\n"+getTabs(depth+1)+addQuote) + |
| addQuote + |
| ",\n" + |
| getTabs(depth) + |
| "]" |
| } |
| |
| // Returns a string that represents a value assignment |
| // (eg if ctx.attr.cpu == "linux": |
| // compiler = "llvm" |
| // elif ctx.attr.cpu == "windows": |
| // compiler = "mingw" |
| // else: |
| // fail("Unreachable") |
| func getAssignmentStatement(field string, valToIds map[string][]string, |
| crosstool *crosstoolpb.CrosstoolRelease, |
| toCToolchainIdentifier map[string]CToolchainIdentifier, |
| depth int, isPlainString, shouldFail bool) string { |
| var b bytes.Buffer |
| if len(valToIds) <= 1 { |
| // if there is only one possible value for this field, we don't need if statements |
| for val := range valToIds { |
| if val != "None" && isPlainString { |
| val = "\"" + val + "\"" |
| } |
| b.WriteString(fmt.Sprintf("%s%s = %s\n", getTabs(depth), field, val)) |
| break |
| } |
| } else { |
| first := true |
| var keys []string |
| for k := range valToIds { |
| keys = append(keys, k) |
| } |
| sort.Strings(keys) |
| for _, value := range keys { |
| ids := valToIds[value] |
| branch := "elif" |
| if first { |
| branch = "if" |
| } |
| b.WriteString( |
| getIfStatement(branch, ids, field, value, |
| toCToolchainIdentifier, depth, isPlainString)) |
| first = false |
| } |
| if shouldFail { |
| b.WriteString( |
| fmt.Sprintf( |
| "%selse:\n%sfail(\"Unreachable\")\n", |
| getTabs(depth), getTabs(depth+1))) |
| } else { |
| b.WriteString( |
| fmt.Sprintf( |
| "%selse:\n%s%s = None\n", |
| getTabs(depth), getTabs(depth+1), field)) |
| } |
| } |
| b.WriteString("\n") |
| return b.String() |
| } |
| |
| func getCPUToCompilers(identifiers []CToolchainIdentifier) map[string][]string { |
| res := make(map[string][]string) |
| for _, identifier := range identifiers { |
| if identifier.compiler != "" { |
| res[identifier.cpu] = append(res[identifier.cpu], identifier.compiler) |
| } |
| } |
| return res |
| } |
| |
| func getIfStatement(ifOrElseIf string, identifiers []string, field, val string, |
| toCToolchainIdentifier map[string]CToolchainIdentifier, depth int, |
| isPlainString bool) string { |
| usedStmts := make(map[string]bool) |
| if val != "None" && isPlainString { |
| val = "\"" + val + "\"" |
| } |
| var cToolchainIdentifiers []CToolchainIdentifier |
| for _, value := range toCToolchainIdentifier { |
| cToolchainIdentifiers = append(cToolchainIdentifiers, value) |
| } |
| cpuToCompilers := getCPUToCompilers(cToolchainIdentifiers) |
| countCpus := make(map[string]int) |
| var conditions []string |
| for _, id := range identifiers { |
| identifier := toCToolchainIdentifier[id] |
| stmt := getConditionStatementForCToolchainIdentifier(identifier) |
| if _, ok := usedStmts[stmt]; !ok { |
| conditions = append(conditions, stmt) |
| usedStmts[stmt] = true |
| if identifier.compiler != "" { |
| countCpus[identifier.cpu]++ |
| } |
| } |
| } |
| |
| var compressedConditions []string |
| usedStmtsOptimized := make(map[string]bool) |
| for _, id := range identifiers { |
| identifier := toCToolchainIdentifier[id] |
| var stmt string |
| if _, ok := countCpus[identifier.cpu]; ok { |
| if countCpus[identifier.cpu] == len(cpuToCompilers[identifier.cpu]) { |
| stmt = getConditionStatementForCToolchainIdentifier( |
| CToolchainIdentifier{cpu: identifier.cpu, compiler: ""}) |
| } else { |
| stmt = getConditionStatementForCToolchainIdentifier(identifier) |
| } |
| } else { |
| stmt = getConditionStatementForCToolchainIdentifier(identifier) |
| } |
| if _, ok := usedStmtsOptimized[stmt]; !ok { |
| compressedConditions = append(compressedConditions, stmt) |
| usedStmtsOptimized[stmt] = true |
| } |
| } |
| |
| sort.Strings(compressedConditions) |
| val = strings.Join(strings.Split(val, "\n"+getTabs(depth)), "\n"+getTabs(depth+1)) |
| return fmt.Sprintf(`%s%s %s: |
| %s%s = %s |
| `, getTabs(depth), |
| ifOrElseIf, |
| "("+strings.Join(compressedConditions, "\n"+getTabs(depth+1)+"or ")+")", |
| getTabs(depth+1), |
| field, |
| val) |
| } |
| |
| func getToolchainIdentifiers(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetToolchainIdentifier()) |
| } |
| return res |
| } |
| |
| func getHostSystemNames(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetHostSystemName()) |
| } |
| return res |
| } |
| |
| func getTargetSystemNames(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetTargetSystemName()) |
| } |
| return res |
| } |
| |
| func getTargetCpus(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetTargetCpu()) |
| } |
| return res |
| } |
| |
| func getTargetLibcs(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetTargetLibc()) |
| } |
| return res |
| } |
| |
| func getCompilers(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetCompiler()) |
| } |
| return res |
| } |
| |
| func getAbiVersions(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetAbiVersion()) |
| } |
| return res |
| } |
| |
| func getAbiLibcVersions(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| res = append(res, toolchain.GetAbiLibcVersion()) |
| } |
| return res |
| } |
| |
| func getCcTargetOss(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| targetOS := "None" |
| if toolchain.GetCcTargetOs() != "" { |
| targetOS = toolchain.GetCcTargetOs() |
| } |
| res = append(res, targetOS) |
| } |
| return res |
| } |
| |
| func getBuiltinSysroots(crosstool *crosstoolpb.CrosstoolRelease) []string { |
| var res []string |
| for _, toolchain := range crosstool.GetToolchain() { |
| sysroot := "None" |
| if toolchain.GetBuiltinSysroot() != "" { |
| sysroot = toolchain.GetBuiltinSysroot() |
| } |
| res = append(res, sysroot) |
| } |
| return res |
| } |
| |
| func getMappedStringValuesToIdentifiers(identifiers, fields []string) map[string][]string { |
| res := make(map[string][]string) |
| for i := range identifiers { |
| res[fields[i]] = append(res[fields[i]], identifiers[i]) |
| } |
| return res |
| } |
| |
| func getReturnStatement() string { |
| return ` |
| out = ctx.actions.declare_file(ctx.label.name) |
| ctx.actions.write(out, "Fake executable") |
| return [ |
| cc_common.create_cc_toolchain_config_info( |
| ctx = ctx, |
| features = features, |
| action_configs = action_configs, |
| artifact_name_patterns = artifact_name_patterns, |
| cxx_builtin_include_directories = cxx_builtin_include_directories, |
| toolchain_identifier = toolchain_identifier, |
| host_system_name = host_system_name, |
| target_system_name = target_system_name, |
| target_cpu = target_cpu, |
| target_libc = target_libc, |
| compiler = compiler, |
| abi_version = abi_version, |
| abi_libc_version = abi_libc_version, |
| tool_paths = tool_paths, |
| make_variables = make_variables, |
| builtin_sysroot = builtin_sysroot, |
| cc_target_os = cc_target_os |
| ), |
| DefaultInfo( |
| executable = out, |
| ), |
| ] |
| ` |
| } |
| |
| // Transform writes a cc_toolchain_config rule functionally equivalent to the |
| // CROSSTOOL file. |
| func Transform(crosstool *crosstoolpb.CrosstoolRelease) (string, error) { |
| var b bytes.Buffer |
| |
| cToolchainIdentifiers := toolchainToCToolchainIdentifier(crosstool) |
| |
| toolchainToFeatures, featureNameToFeature, err := getFeatures(crosstool) |
| if err != nil { |
| return "", err |
| } |
| |
| toolchainToActions, actionNameToAction, err := getActions(crosstool) |
| if err != nil { |
| return "", err |
| } |
| |
| header := getCcToolchainConfigHeader() |
| if _, err := b.WriteString(header); err != nil { |
| return "", err |
| } |
| |
| loadActionsStmt := getLoadActionsStmt() |
| if _, err := b.WriteString(loadActionsStmt); err != nil { |
| return "", err |
| } |
| |
| implHeader := getImplHeader() |
| if _, err := b.WriteString(implHeader); err != nil { |
| return "", err |
| } |
| |
| stringFields := []string{ |
| "toolchain_identifier", |
| "host_system_name", |
| "target_system_name", |
| "target_cpu", |
| "target_libc", |
| "compiler", |
| "abi_version", |
| "abi_libc_version", |
| "cc_target_os", |
| "builtin_sysroot", |
| } |
| |
| for _, stringField := range stringFields { |
| stmt := getStringStatement(crosstool, cToolchainIdentifiers, stringField, 1) |
| if _, err := b.WriteString(stmt); err != nil { |
| return "", err |
| } |
| } |
| |
| listsOfActions := []string{ |
| "all_compile_actions", |
| "all_cpp_compile_actions", |
| "preprocessor_compile_actions", |
| "codegen_compile_actions", |
| "all_link_actions", |
| } |
| |
| for _, listOfActions := range listsOfActions { |
| actions := getListOfActions(listOfActions, 1) |
| if _, err := b.WriteString(actions); err != nil { |
| return "", err |
| } |
| } |
| |
| actionConfigDeclaration := getActionConfigsDeclaration( |
| crosstool, cToolchainIdentifiers, actionNameToAction, 1) |
| if _, err := b.WriteString(actionConfigDeclaration); err != nil { |
| return "", err |
| } |
| |
| actionConfigStatement := getActionConfigsStmt( |
| cToolchainIdentifiers, toolchainToActions, 1) |
| if _, err := b.WriteString(actionConfigStatement); err != nil { |
| return "", err |
| } |
| |
| featureDeclaration := getFeaturesDeclaration( |
| crosstool, cToolchainIdentifiers, featureNameToFeature, 1) |
| if _, err := b.WriteString(featureDeclaration); err != nil { |
| return "", err |
| } |
| |
| featuresStatement := getFeaturesStmt( |
| cToolchainIdentifiers, toolchainToFeatures, 1) |
| if _, err := b.WriteString(featuresStatement); err != nil { |
| return "", err |
| } |
| |
| includeDirectories := getStringArr( |
| crosstool, cToolchainIdentifiers, "cxx_builtin_include_directories", 1) |
| if _, err := b.WriteString(includeDirectories); err != nil { |
| return "", err |
| } |
| |
| artifactNamePatterns := getArtifactNamePatterns( |
| crosstool, cToolchainIdentifiers, 1) |
| if _, err := b.WriteString(artifactNamePatterns); err != nil { |
| return "", err |
| } |
| |
| makeVariables := getMakeVariables(crosstool, cToolchainIdentifiers, 1) |
| if _, err := b.WriteString(makeVariables); err != nil { |
| return "", err |
| } |
| |
| toolPaths := getToolPaths(crosstool, cToolchainIdentifiers, 1) |
| if _, err := b.WriteString(toolPaths); err != nil { |
| return "", err |
| } |
| |
| if _, err := b.WriteString(getReturnStatement()); err != nil { |
| return "", err |
| } |
| |
| rule := getRule(cToolchainIdentifiers, getCompilers(crosstool)) |
| if _, err := b.WriteString(rule); err != nil { |
| return "", err |
| } |
| |
| return b.String(), nil |
| } |