Home | History | Annotate | Download | only in cc
      1 // Copyright 2016 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package cc
     16 
     17 import (
     18 	"fmt"
     19 	"sort"
     20 	"strings"
     21 
     22 	"android/soong/android"
     23 	"android/soong/cc/config"
     24 )
     25 
     26 func init() {
     27 	android.RegisterMakeVarsProvider(pctx, makeVarsProvider)
     28 }
     29 
     30 func makeVarsProvider(ctx android.MakeVarsContext) {
     31 	ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}")
     32 	ctx.Strict("LLVM_PREBUILTS_VERSION", "${config.ClangVersion}")
     33 	ctx.Strict("LLVM_PREBUILTS_BASE", "${config.ClangBase}")
     34 	ctx.Strict("LLVM_PREBUILTS_PATH", "${config.ClangBin}")
     35 	ctx.Strict("CLANG", "${config.ClangBin}/clang")
     36 	ctx.Strict("CLANG_CXX", "${config.ClangBin}/clang++")
     37 	ctx.Strict("LLVM_AS", "${config.ClangBin}/llvm-as")
     38 	ctx.Strict("LLVM_LINK", "${config.ClangBin}/llvm-link")
     39 	ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy")
     40 	ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " "))
     41 
     42 	ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}")
     43 	ctx.Strict("RS_LLVM_PREBUILTS_BASE", "${config.RSClangBase}")
     44 	ctx.Strict("RS_LLVM_PREBUILTS_PATH", "${config.RSLLVMPrebuiltsPath}")
     45 	ctx.Strict("RS_LLVM_INCLUDES", "${config.RSIncludePath}")
     46 	ctx.Strict("RS_CLANG", "${config.RSLLVMPrebuiltsPath}/clang")
     47 	ctx.Strict("RS_LLVM_AS", "${config.RSLLVMPrebuiltsPath}/llvm-as")
     48 	ctx.Strict("RS_LLVM_LINK", "${config.RSLLVMPrebuiltsPath}/llvm-link")
     49 
     50 	ctx.Strict("GLOBAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideGlobalCflags}")
     51 	ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.ClangExtraNoOverrideCflags}")
     52 	ctx.Strict("GLOBAL_CPPFLAGS_NO_OVERRIDE", "")
     53 	ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
     54 	ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " "))
     55 
     56 	if ctx.Config().ProductVariables.DeviceVndkVersion != nil {
     57 		ctx.Strict("BOARD_VNDK_VERSION", *ctx.Config().ProductVariables.DeviceVndkVersion)
     58 	} else {
     59 		ctx.Strict("BOARD_VNDK_VERSION", "")
     60 	}
     61 
     62 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", asanCflags)
     63 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", asanLdflags)
     64 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES", asanLibs)
     65 
     66 	ctx.Strict("CFI_EXTRA_CFLAGS", cfiCflags)
     67 	ctx.Strict("CFI_EXTRA_LDFLAGS", cfiLdflags)
     68 
     69 	ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion)
     70 	ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion)
     71 	ctx.Strict("DEFAULT_GCC_CPP_STD_VERSION", config.GccCppStdVersion)
     72 	ctx.Strict("EXPERIMENTAL_C_STD_VERSION", config.ExperimentalCStdVersion)
     73 	ctx.Strict("EXPERIMENTAL_CPP_STD_VERSION", config.ExperimentalCppStdVersion)
     74 
     75 	ctx.Strict("DEFAULT_GLOBAL_TIDY_CHECKS", "${config.TidyDefaultGlobalChecks}")
     76 	ctx.Strict("DEFAULT_LOCAL_TIDY_CHECKS", joinLocalTidyChecks(config.DefaultLocalTidyChecks))
     77 	ctx.Strict("DEFAULT_TIDY_HEADER_DIRS", "${config.TidyDefaultHeaderDirs}")
     78 
     79 	ctx.Strict("AIDL_CPP", "${aidlCmd}")
     80 
     81 	includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes} ${config.CommonGlobalSystemIncludes}")
     82 	if err != nil {
     83 		panic(err)
     84 	}
     85 	includes, systemIncludes := splitSystemIncludes(ctx, includeFlags)
     86 	ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " "))
     87 	ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " "))
     88 
     89 	sort.Strings(ndkMigratedLibs)
     90 	ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " "))
     91 
     92 	hostTargets := ctx.Config().Targets[android.Host]
     93 	makeVarsToolchain(ctx, "", hostTargets[0])
     94 	if len(hostTargets) > 1 {
     95 		makeVarsToolchain(ctx, "2ND_", hostTargets[1])
     96 	}
     97 
     98 	crossTargets := ctx.Config().Targets[android.HostCross]
     99 	if len(crossTargets) > 0 {
    100 		makeVarsToolchain(ctx, "", crossTargets[0])
    101 		if len(crossTargets) > 1 {
    102 			makeVarsToolchain(ctx, "2ND_", crossTargets[1])
    103 		}
    104 	}
    105 
    106 	deviceTargets := ctx.Config().Targets[android.Device]
    107 	makeVarsToolchain(ctx, "", deviceTargets[0])
    108 	if len(deviceTargets) > 1 {
    109 		makeVarsToolchain(ctx, "2ND_", deviceTargets[1])
    110 	}
    111 }
    112 
    113 func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
    114 	target android.Target) {
    115 	var typePrefix string
    116 	switch target.Os.Class {
    117 	case android.Host:
    118 		typePrefix = "HOST_"
    119 	case android.HostCross:
    120 		typePrefix = "HOST_CROSS_"
    121 	case android.Device:
    122 		typePrefix = "TARGET_"
    123 	}
    124 	makePrefix := secondPrefix + typePrefix
    125 
    126 	toolchain := config.FindToolchain(target.Os, target.Arch)
    127 
    128 	var productExtraCflags string
    129 	var productExtraLdflags string
    130 
    131 	hod := "Host"
    132 	if target.Os.Class == android.Device {
    133 		hod = "Device"
    134 	}
    135 
    136 	if target.Os.Class == android.Device && Bool(ctx.Config().ProductVariables.Brillo) {
    137 		productExtraCflags += "-D__BRILLO__"
    138 	}
    139 	if target.Os.Class == android.Host && Bool(ctx.Config().ProductVariables.HostStaticBinaries) {
    140 		productExtraLdflags += "-static"
    141 	}
    142 
    143 	ctx.Strict(makePrefix+"GLOBAL_CFLAGS", strings.Join([]string{
    144 		toolchain.Cflags(),
    145 		"${config.CommonGlobalCflags}",
    146 		fmt.Sprintf("${config.%sGlobalCflags}", hod),
    147 		toolchain.ToolchainCflags(),
    148 		productExtraCflags,
    149 	}, " "))
    150 	ctx.Strict(makePrefix+"GLOBAL_CONLYFLAGS", strings.Join([]string{
    151 		"${config.CommonGlobalConlyflags}",
    152 	}, " "))
    153 	ctx.Strict(makePrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{
    154 		"${config.CommonGlobalCppflags}",
    155 		toolchain.Cppflags(),
    156 	}, " "))
    157 	ctx.Strict(makePrefix+"GLOBAL_LDFLAGS", strings.Join([]string{
    158 		toolchain.Ldflags(),
    159 		toolchain.ToolchainLdflags(),
    160 		productExtraLdflags,
    161 	}, " "))
    162 
    163 	includeFlags, err := ctx.Eval(toolchain.IncludeFlags())
    164 	if err != nil {
    165 		panic(err)
    166 	}
    167 	includes, systemIncludes := splitSystemIncludes(ctx, includeFlags)
    168 	ctx.StrictRaw(makePrefix+"C_INCLUDES", strings.Join(includes, " "))
    169 	ctx.StrictRaw(makePrefix+"C_SYSTEM_INCLUDES", strings.Join(systemIncludes, " "))
    170 
    171 	if target.Arch.ArchType == android.Arm {
    172 		flags, err := toolchain.InstructionSetFlags("arm")
    173 		if err != nil {
    174 			panic(err)
    175 		}
    176 		ctx.Strict(makePrefix+"arm_CFLAGS", flags)
    177 
    178 		flags, err = toolchain.InstructionSetFlags("thumb")
    179 		if err != nil {
    180 			panic(err)
    181 		}
    182 		ctx.Strict(makePrefix+"thumb_CFLAGS", flags)
    183 	}
    184 
    185 	if toolchain.ClangSupported() {
    186 		clangPrefix := secondPrefix + "CLANG_" + typePrefix
    187 		clangExtras := "-target " + toolchain.ClangTriple()
    188 		clangExtras += " -B" + config.ToolPath(toolchain)
    189 
    190 		ctx.Strict(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{
    191 			toolchain.ClangCflags(),
    192 			"${config.CommonClangGlobalCflags}",
    193 			fmt.Sprintf("${config.%sClangGlobalCflags}", hod),
    194 			toolchain.ToolchainClangCflags(),
    195 			clangExtras,
    196 			productExtraCflags,
    197 		}, " "))
    198 		ctx.Strict(clangPrefix+"GLOBAL_CPPFLAGS", strings.Join([]string{
    199 			"${config.CommonClangGlobalCppflags}",
    200 			toolchain.ClangCppflags(),
    201 		}, " "))
    202 		ctx.Strict(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{
    203 			toolchain.ClangLdflags(),
    204 			toolchain.ToolchainClangLdflags(),
    205 			productExtraLdflags,
    206 			clangExtras,
    207 		}, " "))
    208 
    209 		if target.Os.Class == android.Device {
    210 			ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so"))
    211 			ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so"))
    212 		}
    213 
    214 		// This is used by external/gentoo/...
    215 		ctx.Strict("CLANG_CONFIG_"+target.Arch.ArchType.Name+"_"+typePrefix+"TRIPLE",
    216 			toolchain.ClangTriple())
    217 	}
    218 
    219 	ctx.Strict(makePrefix+"CC", gccCmd(toolchain, "gcc"))
    220 	ctx.Strict(makePrefix+"CXX", gccCmd(toolchain, "g++"))
    221 
    222 	if target.Os == android.Darwin {
    223 		ctx.Strict(makePrefix+"AR", "${config.MacArPath}")
    224 	} else {
    225 		ctx.Strict(makePrefix+"AR", gccCmd(toolchain, "ar"))
    226 		ctx.Strict(makePrefix+"READELF", gccCmd(toolchain, "readelf"))
    227 		ctx.Strict(makePrefix+"NM", gccCmd(toolchain, "nm"))
    228 	}
    229 
    230 	if target.Os == android.Windows {
    231 		ctx.Strict(makePrefix+"OBJDUMP", gccCmd(toolchain, "objdump"))
    232 	}
    233 
    234 	if target.Os.Class == android.Device {
    235 		ctx.Strict(makePrefix+"OBJCOPY", gccCmd(toolchain, "objcopy"))
    236 		ctx.Strict(makePrefix+"LD", gccCmd(toolchain, "ld"))
    237 		ctx.Strict(makePrefix+"STRIP", gccCmd(toolchain, "strip"))
    238 		ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
    239 		ctx.Strict(makePrefix+"NDK_GCC_VERSION", toolchain.GccVersion())
    240 		ctx.Strict(makePrefix+"NDK_TRIPLE", toolchain.ClangTriple())
    241 	}
    242 
    243 	ctx.Strict(makePrefix+"TOOLCHAIN_ROOT", toolchain.GccRoot())
    244 	ctx.Strict(makePrefix+"TOOLS_PREFIX", gccCmd(toolchain, ""))
    245 	ctx.Strict(makePrefix+"SHLIB_SUFFIX", toolchain.ShlibSuffix())
    246 	ctx.Strict(makePrefix+"EXECUTABLE_SUFFIX", toolchain.ExecutableSuffix())
    247 }
    248 
    249 func splitSystemIncludes(ctx android.MakeVarsContext, val string) (includes, systemIncludes []string) {
    250 	flags, err := ctx.Eval(val)
    251 	if err != nil {
    252 		panic(err)
    253 	}
    254 
    255 	extract := func(flags string, dirs []string, prefix string) (string, []string, bool) {
    256 		if strings.HasPrefix(flags, prefix) {
    257 			flags = strings.TrimPrefix(flags, prefix)
    258 			flags = strings.TrimLeft(flags, " ")
    259 			s := strings.SplitN(flags, " ", 2)
    260 			dirs = append(dirs, s[0])
    261 			if len(s) > 1 {
    262 				return strings.TrimLeft(s[1], " "), dirs, true
    263 			}
    264 			return "", dirs, true
    265 		} else {
    266 			return flags, dirs, false
    267 		}
    268 	}
    269 
    270 	flags = strings.TrimLeft(flags, " ")
    271 	for flags != "" {
    272 		found := false
    273 		flags, includes, found = extract(flags, includes, "-I")
    274 		if !found {
    275 			flags, systemIncludes, found = extract(flags, systemIncludes, "-isystem ")
    276 		}
    277 		if !found {
    278 			panic(fmt.Errorf("Unexpected flag in %q", flags))
    279 		}
    280 	}
    281 
    282 	return includes, systemIncludes
    283 }
    284 
    285 func joinLocalTidyChecks(checks []config.PathBasedTidyCheck) string {
    286 	rets := make([]string, len(checks))
    287 	for i, check := range config.DefaultLocalTidyChecks {
    288 		rets[i] = check.PathPrefix + ":" + check.Checks
    289 	}
    290 	return strings.Join(rets, " ")
    291 }
    292