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 )
     20 
     21 type BinaryLinkerProperties struct {
     22 	// compile executable with -static
     23 	Static_executable *bool `android:"arch_variant"`
     24 
     25 	// set the name of the output
     26 	Stem *string `android:"arch_variant"`
     27 
     28 	// append to the name of the output
     29 	Suffix *string `android:"arch_variant"`
     30 
     31 	// if set, add an extra objcopy --prefix-symbols= step
     32 	Prefix_symbols *string
     33 
     34 	// local file name to pass to the linker as --version_script
     35 	Version_script *string `android:"arch_variant"`
     36 
     37 	// if set, install a symlink to the preferred architecture
     38 	Symlink_preferred_arch *bool
     39 
     40 	// install symlinks to the binary.  Symlink names will have the suffix and the binary
     41 	// extension (if any) appended
     42 	Symlinks []string `android:"arch_variant"`
     43 
     44 	// do not pass -pie
     45 	No_pie *bool `android:"arch_variant"`
     46 
     47 	DynamicLinker string `blueprint:"mutated"`
     48 
     49 	// Names of modules to be overridden. Listed modules can only be other binaries
     50 	// (in Make or Soong).
     51 	// This does not completely prevent installation of the overridden binaries, but if both
     52 	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
     53 	// from PRODUCT_PACKAGES.
     54 	Overrides []string
     55 }
     56 
     57 func init() {
     58 	android.RegisterModuleType("cc_binary", binaryFactory)
     59 	android.RegisterModuleType("cc_binary_host", binaryHostFactory)
     60 }
     61 
     62 // Module factory for binaries
     63 func binaryFactory() android.Module {
     64 	module, _ := NewBinary(android.HostAndDeviceSupported)
     65 	return module.Init()
     66 }
     67 
     68 // Module factory for host binaries
     69 func binaryHostFactory() android.Module {
     70 	module, _ := NewBinary(android.HostSupported)
     71 	return module.Init()
     72 }
     73 
     74 //
     75 // Executables
     76 //
     77 
     78 type binaryDecorator struct {
     79 	*baseLinker
     80 	*baseInstaller
     81 	stripper
     82 
     83 	Properties BinaryLinkerProperties
     84 
     85 	toolPath android.OptionalPath
     86 
     87 	// Names of symlinks to be installed for use in LOCAL_MODULE_SYMLINKS
     88 	symlinks []string
     89 
     90 	// Output archive of gcno coverage information
     91 	coverageOutputFile android.OptionalPath
     92 }
     93 
     94 var _ linker = (*binaryDecorator)(nil)
     95 
     96 func (binary *binaryDecorator) linkerProps() []interface{} {
     97 	return append(binary.baseLinker.linkerProps(),
     98 		&binary.Properties,
     99 		&binary.stripper.StripProperties)
    100 
    101 }
    102 
    103 func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string {
    104 	stem := ctx.baseModuleName()
    105 	if String(binary.Properties.Stem) != "" {
    106 		stem = String(binary.Properties.Stem)
    107 	}
    108 
    109 	return stem + String(binary.Properties.Suffix)
    110 }
    111 
    112 func (binary *binaryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
    113 	deps = binary.baseLinker.linkerDeps(ctx, deps)
    114 	if ctx.toolchain().Bionic() {
    115 		if !Bool(binary.baseLinker.Properties.Nocrt) {
    116 			if !ctx.useSdk() {
    117 				if binary.static() {
    118 					deps.CrtBegin = "crtbegin_static"
    119 				} else {
    120 					deps.CrtBegin = "crtbegin_dynamic"
    121 				}
    122 				deps.CrtEnd = "crtend_android"
    123 			} else {
    124 				// TODO(danalbert): Add generation of crt objects.
    125 				// For `sdk_version: "current"`, we don't actually have a
    126 				// freshly generated set of CRT objects. Use the last stable
    127 				// version.
    128 				version := ctx.sdkVersion()
    129 				if version == "current" {
    130 					version = getCurrentNdkPrebuiltVersion(ctx)
    131 				}
    132 
    133 				if binary.static() {
    134 					deps.CrtBegin = "ndk_crtbegin_static." + version
    135 				} else {
    136 					if binary.static() {
    137 						deps.CrtBegin = "ndk_crtbegin_static." + version
    138 					} else {
    139 						deps.CrtBegin = "ndk_crtbegin_dynamic." + version
    140 					}
    141 					deps.CrtEnd = "ndk_crtend_android." + version
    142 				}
    143 			}
    144 		}
    145 
    146 		if binary.static() {
    147 			if ctx.selectedStl() == "libc++_static" {
    148 				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
    149 			}
    150 			// static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
    151 			// --start-group/--end-group along with libgcc.  If they are in deps.StaticLibs,
    152 			// move them to the beginning of deps.LateStaticLibs
    153 			var groupLibs []string
    154 			deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
    155 				[]string{"libc", "libc_nomalloc", "libcompiler_rt"})
    156 			deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
    157 		}
    158 
    159 		if ctx.Os() == android.LinuxBionic && !binary.static() {
    160 			deps.LinkerScript = "host_bionic_linker_script"
    161 		}
    162 	}
    163 
    164 	if !binary.static() && inList("libc", deps.StaticLibs) {
    165 		ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
    166 			"from static libs or set static_executable: true")
    167 	}
    168 
    169 	android.ExtractSourceDeps(ctx, binary.Properties.Version_script)
    170 
    171 	return deps
    172 }
    173 
    174 func (binary *binaryDecorator) isDependencyRoot() bool {
    175 	return true
    176 }
    177 
    178 func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
    179 	module := newModule(hod, android.MultilibFirst)
    180 	binary := &binaryDecorator{
    181 		baseLinker:    NewBaseLinker(),
    182 		baseInstaller: NewBaseInstaller("bin", "", InstallInSystem),
    183 	}
    184 	module.compiler = NewBaseCompiler()
    185 	module.linker = binary
    186 	module.installer = binary
    187 	return module, binary
    188 }
    189 
    190 func (binary *binaryDecorator) linkerInit(ctx BaseModuleContext) {
    191 	binary.baseLinker.linkerInit(ctx)
    192 
    193 	if !ctx.toolchain().Bionic() {
    194 		if ctx.Os() == android.Linux {
    195 			if binary.Properties.Static_executable == nil && ctx.Config().HostStaticBinaries() {
    196 				binary.Properties.Static_executable = BoolPtr(true)
    197 			}
    198 		} else {
    199 			// Static executables are not supported on Darwin or Windows
    200 			binary.Properties.Static_executable = nil
    201 		}
    202 	}
    203 }
    204 
    205 func (binary *binaryDecorator) static() bool {
    206 	return Bool(binary.Properties.Static_executable)
    207 }
    208 
    209 func (binary *binaryDecorator) staticBinary() bool {
    210 	return binary.static()
    211 }
    212 
    213 func (binary *binaryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
    214 	flags = binary.baseLinker.linkerFlags(ctx, flags)
    215 
    216 	if ctx.Host() && !binary.static() {
    217 		if !ctx.Config().IsEnvTrue("DISABLE_HOST_PIE") {
    218 			flags.LdFlags = append(flags.LdFlags, "-pie")
    219 			if ctx.Windows() {
    220 				flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
    221 			}
    222 		}
    223 	}
    224 
    225 	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
    226 	// all code is position independent, and then those warnings get promoted to
    227 	// errors.
    228 	if !ctx.Windows() {
    229 		flags.CFlags = append(flags.CFlags, "-fPIE")
    230 	}
    231 
    232 	if ctx.toolchain().Bionic() {
    233 		if binary.static() {
    234 			// Clang driver needs -static to create static executable.
    235 			// However, bionic/linker uses -shared to overwrite.
    236 			// Linker for x86 targets does not allow coexistance of -static and -shared,
    237 			// so we add -static only if -shared is not used.
    238 			if !inList("-shared", flags.LdFlags) {
    239 				flags.LdFlags = append(flags.LdFlags, "-static")
    240 			}
    241 
    242 			flags.LdFlags = append(flags.LdFlags,
    243 				"-nostdlib",
    244 				"-Bstatic",
    245 				"-Wl,--gc-sections",
    246 			)
    247 		} else {
    248 			if flags.DynamicLinker == "" {
    249 				if binary.Properties.DynamicLinker != "" {
    250 					flags.DynamicLinker = binary.Properties.DynamicLinker
    251 				} else {
    252 					switch ctx.Os() {
    253 					case android.Android:
    254 						flags.DynamicLinker = "/system/bin/linker"
    255 					case android.LinuxBionic:
    256 						flags.DynamicLinker = ""
    257 					default:
    258 						ctx.ModuleErrorf("unknown dynamic linker")
    259 					}
    260 					if flags.Toolchain.Is64Bit() {
    261 						flags.DynamicLinker += "64"
    262 					}
    263 				}
    264 			}
    265 
    266 			flags.LdFlags = append(flags.LdFlags,
    267 				"-pie",
    268 				"-nostdlib",
    269 				"-Bdynamic",
    270 				"-Wl,--gc-sections",
    271 				"-Wl,-z,nocopyreloc",
    272 			)
    273 
    274 		}
    275 	} else {
    276 		if binary.static() {
    277 			flags.LdFlags = append(flags.LdFlags, "-static")
    278 		}
    279 		if ctx.Darwin() {
    280 			flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
    281 		}
    282 	}
    283 
    284 	return flags
    285 }
    286 
    287 func (binary *binaryDecorator) link(ctx ModuleContext,
    288 	flags Flags, deps PathDeps, objs Objects) android.Path {
    289 
    290 	versionScript := ctx.ExpandOptionalSource(binary.Properties.Version_script, "version_script")
    291 	fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
    292 	outputFile := android.PathForModuleOut(ctx, fileName)
    293 	ret := outputFile
    294 
    295 	var linkerDeps android.Paths
    296 
    297 	sharedLibs := deps.SharedLibs
    298 	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
    299 
    300 	if versionScript.Valid() {
    301 		if ctx.Darwin() {
    302 			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
    303 		} else {
    304 			flags.LdFlags = append(flags.LdFlags, "-Wl,--version-script,"+versionScript.String())
    305 			linkerDeps = append(linkerDeps, versionScript.Path())
    306 		}
    307 	}
    308 
    309 	if deps.LinkerScript.Valid() {
    310 		flags.LdFlags = append(flags.LdFlags, "-Wl,-T,"+deps.LinkerScript.String())
    311 		linkerDeps = append(linkerDeps, deps.LinkerScript.Path())
    312 	}
    313 
    314 	if flags.DynamicLinker != "" {
    315 		flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
    316 	}
    317 
    318 	builderFlags := flagsToBuilderFlags(flags)
    319 
    320 	if binary.stripper.needsStrip(ctx) {
    321 		strippedOutputFile := outputFile
    322 		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
    323 		binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
    324 	}
    325 
    326 	if String(binary.Properties.Prefix_symbols) != "" {
    327 		afterPrefixSymbols := outputFile
    328 		outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
    329 		TransformBinaryPrefixSymbols(ctx, String(binary.Properties.Prefix_symbols), outputFile,
    330 			flagsToBuilderFlags(flags), afterPrefixSymbols)
    331 	}
    332 
    333 	if Bool(binary.baseLinker.Properties.Use_version_lib) && ctx.Host() {
    334 		versionedOutputFile := outputFile
    335 		outputFile = android.PathForModuleOut(ctx, "unversioned", fileName)
    336 		binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
    337 	}
    338 
    339 	linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
    340 	linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
    341 	linkerDeps = append(linkerDeps, objs.tidyFiles...)
    342 	linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
    343 
    344 	TransformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs,
    345 		deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
    346 		builderFlags, outputFile)
    347 
    348 	objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
    349 	objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
    350 	binary.coverageOutputFile = TransformCoverageFilesToLib(ctx, objs, builderFlags, binary.getStem(ctx))
    351 
    352 	return ret
    353 }
    354 
    355 func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) {
    356 	binary.baseInstaller.install(ctx, file)
    357 	for _, symlink := range binary.Properties.Symlinks {
    358 		binary.symlinks = append(binary.symlinks,
    359 			symlink+String(binary.Properties.Suffix)+ctx.toolchain().ExecutableSuffix())
    360 	}
    361 
    362 	if Bool(binary.Properties.Symlink_preferred_arch) {
    363 		if String(binary.Properties.Stem) == "" && String(binary.Properties.Suffix) == "" {
    364 			ctx.PropertyErrorf("symlink_preferred_arch", "must also specify stem or suffix")
    365 		}
    366 		if ctx.TargetPrimary() {
    367 			binary.symlinks = append(binary.symlinks, ctx.baseModuleName())
    368 		}
    369 	}
    370 
    371 	for _, symlink := range binary.symlinks {
    372 		ctx.InstallSymlink(binary.baseInstaller.installDir(ctx), symlink, binary.baseInstaller.path)
    373 	}
    374 
    375 	if ctx.Os().Class == android.Host {
    376 		binary.toolPath = android.OptionalPathForPath(binary.baseInstaller.path)
    377 	}
    378 }
    379 
    380 func (binary *binaryDecorator) hostToolPath() android.OptionalPath {
    381 	return binary.toolPath
    382 }
    383