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/proptools" 22 ) 23 24 // This file contains the basic functionality for linking against static libraries and shared 25 // libraries. Final linking into libraries or executables is handled in library.go, binary.go, etc. 26 27 type BaseLinkerProperties struct { 28 // list of modules whose object files should be linked into this module 29 // in their entirety. For static library modules, all of the .o files from the intermediate 30 // directory of the dependency will be linked into this modules .a file. For a shared library, 31 // the dependency's .a file will be linked into this module using -Wl,--whole-archive. 32 Whole_static_libs []string `android:"arch_variant,variant_prepend"` 33 34 // list of modules that should be statically linked into this module. 35 Static_libs []string `android:"arch_variant,variant_prepend"` 36 37 // list of modules that should be dynamically linked into this module. 38 Shared_libs []string `android:"arch_variant"` 39 40 // list of modules that should only provide headers for this module. 41 Header_libs []string `android:"arch_variant,variant_prepend"` 42 43 // list of module-specific flags that will be used for all link steps 44 Ldflags []string `android:"arch_variant"` 45 46 // don't insert default compiler flags into asflags, cflags, 47 // cppflags, conlyflags, ldflags, or include_dirs 48 No_default_compiler_flags *bool 49 50 // list of system libraries that will be dynamically linked to 51 // shared library and executable modules. If unset, generally defaults to libc, 52 // libm, and libdl. Set to [] to prevent linking against the defaults. 53 System_shared_libs []string 54 55 // allow the module to contain undefined symbols. By default, 56 // modules cannot contain undefined symbols that are not satisified by their immediate 57 // dependencies. Set this flag to true to remove --no-undefined from the linker flags. 58 // This flag should only be necessary for compiling low-level libraries like libc. 59 Allow_undefined_symbols *bool `android:"arch_variant"` 60 61 // don't link in libgcc.a 62 No_libgcc *bool 63 64 // -l arguments to pass to linker for host-provided shared libraries 65 Host_ldlibs []string `android:"arch_variant"` 66 67 // list of shared libraries to re-export include directories from. Entries must be 68 // present in shared_libs. 69 Export_shared_lib_headers []string `android:"arch_variant"` 70 71 // list of static libraries to re-export include directories from. Entries must be 72 // present in static_libs. 73 Export_static_lib_headers []string `android:"arch_variant"` 74 75 // list of header libraries to re-export include directories from. Entries must be 76 // present in header_libs. 77 Export_header_lib_headers []string `android:"arch_variant"` 78 79 // list of generated headers to re-export include directories from. Entries must be 80 // present in generated_headers. 81 Export_generated_headers []string `android:"arch_variant"` 82 83 // don't link in crt_begin and crt_end. This flag should only be necessary for 84 // compiling crt or libc. 85 Nocrt *bool `android:"arch_variant"` 86 87 // group static libraries. This can resolve missing symbols issues with interdependencies 88 // between static libraries, but it is generally better to order them correctly instead. 89 Group_static_libs *bool `android:"arch_variant"` 90 91 Target struct { 92 Vendor struct { 93 // list of shared libs that should not be used to build 94 // the vendor variant of the C/C++ module. 95 Exclude_shared_libs []string 96 } 97 } 98 } 99 100 func NewBaseLinker() *baseLinker { 101 return &baseLinker{} 102 } 103 104 // baseLinker provides support for shared_libs, static_libs, and whole_static_libs properties 105 type baseLinker struct { 106 Properties BaseLinkerProperties 107 dynamicProperties struct { 108 RunPaths []string `blueprint:"mutated"` 109 } 110 } 111 112 func (linker *baseLinker) appendLdflags(flags []string) { 113 linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...) 114 } 115 116 func (linker *baseLinker) linkerInit(ctx BaseModuleContext) { 117 if ctx.toolchain().Is64Bit() { 118 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib64", "lib64") 119 } else { 120 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib", "lib") 121 } 122 } 123 124 func (linker *baseLinker) linkerProps() []interface{} { 125 return []interface{}{&linker.Properties, &linker.dynamicProperties} 126 } 127 128 func (linker *baseLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { 129 deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...) 130 deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...) 131 deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Static_libs...) 132 deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Shared_libs...) 133 134 deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, linker.Properties.Export_header_lib_headers...) 135 deps.ReexportStaticLibHeaders = append(deps.ReexportStaticLibHeaders, linker.Properties.Export_static_lib_headers...) 136 deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...) 137 deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...) 138 139 if ctx.vndk() { 140 deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Vendor.Exclude_shared_libs) 141 deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Vendor.Exclude_shared_libs) 142 } 143 144 if ctx.ModuleName() != "libcompiler_rt-extras" { 145 deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras") 146 } 147 148 if ctx.toolchain().Bionic() { 149 // libgcc and libatomic have to be last on the command line 150 deps.LateStaticLibs = append(deps.LateStaticLibs, "libatomic") 151 if !Bool(linker.Properties.No_libgcc) { 152 deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc") 153 } 154 155 if !ctx.static() { 156 systemSharedLibs := linker.Properties.System_shared_libs 157 if systemSharedLibs == nil { 158 systemSharedLibs = []string{"libc", "libm", "libdl"} 159 } 160 161 if inList("libdl", deps.SharedLibs) { 162 // If system_shared_libs has libc but not libdl, make sure shared_libs does not 163 // have libdl to avoid loading libdl before libc. 164 if inList("libc", systemSharedLibs) { 165 if !inList("libdl", systemSharedLibs) { 166 ctx.PropertyErrorf("shared_libs", 167 "libdl must be in system_shared_libs, not shared_libs") 168 } 169 _, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs) 170 } 171 } 172 173 // If libc and libdl are both in system_shared_libs make sure libd comes after libc 174 // to avoid loading libdl before libc. 175 if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) && 176 indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) { 177 ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc") 178 } 179 180 deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...) 181 } else if ctx.sdk() || ctx.vndk() { 182 deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl") 183 } 184 } 185 186 if ctx.Windows() { 187 deps.LateStaticLibs = append(deps.LateStaticLibs, "libwinpthread") 188 } 189 190 return deps 191 } 192 193 func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { 194 toolchain := ctx.toolchain() 195 196 if !ctx.noDefaultCompilerFlags() { 197 if Bool(linker.Properties.Allow_undefined_symbols) { 198 if ctx.Darwin() { 199 // darwin defaults to treating undefined symbols as errors 200 flags.LdFlags = append(flags.LdFlags, "-Wl,-undefined,dynamic_lookup") 201 } 202 } else if !ctx.Darwin() { 203 flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined") 204 } 205 206 if flags.Clang { 207 flags.LdFlags = append(flags.LdFlags, toolchain.ClangLdflags()) 208 } else { 209 flags.LdFlags = append(flags.LdFlags, toolchain.Ldflags()) 210 } 211 212 if !ctx.toolchain().Bionic() { 213 CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs) 214 215 flags.LdFlags = append(flags.LdFlags, linker.Properties.Host_ldlibs...) 216 } 217 } 218 219 CheckBadLinkerFlags(ctx, "ldflags", linker.Properties.Ldflags) 220 221 flags.LdFlags = append(flags.LdFlags, proptools.NinjaAndShellEscape(linker.Properties.Ldflags)...) 222 223 if ctx.Host() { 224 rpath_prefix := `\$$ORIGIN/` 225 if ctx.Darwin() { 226 rpath_prefix = "@loader_path/" 227 } 228 229 for _, rpath := range linker.dynamicProperties.RunPaths { 230 flags.LdFlags = append(flags.LdFlags, "-Wl,-rpath,"+rpath_prefix+rpath) 231 } 232 } 233 234 if flags.Clang { 235 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainClangLdflags()) 236 } else { 237 flags.LdFlags = append(flags.LdFlags, toolchain.ToolchainLdflags()) 238 } 239 240 if Bool(linker.Properties.Group_static_libs) { 241 flags.GroupStaticLibs = true 242 } 243 244 return flags 245 } 246 247 func (linker *baseLinker) link(ctx ModuleContext, 248 flags Flags, deps PathDeps, objs Objects) android.Path { 249 panic(fmt.Errorf("baseLinker doesn't know how to link")) 250 } 251