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 15package cc 16 17import ( 18 "android/soong/android" 19 "android/soong/cc/config" 20 "fmt" 21 "strconv" 22 23 "github.com/google/blueprint" 24 "github.com/google/blueprint/proptools" 25) 26 27// This file contains the basic functionality for linking against static libraries and shared 28// libraries. Final linking into libraries or executables is handled in library.go, binary.go, etc. 29 30type BaseLinkerProperties struct { 31 // list of modules whose object files should be linked into this module 32 // in their entirety. For static library modules, all of the .o files from the intermediate 33 // directory of the dependency will be linked into this modules .a file. For a shared library, 34 // the dependency's .a file will be linked into this module using -Wl,--whole-archive. 35 Whole_static_libs []string `android:"arch_variant,variant_prepend"` 36 37 // list of modules that should be statically linked into this module. 38 Static_libs []string `android:"arch_variant,variant_prepend"` 39 40 // list of modules that should be dynamically linked into this module. 41 Shared_libs []string `android:"arch_variant"` 42 43 // list of modules that should only provide headers for this module. 44 Header_libs []string `android:"arch_variant,variant_prepend"` 45 46 // list of module-specific flags that will be used for all link steps 47 Ldflags []string `android:"arch_variant"` 48 49 // list of system libraries that will be dynamically linked to 50 // shared library and executable modules. If unset, generally defaults to libc, 51 // libm, and libdl. Set to [] to prevent linking against the defaults. 52 System_shared_libs []string `android:"arch_variant"` 53 54 // allow the module to contain undefined symbols. By default, 55 // modules cannot contain undefined symbols that are not satisified by their immediate 56 // dependencies. Set this flag to true to remove --no-undefined from the linker flags. 57 // This flag should only be necessary for compiling low-level libraries like libc. 58 Allow_undefined_symbols *bool `android:"arch_variant"` 59 60 // don't link in libgcc.a 61 No_libgcc *bool 62 63 // don't link in libclang_rt.builtins-*.a 64 No_libcrt *bool `android:"arch_variant"` 65 66 // Use clang lld instead of gnu ld. 67 Use_clang_lld *bool `android:"arch_variant"` 68 69 // -l arguments to pass to linker for host-provided shared libraries 70 Host_ldlibs []string `android:"arch_variant"` 71 72 // list of shared libraries to re-export include directories from. Entries must be 73 // present in shared_libs. 74 Export_shared_lib_headers []string `android:"arch_variant"` 75 76 // list of static libraries to re-export include directories from. Entries must be 77 // present in static_libs. 78 Export_static_lib_headers []string `android:"arch_variant"` 79 80 // list of header libraries to re-export include directories from. Entries must be 81 // present in header_libs. 82 Export_header_lib_headers []string `android:"arch_variant"` 83 84 // list of generated headers to re-export include directories from. Entries must be 85 // present in generated_headers. 86 Export_generated_headers []string `android:"arch_variant"` 87 88 // don't link in crt_begin and crt_end. This flag should only be necessary for 89 // compiling crt or libc. 90 Nocrt *bool `android:"arch_variant"` 91 92 // group static libraries. This can resolve missing symbols issues with interdependencies 93 // between static libraries, but it is generally better to order them correctly instead. 94 Group_static_libs *bool `android:"arch_variant"` 95 96 // list of modules that should be installed with this module. This is similar to 'required' 97 // but '.vendor' suffix will be appended to the module names if the shared libraries have 98 // vendor variants and this module uses VNDK. 99 Runtime_libs []string `android:"arch_variant"` 100 101 Target struct { 102 Vendor struct { 103 // list of shared libs that only should be used to build the vendor 104 // variant of the C/C++ module. 105 Shared_libs []string 106 107 // list of shared libs that should not be used to build the vendor variant 108 // of the C/C++ module. 109 Exclude_shared_libs []string 110 111 // list of static libs that should not be used to build the vendor variant 112 // of the C/C++ module. 113 Exclude_static_libs []string 114 115 // list of header libs that should not be used to build the vendor variant 116 // of the C/C++ module. 117 Exclude_header_libs []string 118 119 // list of runtime libs that should not be installed along with the vendor 120 // variant of the C/C++ module. 121 Exclude_runtime_libs []string 122 123 // version script for this vendor variant 124 Version_script *string `android:"arch_variant"` 125 } 126 Recovery struct { 127 // list of shared libs that only should be used to build the recovery 128 // variant of the C/C++ module. 129 Shared_libs []string 130 131 // list of shared libs that should not be used to build 132 // the recovery variant of the C/C++ module. 133 Exclude_shared_libs []string 134 135 // list of static libs that should not be used to build 136 // the recovery variant of the C/C++ module. 137 Exclude_static_libs []string 138 139 // list of header libs that should not be used to build the recovery variant 140 // of the C/C++ module. 141 Exclude_header_libs []string 142 } 143 } 144 145 // make android::build:GetBuildNumber() available containing the build ID. 146 Use_version_lib *bool `android:"arch_variant"` 147 148 // Generate compact dynamic relocation table, default true. 149 Pack_relocations *bool `android:"arch_variant"` 150 151 // local file name to pass to the linker as --version_script 152 Version_script *string `android:"path,arch_variant"` 153 154 // Local file name to pass to the linker as --symbol-ordering-file 155 Symbol_ordering_file *string `android:"arch_variant"` 156} 157 158func NewBaseLinker(sanitize *sanitize) *baseLinker { 159 return &baseLinker{sanitize: sanitize} 160} 161 162// baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties 163type baseLinker struct { 164 Properties BaseLinkerProperties 165 dynamicProperties struct { 166 RunPaths []string `blueprint:"mutated"` 167 BuildStubs bool `blueprint:"mutated"` 168 } 169 170 sanitize *sanitize 171} 172 173func (linker *baseLinker) appendLdflags(flags []string) { 174 linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...) 175} 176 177func (linker *baseLinker) linkerInit(ctx BaseModuleContext) { 178 if ctx.toolchain().Is64Bit() { 179 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib64", "lib64") 180 } else { 181 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib", "lib") 182 } 183} 184 185func (linker *baseLinker) linkerProps() []interface{} { 186 return []interface{}{&linker.Properties, &linker.dynamicProperties} 187} 188 189func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { 190 deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...) 191 deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...) 192 deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...) 193 deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...) 194 deps.RuntimeLibs = append(deps.RuntimeLibs, linker.Properties.Runtime_libs...) 195 196 deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...) 197 deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...) 198 deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...) 199 deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...) 200 201 if Bool(linker.Properties.Use_version_lib) { 202 deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion") 203 } 204 205 if ctx.useVndk() { 206 deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Vendor.Shared_libs...) 207 deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs) 208 deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs) 209 deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs) 210 deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs) 211 deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs) 212 deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs) 213 deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs) 214 } 215 216 if ctx.inRecovery() { 217 deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Recovery.Shared_libs...) 218 deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs) 219 deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs) 220 deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs) 221 deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Recovery.Exclude_header_libs) 222 deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Recovery.Exclude_header_libs) 223 deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs) 224 deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs) 225 } 226 227 if ctx.toolchain().Bionic() { 228 // libclang_rt.builtins, libgcc and libatomic have to be last on the command line 229 if !Bool(linker.Properties.No_libcrt) { 230 deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain())) 231 deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic") 232 deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc_stripped") 233 } else if !Bool(linker.Properties.No_libgcc) { 234 deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic") 235 deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc") 236 } 237 238 systemSharedLibs := linker.Properties.System_shared_libs 239 if systemSharedLibs == nil { 240 // Provide a default system_shared_libs if it is unspecified. Note: If an 241 // empty list [] is specified, it implies that the module declines the 242 // default system_shared_libs. 243 systemSharedLibs = []string{"libc", "libm", "libdl"} 244 } 245 246 if inList("libdl", deps.SharedLibs) { 247 // If system_shared_libs has libc but not libdl, make sure shared_libs does not 248 // have libdl to avoid loading libdl before libc. 249 if inList("libc", systemSharedLibs) { 250 if !inList("libdl", systemSharedLibs) { 251 ctx.PropertyErrorf("shared_libs", 252 "libdl must be in system_shared_libs, not shared_libs") 253 } 254 _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs) 255 } 256 } 257 258 if inList("libc_scudo", deps.SharedLibs) { 259 // libc_scudo is an alternate implementation of all 260 // allocation functions (malloc, free), that uses 261 // the scudo allocator instead of the default native 262 // allocator. If this library is in the list, make 263 // sure it's first so it properly overrides the 264 // allocation functions of all other shared libraries. 265 _, deps.SharedLibs = removeFromList("libc_scudo", deps.SharedLibs) 266 deps.SharedLibs = append([]string{"libc_scudo"}, deps.SharedLibs...) 267 } 268 269 // If libc and libdl are both in system_shared_libs make sure libdl comes after libc 270 // to avoid loading libdl before libc. 271 if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) && 272 indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) { 273 ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc") 274 } 275 276 deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...) 277 } 278 279 if ctx.Fuchsia() { 280 if ctx.ModuleName() != "libbioniccompat" && 281 ctx.ModuleName() != "libcompiler_rt-extras" && 282 ctx.ModuleName() != "libcompiler_rt" { 283 deps.StaticLibs = append(deps.StaticLibs, "libbioniccompat") 284 } 285 if ctx.ModuleName() != "libcompiler_rt" && ctx.ModuleName() != "libcompiler_rt-extras" { 286 deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt") 287 } 288 289 } 290 291 if ctx.Windows() { 292 deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread") 293 } 294 295 return deps 296} 297 298func (linker *baseLinker) useClangLld(ctx ModuleContext) bool { 299 // Clang lld is not ready for for Darwin host executables yet. 300 // See https://lld.llvm.org/AtomLLD.html for status of lld for Mach-O. 301 if ctx.Darwin() { 302 return false 303 } 304 // http://b/110800681 - lld cannot link Android's Windows modules yet. 305 if ctx.Windows() { 306 return false 307 } 308 if linker.Properties.Use_clang_lld != nil { 309 return Bool(linker.Properties.Use_clang_lld) 310 } 311 return true 312} 313 314// Check whether the SDK version is not older than the specific one 315func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool { 316 if ctx.sdkVersion() == "current" { 317 return true 318 } 319 parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion()) 320 if err != nil { 321 ctx.PropertyErrorf("sdk_version", 322 "Invalid sdk_version value (must be int or current): %q", 323 ctx.sdkVersion()) 324 } 325 if parsedSdkVersion < SdkVersion { 326 return false 327 } 328 return true 329} 330 331// ModuleContext extends BaseModuleContext 332// BaseModuleContext should know if LLD is used? 333func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { 334 toolchain := ctx.toolchain() 335 336 hod := "Host" 337 if ctx.Os().Class == android.Device { 338 hod = "Device" 339 } 340 341 if linker.useClangLld(ctx) { 342 flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLldflags}", hod)) 343 if !BoolDefault(linker.Properties.Pack_relocations, true) { 344 flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=none") 345 } else if ctx.Device() { 346 // The SHT_RELR relocations is only supported by API level >= 28. 347 // Do not turn this on if older version NDK is used. 348 if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 28) { 349 flags.LdFlags = append(flags.LdFlags, "-Wl,--pack-dyn-relocs=android+relr") 350 flags.LdFlags = append(flags.LdFlags, "-Wl,--use-android-relr-tags") 351 } 352 } 353 } else { 354 flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod)) 355 } 356 if Bool(linker.Properties.Allow_undefined_symbols) { 357 if ctx.Darwin() { 358 // darwin defaults to treating undefined symbols as errors 359 flags.LdFlags = append(flags.LdFlags, "-Wl,-undefined,dynamic_lookup") 360 } 361 } else if !ctx.Darwin() { 362 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined") 363 } 364 365 if linker.useClangLld(ctx) { 366 flags.LdFlags = append(flags.LdFlags, toolchain.ClangLldflags()) 367 } else { 368 flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags()) 369 } 370 371 if !ctx.toolchain().Bionic() && !ctx.Fuchsia() { 372 CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs) 373 374 flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...) 375 376 if !ctx.Windows() { 377 // Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device 378 // builds 379 flags.LdFlags = append(flags.LdFlags, 380 "-ldl", 381 "-lpthread", 382 "-lm", 383 ) 384 if !ctx.Darwin() { 385 flags.LdFlags = append(flags.LdFlags, "-lrt") 386 } 387 } 388 } 389 390 if ctx.Fuchsia() { 391 flags.LdFlags = append(flags.LdFlags, "-lfdio", "-lzircon") 392 } 393 394 CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags) 395 396 flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...) 397 398 if ctx.Host() { 399 rpath_prefix := `\$$ORIGIN/` 400 if ctx.Darwin() { 401 rpath_prefix = "@loader_path/" 402 } 403 404 if !ctx.static() { 405 for _, rpath := range linker.dynamicProperties.RunPaths { 406 flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath) 407 } 408 } 409 } 410 411 if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) { 412 // The bionic linker now has support gnu style hashes (which are much faster!), but shipping 413 // to older devices requires the old style hash. Fortunately, we can build with both and 414 // it'll work anywhere. 415 // This is not currently supported on MIPS architectures. 416 flags.LdFlags = append(flags.LdFlags, "-Wl,--hash-style=both") 417 } 418 419 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags()) 420 421 if Bool(linker.Properties.Group_static_libs) { 422 flags.GroupStaticLibs = true 423 } 424 425 // Version_script is not needed when linking stubs lib where the version 426 // script is created from the symbol map file. 427 if !linker.dynamicProperties.BuildStubs { 428 versionScript := ctx.ExpandOptionalSource( 429 linker.Properties.Version_script, "version_script") 430 431 if ctx.useVndk() && linker.Properties.Target.Vendor.Version_script != nil { 432 versionScript = ctx.ExpandOptionalSource( 433 linker.Properties.Target.Vendor.Version_script, 434 "target.vendor.version_script") 435 } 436 437 if versionScript.Valid() { 438 if ctx.Darwin() { 439 ctx.PropertyErrorf("version_script", "Not supported on Darwin") 440 } else { 441 flags.LdFlags = append(flags.LdFlags, 442 "-Wl,--version-script,"+versionScript.String()) 443 flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path()) 444 445 if linker.sanitize.isSanitizerEnabled(cfi) { 446 cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath) 447 flags.LdFlags = append(flags.LdFlags, 448 "-Wl,--version-script,"+cfiExportsMap.String()) 449 flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap) 450 } 451 } 452 } 453 } 454 455 if !linker.dynamicProperties.BuildStubs { 456 symbolOrderingFile := ctx.ExpandOptionalSource( 457 linker.Properties.Symbol_ordering_file, "Symbol_ordering_file") 458 if symbolOrderingFile.Valid() { 459 flags.LdFlags = append(flags.LdFlags, 460 "-Wl,--symbol-ordering-file,"+symbolOrderingFile.String()) 461 flags.LdFlagsDeps = append(flags.LdFlagsDeps, symbolOrderingFile.Path()) 462 } 463 } 464 465 return flags 466} 467 468func (linker *baseLinker) link(ctx ModuleContext, 469 flags Flags, deps PathDeps, objs Objects) android.Path { 470 panic(fmt.Errorf("baseLinker doesn't know how to link")) 471} 472 473// Injecting version symbols 474// Some host modules want a version number, but we don't want to rebuild it every time. Optionally add a step 475// after linking that injects a constant placeholder with the current version number. 476 477func init() { 478 pctx.HostBinToolVariable("symbolInjectCmd", "symbol_inject") 479} 480 481var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol", 482 blueprint.RuleParams{ 483 Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " + 484 "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $buildNumberFromFile", 485 CommandDeps: []string{"$symbolInjectCmd"}, 486 }, 487 "buildNumberFromFile") 488 489func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) { 490 ctx.Build(pctx, android.BuildParams{ 491 Rule: injectVersionSymbol, 492 Description: "inject version symbol", 493 Input: in, 494 Output: out, 495 Args: map[string]string{ 496 "buildNumberFromFile": ctx.Config().BuildNumberFromFile(), 497 }, 498 }) 499} 500