github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/linker.go (about) 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 "android/soong/android" 19 "fmt" 20 21 "github.com/google/blueprint" 22 "github.com/google/blueprint/proptools" 23 ) 24 25 // This file contains the basic functionality for linking against static libraries and shared 26 // libraries. Final linking into libraries or executables is handled in library.go, binary.go, etc. 27 28 type BaseLinkerProperties struct { 29 // list of modules whose object files should be linked into this module 30 // in their entirety. For static library modules, all of the .o files from the intermediate 31 // directory of the dependency will be linked into this modules .a file. For a shared library, 32 // the dependency's .a file will be linked into this module using -Wl,--whole-archive. 33 Whole_static_libs []string `android:"arch_variant,variant_prepend"` 34 35 // list of modules that should be statically linked into this module. 36 Static_libs []string `android:"arch_variant,variant_prepend"` 37 38 // list of modules that should be dynamically linked into this module. 39 Shared_libs []string `android:"arch_variant"` 40 41 // list of modules that should only provide headers for this module. 42 Header_libs []string `android:"arch_variant,variant_prepend"` 43 44 // list of module-specific flags that will be used for all link steps 45 Ldflags []string `android:"arch_variant"` 46 47 // list of system libraries that will be dynamically linked to 48 // shared library and executable modules. If unset, generally defaults to libc, 49 // libm, and libdl. Set to [] to prevent linking against the defaults. 50 System_shared_libs []string 51 52 // allow the module to contain undefined symbols. By default, 53 // modules cannot contain undefined symbols that are not satisified by their immediate 54 // dependencies. Set this flag to true to remove --no-undefined from the linker flags. 55 // This flag should only be necessary for compiling low-level libraries like libc. 56 Allow_undefined_symbols *bool `android:"arch_variant"` 57 58 // don't link in libgcc.a 59 No_libgcc *bool 60 61 // -l arguments to pass to linker for host-provided shared libraries 62 Host_ldlibs []string `android:"arch_variant"` 63 64 // list of shared libraries to re-export include directories from. Entries must be 65 // present in shared_libs. 66 Export_shared_lib_headers []string `android:"arch_variant"` 67 68 // list of static libraries to re-export include directories from. Entries must be 69 // present in static_libs. 70 Export_static_lib_headers []string `android:"arch_variant"` 71 72 // list of header libraries to re-export include directories from. Entries must be 73 // present in header_libs. 74 Export_header_lib_headers []string `android:"arch_variant"` 75 76 // list of generated headers to re-export include directories from. Entries must be 77 // present in generated_headers. 78 Export_generated_headers []string `android:"arch_variant"` 79 80 // don't link in crt_begin and crt_end. This flag should only be necessary for 81 // compiling crt or libc. 82 Nocrt *bool `android:"arch_variant"` 83 84 // group static libraries. This can resolve missing symbols issues with interdependencies 85 // between static libraries, but it is generally better to order them correctly instead. 86 Group_static_libs *bool `android:"arch_variant"` 87 88 Target struct { 89 Vendor struct { 90 // list of shared libs that should not be used to build 91 // the vendor variant of the C/C++ module. 92 Exclude_shared_libs []string 93 94 // list of static libs that should not be used to build 95 // the vendor variant of the C/C++ module. 96 Exclude_static_libs []string 97 } 98 } 99 100 // make android::build:GetBuildNumber() available containing the build ID. 101 Use_version_lib *bool `android:"arch_variant"` 102 } 103 104 func NewBaseLinker() *baseLinker { 105 return &baseLinker{} 106 } 107 108 // baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties 109 type baseLinker struct { 110 Properties BaseLinkerProperties 111 dynamicProperties struct { 112 RunPaths []string `blueprint:"mutated"` 113 } 114 } 115 116 func (linker *baseLinker) appendLdflags(flags []string) { 117 linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...) 118 } 119 120 func (linker *baseLinker) linkerInit(ctx BaseModuleContext) { 121 if ctx.toolchain().Is64Bit() { 122 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib64", "lib64") 123 } else { 124 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib", "lib") 125 } 126 } 127 128 func (linker *baseLinker) linkerProps() []interface{} { 129 return []interface{}{&linker.Properties, &linker.dynamicProperties} 130 } 131 132 func (linker *baseLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { 133 deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...) 134 deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...) 135 deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...) 136 deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...) 137 138 deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...) 139 deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...) 140 deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...) 141 deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...) 142 143 if Bool(linker.Properties.Use_version_lib) { 144 deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion") 145 } 146 147 if ctx.useVndk() { 148 deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs) 149 deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs) 150 deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs) 151 deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs) 152 deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs) 153 } 154 155 if ctx.ModuleName() != "libcompiler_rt-extras" { 156 deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras") 157 } 158 159 if ctx.toolchain().Bionic() { 160 // libgcc and libatomic have to be last on the command line 161 deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic") 162 if !Bool(linker.Properties.No_libgcc) { 163 deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc") 164 } 165 166 if !ctx.static() { 167 systemSharedLibs := linker.Properties.System_shared_libs 168 if systemSharedLibs == nil { 169 systemSharedLibs = []string{"libc", "libm", "libdl"} 170 } 171 172 if inList("libdl", deps.SharedLibs) { 173 // If system_shared_libs has libc but not libdl, make sure shared_libs does not 174 // have libdl to avoid loading libdl before libc. 175 if inList("libc", systemSharedLibs) { 176 if !inList("libdl", systemSharedLibs) { 177 ctx.PropertyErrorf("shared_libs", 178 "libdl must be in system_shared_libs, not shared_libs") 179 } 180 _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs) 181 } 182 } 183 184 // If libc and libdl are both in system_shared_libs make sure libd comes after libc 185 // to avoid loading libdl before libc. 186 if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) && 187 indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) { 188 ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc") 189 } 190 191 deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...) 192 } else if ctx.useSdk() || ctx.useVndk() { 193 deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl") 194 } 195 } 196 197 if ctx.Windows() { 198 deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread") 199 } 200 201 return deps 202 } 203 204 func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { 205 toolchain := ctx.toolchain() 206 207 hod := "Host" 208 if ctx.Os().Class == android.Device { 209 hod = "Device" 210 } 211 212 flags.LdFlags = append(flags.LdFlags, fmt.Sprintf("${config.%sGlobalLdflags}", hod)) 213 if Bool(linker.Properties.Allow_undefined_symbols) { 214 if ctx.Darwin() { 215 // darwin defaults to treating undefined symbols as errors 216 flags.LdFlags = append(flags.LdFlags, "-Wl,-undefined,dynamic_lookup") 217 } 218 } else if !ctx.Darwin() { 219 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined") 220 } 221 222 if flags.Clang { 223 flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags()) 224 } else { 225 flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags()) 226 } 227 228 if !ctx.toolchain().Bionic() { 229 CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs) 230 231 flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...) 232 233 if !ctx.Windows() { 234 // Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device 235 // builds 236 flags.LdFlags = append(flags.LdFlags, 237 "-ldl", 238 "-lpthread", 239 "-lm", 240 ) 241 if !ctx.Darwin() { 242 flags.LdFlags = append(flags.LdFlags, "-lrt") 243 } 244 } 245 } 246 247 CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags) 248 249 flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscape(linker.Properties.Ldflags)...) 250 251 if ctx.Host() { 252 rpath_prefix := `\$$ORIGIN/` 253 if ctx.Darwin() { 254 rpath_prefix = "@loader_path/" 255 } 256 257 if !ctx.static() { 258 for _, rpath := range linker.dynamicProperties.RunPaths { 259 flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath) 260 } 261 } 262 } 263 264 if ctx.useSdk() && (ctx.Arch().ArchType != android.Mips && ctx.Arch().ArchType != android.Mips64) { 265 // The bionic linker now has support gnu style hashes (which are much faster!), but shipping 266 // to older devices requires the old style hash. Fortunately, we can build with both and 267 // it'll work anywhere. 268 // This is not currently supported on MIPS architectures. 269 flags.LdFlags = append(flags.LdFlags, "-Wl,--hash-style=both") 270 } 271 272 if flags.Clang { 273 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags()) 274 } else { 275 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags()) 276 } 277 278 if Bool(linker.Properties.Group_static_libs) { 279 flags.GroupStaticLibs = true 280 } 281 282 return flags 283 } 284 285 func (linker *baseLinker) link(ctx ModuleContext, 286 flags Flags, deps PathDeps, objs Objects) android.Path { 287 panic(fmt.Errorf("baseLinker doesn't know how to link")) 288 } 289 290 // Injecting version symbols 291 // Some host modules want a version number, but we don't want to rebuild it every time. Optionally add a step 292 // after linking that injects a constant placeholder with the current version number. 293 294 func init() { 295 pctx.HostBinToolVariable("symbolInjectCmd", "symbol_inject") 296 } 297 298 var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol", 299 blueprint.RuleParams{ 300 Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " + 301 "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $buildNumberFromFile", 302 CommandDeps: []string{"$symbolInjectCmd"}, 303 }, 304 "buildNumberFromFile") 305 306 func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) { 307 ctx.Build(pctx, android.BuildParams{ 308 Rule: injectVersionSymbol, 309 Description: "inject version symbol", 310 Input: in, 311 Output: out, 312 Args: map[string]string{ 313 "buildNumberFromFile": ctx.Config().BuildNumberFromFile(), 314 }, 315 }) 316 }