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 	"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