github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/binary.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  )
    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  }