github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/builder.go (about)

     1  // Copyright 2015 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  // This file generates the final rules for compiling all C/C++.  All properties related to
    18  // compiling should have been translated into builderFlags or another argument to the Transform*
    19  // functions.
    20  
    21  import (
    22  	"fmt"
    23  	"path/filepath"
    24  	"runtime"
    25  	"strconv"
    26  	"strings"
    27  
    28  	"github.com/google/blueprint"
    29  
    30  	"android/soong/android"
    31  	"android/soong/cc/config"
    32  )
    33  
    34  const (
    35  	objectExtension        = ".o"
    36  	staticLibraryExtension = ".a"
    37  )
    38  
    39  var (
    40  	abiCheckAllowFlags = []string{
    41  		"-allow-unreferenced-changes",
    42  		"-allow-unreferenced-elf-symbol-changes",
    43  	}
    44  )
    45  
    46  var (
    47  	pctx = android.NewPackageContext("android/soong/cc")
    48  
    49  	cc = pctx.AndroidGomaStaticRule("cc",
    50  		blueprint.RuleParams{
    51  			Depfile:     "${out}.d",
    52  			Deps:        blueprint.DepsGCC,
    53  			Command:     "$relPwd ${config.CcWrapper}$ccCmd -c $cFlags -MD -MF ${out}.d -o $out $in",
    54  			CommandDeps: []string{"$ccCmd"},
    55  		},
    56  		"ccCmd", "cFlags")
    57  
    58  	ld = pctx.AndroidStaticRule("ld",
    59  		blueprint.RuleParams{
    60  			Command: "$ldCmd ${crtBegin} @${out}.rsp " +
    61  				"${libFlags} ${crtEnd} -o ${out} ${ldFlags}",
    62  			CommandDeps:    []string{"$ldCmd"},
    63  			Rspfile:        "${out}.rsp",
    64  			RspfileContent: "${in}",
    65  		},
    66  		"ldCmd", "crtBegin", "libFlags", "crtEnd", "ldFlags")
    67  
    68  	partialLd = pctx.AndroidStaticRule("partialLd",
    69  		blueprint.RuleParams{
    70  			Command:     "$ldCmd -nostdlib -Wl,-r ${in} -o ${out} ${ldFlags}",
    71  			CommandDeps: []string{"$ldCmd"},
    72  		},
    73  		"ldCmd", "ldFlags")
    74  
    75  	ar = pctx.AndroidStaticRule("ar",
    76  		blueprint.RuleParams{
    77  			Command:        "rm -f ${out} && $arCmd $arFlags $out @${out}.rsp",
    78  			CommandDeps:    []string{"$arCmd"},
    79  			Rspfile:        "${out}.rsp",
    80  			RspfileContent: "${in}",
    81  		},
    82  		"arCmd", "arFlags")
    83  
    84  	darwinAr = pctx.AndroidStaticRule("darwinAr",
    85  		blueprint.RuleParams{
    86  			Command:     "rm -f ${out} && ${config.MacArPath} $arFlags $out $in",
    87  			CommandDeps: []string{"${config.MacArPath}"},
    88  		},
    89  		"arFlags")
    90  
    91  	darwinAppendAr = pctx.AndroidStaticRule("darwinAppendAr",
    92  		blueprint.RuleParams{
    93  			Command:     "cp -f ${inAr} ${out}.tmp && ${config.MacArPath} $arFlags ${out}.tmp $in && mv ${out}.tmp ${out}",
    94  			CommandDeps: []string{"${config.MacArPath}", "${inAr}"},
    95  		},
    96  		"arFlags", "inAr")
    97  
    98  	darwinStrip = pctx.AndroidStaticRule("darwinStrip",
    99  		blueprint.RuleParams{
   100  			Command:     "${config.MacStripPath} -u -r -o $out $in",
   101  			CommandDeps: []string{"${config.MacStripPath}"},
   102  		})
   103  
   104  	prefixSymbols = pctx.AndroidStaticRule("prefixSymbols",
   105  		blueprint.RuleParams{
   106  			Command:     "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
   107  			CommandDeps: []string{"$objcopyCmd"},
   108  		},
   109  		"objcopyCmd", "prefix")
   110  
   111  	_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
   112  
   113  	strip = pctx.AndroidStaticRule("strip",
   114  		blueprint.RuleParams{
   115  			Depfile:     "${out}.d",
   116  			Deps:        blueprint.DepsGCC,
   117  			Command:     "CROSS_COMPILE=$crossCompile $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
   118  			CommandDeps: []string{"$stripPath"},
   119  		},
   120  		"args", "crossCompile")
   121  
   122  	emptyFile = pctx.AndroidStaticRule("emptyFile",
   123  		blueprint.RuleParams{
   124  			Command: "rm -f $out && touch $out",
   125  		})
   126  
   127  	_ = pctx.SourcePathVariable("copyGccLibPath", "build/soong/scripts/copygcclib.sh")
   128  
   129  	copyGccLib = pctx.AndroidStaticRule("copyGccLib",
   130  		blueprint.RuleParams{
   131  			Depfile:     "${out}.d",
   132  			Deps:        blueprint.DepsGCC,
   133  			Command:     "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
   134  			CommandDeps: []string{"$copyGccLibPath", "$ccCmd"},
   135  		},
   136  		"ccCmd", "cFlags", "libName")
   137  
   138  	_ = pctx.SourcePathVariable("tocPath", "build/soong/scripts/toc.sh")
   139  
   140  	toc = pctx.AndroidStaticRule("toc",
   141  		blueprint.RuleParams{
   142  			Depfile:     "${out}.d",
   143  			Deps:        blueprint.DepsGCC,
   144  			Command:     "CROSS_COMPILE=$crossCompile $tocPath -i ${in} -o ${out} -d ${out}.d",
   145  			CommandDeps: []string{"$tocPath"},
   146  			Restat:      true,
   147  		},
   148  		"crossCompile")
   149  
   150  	clangTidy = pctx.AndroidStaticRule("clangTidy",
   151  		blueprint.RuleParams{
   152  			Command:     "rm -f $out && ${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
   153  			CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
   154  		},
   155  		"cFlags", "tidyFlags")
   156  
   157  	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
   158  
   159  	yasm = pctx.AndroidStaticRule("yasm",
   160  		blueprint.RuleParams{
   161  			Command:     "$yasmCmd $asFlags -o $out $in && $yasmCmd $asFlags -M $in >$out.d",
   162  			CommandDeps: []string{"$yasmCmd"},
   163  			Depfile:     "$out.d",
   164  			Deps:        blueprint.DepsGCC,
   165  		},
   166  		"asFlags")
   167  
   168  	windres = pctx.AndroidStaticRule("windres",
   169  		blueprint.RuleParams{
   170  			Command:     "$windresCmd $flags -I$$(dirname $in) -i $in -o $out",
   171  			CommandDeps: []string{"$windresCmd"},
   172  		},
   173  		"windresCmd", "flags")
   174  
   175  	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
   176  
   177  	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
   178  	sAbiDump = pctx.AndroidStaticRule("sAbiDump",
   179  		blueprint.RuleParams{
   180  			Command:     "rm -f $out && $sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem ${config.RSIncludePath}",
   181  			CommandDeps: []string{"$sAbiDumper"},
   182  		},
   183  		"cFlags", "exportDirs")
   184  
   185  	_ = pctx.SourcePathVariable("sAbiLinker", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-linker")
   186  
   187  	sAbiLink = pctx.AndroidStaticRule("sAbiLink",
   188  		blueprint.RuleParams{
   189  			Command:        "$sAbiLinker -o ${out} $symbolFilter -arch $arch  $exportedHeaderFlags @${out}.rsp ",
   190  			CommandDeps:    []string{"$sAbiLinker"},
   191  			Rspfile:        "${out}.rsp",
   192  			RspfileContent: "${in}",
   193  		},
   194  		"symbolFilter", "arch", "exportedHeaderFlags")
   195  
   196  	_ = pctx.SourcePathVariable("sAbiDiffer", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-diff")
   197  
   198  	sAbiDiff = pctx.AndroidRuleFunc("sAbiDiff",
   199  		func(ctx android.PackageRuleContext) blueprint.RuleParams {
   200  			// TODO(b/78139997): Add -check-all-apis back
   201  			commandStr := "($sAbiDiffer $allowFlags -lib $libName -arch $arch -o ${out} -new $in -old $referenceDump)"
   202  			distAbiDiffDir := android.PathForDist(ctx, "abidiffs")
   203  			commandStr += "|| (echo ' ---- Please update abi references by running platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l ${libName} ----'"
   204  			if distAbiDiffDir.Valid() {
   205  				commandStr += " && (mkdir -p " + distAbiDiffDir.String() + " && cp ${out} " + distAbiDiffDir.String() + ")"
   206  			}
   207  			commandStr += " && exit 1)"
   208  			return blueprint.RuleParams{
   209  				Command:     commandStr,
   210  				CommandDeps: []string{"$sAbiDiffer"},
   211  			}
   212  		},
   213  		"allowFlags", "referenceDump", "libName", "arch")
   214  
   215  	unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
   216  		blueprint.RuleParams{
   217  			Command: "gunzip -c $in > $out",
   218  		})
   219  )
   220  
   221  func init() {
   222  	// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
   223  	// debug output. That way two builds in two different directories will
   224  	// create the same output.
   225  	if runtime.GOOS != "darwin" {
   226  		pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
   227  	} else {
   228  		// Darwin doesn't have /proc
   229  		pctx.StaticVariable("relPwd", "")
   230  	}
   231  }
   232  
   233  type builderFlags struct {
   234  	globalFlags    string
   235  	arFlags        string
   236  	asFlags        string
   237  	cFlags         string
   238  	toolingCFlags  string // A separate set of Cflags for clang LibTooling tools
   239  	conlyFlags     string
   240  	cppFlags       string
   241  	ldFlags        string
   242  	libFlags       string
   243  	yaccFlags      string
   244  	protoFlags     string
   245  	protoOutParams string
   246  	tidyFlags      string
   247  	sAbiFlags      string
   248  	yasmFlags      string
   249  	aidlFlags      string
   250  	rsFlags        string
   251  	toolchain      config.Toolchain
   252  	clang          bool
   253  	tidy           bool
   254  	coverage       bool
   255  	sAbiDump       bool
   256  	protoRoot      bool
   257  
   258  	systemIncludeFlags string
   259  
   260  	groupStaticLibs bool
   261  	arGoldPlugin    bool
   262  
   263  	stripKeepSymbols       bool
   264  	stripKeepMiniDebugInfo bool
   265  	stripAddGnuDebuglink   bool
   266  }
   267  
   268  type Objects struct {
   269  	objFiles      android.Paths
   270  	tidyFiles     android.Paths
   271  	coverageFiles android.Paths
   272  	sAbiDumpFiles android.Paths
   273  }
   274  
   275  func (a Objects) Copy() Objects {
   276  	return Objects{
   277  		objFiles:      append(android.Paths{}, a.objFiles...),
   278  		tidyFiles:     append(android.Paths{}, a.tidyFiles...),
   279  		coverageFiles: append(android.Paths{}, a.coverageFiles...),
   280  		sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
   281  	}
   282  }
   283  
   284  func (a Objects) Append(b Objects) Objects {
   285  	return Objects{
   286  		objFiles:      append(a.objFiles, b.objFiles...),
   287  		tidyFiles:     append(a.tidyFiles, b.tidyFiles...),
   288  		coverageFiles: append(a.coverageFiles, b.coverageFiles...),
   289  		sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
   290  	}
   291  }
   292  
   293  // Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
   294  func TransformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles android.Paths,
   295  	flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
   296  
   297  	objFiles := make(android.Paths, len(srcFiles))
   298  	var tidyFiles android.Paths
   299  	if flags.tidy && flags.clang {
   300  		tidyFiles = make(android.Paths, 0, len(srcFiles))
   301  	}
   302  	var coverageFiles android.Paths
   303  	if flags.coverage {
   304  		coverageFiles = make(android.Paths, 0, len(srcFiles))
   305  	}
   306  
   307  	commonFlags := strings.Join([]string{
   308  		flags.globalFlags,
   309  		flags.systemIncludeFlags,
   310  	}, " ")
   311  
   312  	toolingCflags := strings.Join([]string{
   313  		commonFlags,
   314  		flags.toolingCFlags,
   315  		flags.conlyFlags,
   316  	}, " ")
   317  
   318  	cflags := strings.Join([]string{
   319  		commonFlags,
   320  		flags.cFlags,
   321  		flags.conlyFlags,
   322  	}, " ")
   323  
   324  	toolingCppflags := strings.Join([]string{
   325  		commonFlags,
   326  		flags.toolingCFlags,
   327  		flags.cppFlags,
   328  	}, " ")
   329  
   330  	cppflags := strings.Join([]string{
   331  		commonFlags,
   332  		flags.cFlags,
   333  		flags.cppFlags,
   334  	}, " ")
   335  
   336  	asflags := strings.Join([]string{
   337  		commonFlags,
   338  		flags.asFlags,
   339  	}, " ")
   340  
   341  	var sAbiDumpFiles android.Paths
   342  	if flags.sAbiDump && flags.clang {
   343  		sAbiDumpFiles = make(android.Paths, 0, len(srcFiles))
   344  	}
   345  
   346  	if flags.clang {
   347  		cflags += " ${config.NoOverrideClangGlobalCflags}"
   348  		toolingCflags += " ${config.NoOverrideClangGlobalCflags}"
   349  		cppflags += " ${config.NoOverrideClangGlobalCflags}"
   350  		toolingCppflags += " ${config.NoOverrideClangGlobalCflags}"
   351  	} else {
   352  		cflags += " ${config.NoOverrideGlobalCflags}"
   353  		cppflags += " ${config.NoOverrideGlobalCflags}"
   354  	}
   355  
   356  	for i, srcFile := range srcFiles {
   357  		objFile := android.ObjPathWithExt(ctx, subdir, srcFile, "o")
   358  
   359  		objFiles[i] = objFile
   360  
   361  		switch srcFile.Ext() {
   362  		case ".asm":
   363  			ctx.Build(pctx, android.BuildParams{
   364  				Rule:        yasm,
   365  				Description: "yasm " + srcFile.Rel(),
   366  				Output:      objFile,
   367  				Input:       srcFile,
   368  				Implicits:   cFlagsDeps,
   369  				OrderOnly:   pathDeps,
   370  				Args: map[string]string{
   371  					"asFlags": flags.yasmFlags,
   372  				},
   373  			})
   374  			continue
   375  		case ".rc":
   376  			ctx.Build(pctx, android.BuildParams{
   377  				Rule:        windres,
   378  				Description: "windres " + srcFile.Rel(),
   379  				Output:      objFile,
   380  				Input:       srcFile,
   381  				Implicits:   cFlagsDeps,
   382  				OrderOnly:   pathDeps,
   383  				Args: map[string]string{
   384  					"windresCmd": gccCmd(flags.toolchain, "windres"),
   385  					"flags":      flags.toolchain.WindresFlags(),
   386  				},
   387  			})
   388  			continue
   389  		}
   390  
   391  		var moduleCflags string
   392  		var moduleToolingCflags string
   393  		var ccCmd string
   394  		tidy := flags.tidy && flags.clang
   395  		coverage := flags.coverage
   396  		dump := flags.sAbiDump && flags.clang
   397  
   398  		switch srcFile.Ext() {
   399  		case ".S", ".s":
   400  			ccCmd = "gcc"
   401  			moduleCflags = asflags
   402  			tidy = false
   403  			coverage = false
   404  			dump = false
   405  		case ".c":
   406  			ccCmd = "gcc"
   407  			moduleCflags = cflags
   408  			moduleToolingCflags = toolingCflags
   409  		case ".cpp", ".cc", ".mm":
   410  			ccCmd = "g++"
   411  			moduleCflags = cppflags
   412  			moduleToolingCflags = toolingCppflags
   413  		default:
   414  			ctx.ModuleErrorf("File %s has unknown extension", srcFile)
   415  			continue
   416  		}
   417  
   418  		if flags.clang {
   419  			switch ccCmd {
   420  			case "gcc":
   421  				ccCmd = "clang"
   422  			case "g++":
   423  				ccCmd = "clang++"
   424  			default:
   425  				panic("unrecoginzied ccCmd")
   426  			}
   427  		}
   428  
   429  		ccDesc := ccCmd
   430  
   431  		if flags.clang {
   432  			ccCmd = "${config.ClangBin}/" + ccCmd
   433  		} else {
   434  			ccCmd = gccCmd(flags.toolchain, ccCmd)
   435  		}
   436  
   437  		var implicitOutputs android.WritablePaths
   438  		if coverage {
   439  			gcnoFile := android.ObjPathWithExt(ctx, subdir, srcFile, "gcno")
   440  			implicitOutputs = append(implicitOutputs, gcnoFile)
   441  			coverageFiles = append(coverageFiles, gcnoFile)
   442  		}
   443  
   444  		ctx.Build(pctx, android.BuildParams{
   445  			Rule:            cc,
   446  			Description:     ccDesc + " " + srcFile.Rel(),
   447  			Output:          objFile,
   448  			ImplicitOutputs: implicitOutputs,
   449  			Input:           srcFile,
   450  			Implicits:       cFlagsDeps,
   451  			OrderOnly:       pathDeps,
   452  			Args: map[string]string{
   453  				"cFlags": moduleCflags,
   454  				"ccCmd":  ccCmd,
   455  			},
   456  		})
   457  
   458  		if tidy {
   459  			tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
   460  			tidyFiles = append(tidyFiles, tidyFile)
   461  
   462  			ctx.Build(pctx, android.BuildParams{
   463  				Rule:        clangTidy,
   464  				Description: "clang-tidy " + srcFile.Rel(),
   465  				Output:      tidyFile,
   466  				Input:       srcFile,
   467  				// We must depend on objFile, since clang-tidy doesn't
   468  				// support exporting dependencies.
   469  				Implicit: objFile,
   470  				Args: map[string]string{
   471  					"cFlags":    moduleToolingCflags,
   472  					"tidyFlags": flags.tidyFlags,
   473  				},
   474  			})
   475  		}
   476  
   477  		if dump {
   478  			sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump")
   479  			sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile)
   480  
   481  			ctx.Build(pctx, android.BuildParams{
   482  				Rule:        sAbiDump,
   483  				Description: "header-abi-dumper " + srcFile.Rel(),
   484  				Output:      sAbiDumpFile,
   485  				Input:       srcFile,
   486  				Implicit:    objFile,
   487  				Args: map[string]string{
   488  					"cFlags":     moduleToolingCflags,
   489  					"exportDirs": flags.sAbiFlags,
   490  				},
   491  			})
   492  		}
   493  
   494  	}
   495  
   496  	return Objects{
   497  		objFiles:      objFiles,
   498  		tidyFiles:     tidyFiles,
   499  		coverageFiles: coverageFiles,
   500  		sAbiDumpFiles: sAbiDumpFiles,
   501  	}
   502  }
   503  
   504  // Generate a rule for compiling multiple .o files to a static library (.a)
   505  func TransformObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths,
   506  	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
   507  
   508  	if ctx.Darwin() {
   509  		transformDarwinObjToStaticLib(ctx, objFiles, flags, outputFile, deps)
   510  		return
   511  	}
   512  
   513  	arCmd := "${config.ClangBin}/llvm-ar"
   514  	arFlags := "crsD"
   515  	if !ctx.Darwin() {
   516  		arFlags += " -format=gnu"
   517  	}
   518  	if flags.arGoldPlugin {
   519  		arFlags += " --plugin ${config.LLVMGoldPlugin}"
   520  	}
   521  	if flags.arFlags != "" {
   522  		arFlags += " " + flags.arFlags
   523  	}
   524  
   525  	ctx.Build(pctx, android.BuildParams{
   526  		Rule:        ar,
   527  		Description: "static link " + outputFile.Base(),
   528  		Output:      outputFile,
   529  		Inputs:      objFiles,
   530  		Implicits:   deps,
   531  		Args: map[string]string{
   532  			"arFlags": arFlags,
   533  			"arCmd":   arCmd,
   534  		},
   535  	})
   536  }
   537  
   538  // Generate a rule for compiling multiple .o files to a static library (.a) on
   539  // darwin.  The darwin ar tool doesn't support @file for list files, and has a
   540  // very small command line length limit, so we have to split the ar into multiple
   541  // steps, each appending to the previous one.
   542  func transformDarwinObjToStaticLib(ctx android.ModuleContext, objFiles android.Paths,
   543  	flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
   544  
   545  	arFlags := "cqs"
   546  
   547  	if len(objFiles) == 0 {
   548  		dummy := android.PathForModuleOut(ctx, "dummy"+objectExtension)
   549  		dummyAr := android.PathForModuleOut(ctx, "dummy"+staticLibraryExtension)
   550  
   551  		ctx.Build(pctx, android.BuildParams{
   552  			Rule:        emptyFile,
   553  			Description: "empty object file",
   554  			Output:      dummy,
   555  			Implicits:   deps,
   556  		})
   557  
   558  		ctx.Build(pctx, android.BuildParams{
   559  			Rule:        darwinAr,
   560  			Description: "empty static archive",
   561  			Output:      dummyAr,
   562  			Input:       dummy,
   563  			Args: map[string]string{
   564  				"arFlags": arFlags,
   565  			},
   566  		})
   567  
   568  		ctx.Build(pctx, android.BuildParams{
   569  			Rule:        darwinAppendAr,
   570  			Description: "static link " + outputFile.Base(),
   571  			Output:      outputFile,
   572  			Input:       dummy,
   573  			Args: map[string]string{
   574  				"arFlags": "d",
   575  				"inAr":    dummyAr.String(),
   576  			},
   577  		})
   578  
   579  		return
   580  	}
   581  
   582  	// ARG_MAX on darwin is 262144, use half that to be safe
   583  	objFilesLists, err := splitListForSize(objFiles, 131072)
   584  	if err != nil {
   585  		ctx.ModuleErrorf("%s", err.Error())
   586  	}
   587  
   588  	var in, out android.WritablePath
   589  	for i, l := range objFilesLists {
   590  		in = out
   591  		out = outputFile
   592  		if i != len(objFilesLists)-1 {
   593  			out = android.PathForModuleOut(ctx, outputFile.Base()+strconv.Itoa(i))
   594  		}
   595  
   596  		build := android.BuildParams{
   597  			Rule:        darwinAr,
   598  			Description: "static link " + out.Base(),
   599  			Output:      out,
   600  			Inputs:      l,
   601  			Implicits:   deps,
   602  			Args: map[string]string{
   603  				"arFlags": arFlags,
   604  			},
   605  		}
   606  		if i != 0 {
   607  			build.Rule = darwinAppendAr
   608  			build.Args["inAr"] = in.String()
   609  		}
   610  		ctx.Build(pctx, build)
   611  	}
   612  }
   613  
   614  // Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
   615  // and shared libraries, to a shared library (.so) or dynamic executable
   616  func TransformObjToDynamicBinary(ctx android.ModuleContext,
   617  	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
   618  	crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath) {
   619  
   620  	var ldCmd string
   621  	if flags.clang {
   622  		ldCmd = "${config.ClangBin}/clang++"
   623  	} else {
   624  		ldCmd = gccCmd(flags.toolchain, "g++")
   625  	}
   626  
   627  	var libFlagsList []string
   628  
   629  	if len(flags.libFlags) > 0 {
   630  		libFlagsList = append(libFlagsList, flags.libFlags)
   631  	}
   632  
   633  	if len(wholeStaticLibs) > 0 {
   634  		if ctx.Host() && ctx.Darwin() {
   635  			libFlagsList = append(libFlagsList, android.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
   636  		} else {
   637  			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
   638  			libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
   639  			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
   640  		}
   641  	}
   642  
   643  	if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 {
   644  		libFlagsList = append(libFlagsList, "-Wl,--start-group")
   645  	}
   646  	libFlagsList = append(libFlagsList, staticLibs.Strings()...)
   647  	if flags.groupStaticLibs && !ctx.Darwin() && len(staticLibs) > 0 {
   648  		libFlagsList = append(libFlagsList, "-Wl,--end-group")
   649  	}
   650  
   651  	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
   652  		libFlagsList = append(libFlagsList, "-Wl,--start-group")
   653  	}
   654  	libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
   655  	if groupLate && !ctx.Darwin() && len(lateStaticLibs) > 0 {
   656  		libFlagsList = append(libFlagsList, "-Wl,--end-group")
   657  	}
   658  
   659  	for _, lib := range sharedLibs {
   660  		libFlagsList = append(libFlagsList, lib.String())
   661  	}
   662  
   663  	deps = append(deps, staticLibs...)
   664  	deps = append(deps, lateStaticLibs...)
   665  	deps = append(deps, wholeStaticLibs...)
   666  	if crtBegin.Valid() {
   667  		deps = append(deps, crtBegin.Path(), crtEnd.Path())
   668  	}
   669  
   670  	ctx.Build(pctx, android.BuildParams{
   671  		Rule:        ld,
   672  		Description: "link " + outputFile.Base(),
   673  		Output:      outputFile,
   674  		Inputs:      objFiles,
   675  		Implicits:   deps,
   676  		Args: map[string]string{
   677  			"ldCmd":    ldCmd,
   678  			"crtBegin": crtBegin.String(),
   679  			"libFlags": strings.Join(libFlagsList, " "),
   680  			"ldFlags":  flags.ldFlags,
   681  			"crtEnd":   crtEnd.String(),
   682  		},
   683  	})
   684  }
   685  
   686  // Generate a rule to combine .dump sAbi dump files from multiple source files
   687  // into a single .ldump sAbi dump file
   688  func TransformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
   689  	baseName, exportedHeaderFlags string) android.OptionalPath {
   690  	outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
   691  	sabiLock.Lock()
   692  	lsdumpPaths = append(lsdumpPaths, outputFile.String())
   693  	sabiLock.Unlock()
   694  	symbolFilterStr := "-so " + soFile.String()
   695  	ctx.Build(pctx, android.BuildParams{
   696  		Rule:        sAbiLink,
   697  		Description: "header-abi-linker " + outputFile.Base(),
   698  		Output:      outputFile,
   699  		Inputs:      sAbiDumps,
   700  		Implicit:    soFile,
   701  		Args: map[string]string{
   702  			"symbolFilter":        symbolFilterStr,
   703  			"arch":                ctx.Arch().ArchType.Name,
   704  			"exportedHeaderFlags": exportedHeaderFlags,
   705  		},
   706  	})
   707  	return android.OptionalPathForPath(outputFile)
   708  }
   709  
   710  func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
   711  	outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump")
   712  	ctx.Build(pctx, android.BuildParams{
   713  		Rule:        unzipRefSAbiDump,
   714  		Description: "gunzip" + outputFile.Base(),
   715  		Output:      outputFile,
   716  		Input:       zippedRefDump,
   717  	})
   718  	return outputFile
   719  }
   720  
   721  func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
   722  	baseName, exportedHeaderFlags string, isVndkExt bool) android.OptionalPath {
   723  
   724  	outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
   725  
   726  	localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
   727  	if exportedHeaderFlags == "" {
   728  		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
   729  	}
   730  	if isVndkExt {
   731  		localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
   732  	}
   733  
   734  	ctx.Build(pctx, android.BuildParams{
   735  		Rule:        sAbiDiff,
   736  		Description: "header-abi-diff " + outputFile.Base(),
   737  		Output:      outputFile,
   738  		Input:       inputDump,
   739  		Implicit:    referenceDump,
   740  		Args: map[string]string{
   741  			"referenceDump": referenceDump.String(),
   742  			"libName":       baseName[0:(len(baseName) - len(filepath.Ext(baseName)))],
   743  			"arch":          ctx.Arch().ArchType.Name,
   744  			"allowFlags":    strings.Join(localAbiCheckAllowFlags, " "),
   745  		},
   746  	})
   747  	return android.OptionalPathForPath(outputFile)
   748  }
   749  
   750  // Generate a rule for extracting a table of contents from a shared library (.so)
   751  func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
   752  	outputFile android.WritablePath, flags builderFlags) {
   753  
   754  	crossCompile := gccCmd(flags.toolchain, "")
   755  
   756  	ctx.Build(pctx, android.BuildParams{
   757  		Rule:        toc,
   758  		Description: "generate toc " + inputFile.Base(),
   759  		Output:      outputFile,
   760  		Input:       inputFile,
   761  		Args: map[string]string{
   762  			"crossCompile": crossCompile,
   763  		},
   764  	})
   765  }
   766  
   767  // Generate a rule for compiling multiple .o files to a .o using ld partial linking
   768  func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
   769  	flags builderFlags, outputFile android.WritablePath) {
   770  
   771  	var ldCmd string
   772  	if flags.clang {
   773  		ldCmd = "${config.ClangBin}/clang++"
   774  	} else {
   775  		ldCmd = gccCmd(flags.toolchain, "g++")
   776  	}
   777  
   778  	ctx.Build(pctx, android.BuildParams{
   779  		Rule:        partialLd,
   780  		Description: "link " + outputFile.Base(),
   781  		Output:      outputFile,
   782  		Inputs:      objFiles,
   783  		Args: map[string]string{
   784  			"ldCmd":   ldCmd,
   785  			"ldFlags": flags.ldFlags,
   786  		},
   787  	})
   788  }
   789  
   790  // Generate a rule for runing objcopy --prefix-symbols on a binary
   791  func TransformBinaryPrefixSymbols(ctx android.ModuleContext, prefix string, inputFile android.Path,
   792  	flags builderFlags, outputFile android.WritablePath) {
   793  
   794  	objcopyCmd := gccCmd(flags.toolchain, "objcopy")
   795  
   796  	ctx.Build(pctx, android.BuildParams{
   797  		Rule:        prefixSymbols,
   798  		Description: "prefix symbols " + outputFile.Base(),
   799  		Output:      outputFile,
   800  		Input:       inputFile,
   801  		Args: map[string]string{
   802  			"objcopyCmd": objcopyCmd,
   803  			"prefix":     prefix,
   804  		},
   805  	})
   806  }
   807  
   808  func TransformStrip(ctx android.ModuleContext, inputFile android.Path,
   809  	outputFile android.WritablePath, flags builderFlags) {
   810  
   811  	crossCompile := gccCmd(flags.toolchain, "")
   812  	args := ""
   813  	if flags.stripAddGnuDebuglink {
   814  		args += " --add-gnu-debuglink"
   815  	}
   816  	if flags.stripKeepMiniDebugInfo {
   817  		args += " --keep-mini-debug-info"
   818  	}
   819  	if flags.stripKeepSymbols {
   820  		args += " --keep-symbols"
   821  	}
   822  
   823  	ctx.Build(pctx, android.BuildParams{
   824  		Rule:        strip,
   825  		Description: "strip " + outputFile.Base(),
   826  		Output:      outputFile,
   827  		Input:       inputFile,
   828  		Args: map[string]string{
   829  			"crossCompile": crossCompile,
   830  			"args":         args,
   831  		},
   832  	})
   833  }
   834  
   835  func TransformDarwinStrip(ctx android.ModuleContext, inputFile android.Path,
   836  	outputFile android.WritablePath) {
   837  
   838  	ctx.Build(pctx, android.BuildParams{
   839  		Rule:        darwinStrip,
   840  		Description: "strip " + outputFile.Base(),
   841  		Output:      outputFile,
   842  		Input:       inputFile,
   843  	})
   844  }
   845  
   846  func TransformCoverageFilesToLib(ctx android.ModuleContext,
   847  	inputs Objects, flags builderFlags, baseName string) android.OptionalPath {
   848  
   849  	if len(inputs.coverageFiles) > 0 {
   850  		outputFile := android.PathForModuleOut(ctx, baseName+".gcnodir")
   851  
   852  		TransformObjToStaticLib(ctx, inputs.coverageFiles, flags, outputFile, nil)
   853  
   854  		return android.OptionalPathForPath(outputFile)
   855  	}
   856  
   857  	return android.OptionalPath{}
   858  }
   859  
   860  func CopyGccLib(ctx android.ModuleContext, libName string,
   861  	flags builderFlags, outputFile android.WritablePath) {
   862  
   863  	ctx.Build(pctx, android.BuildParams{
   864  		Rule:        copyGccLib,
   865  		Description: "copy gcc library " + libName,
   866  		Output:      outputFile,
   867  		Args: map[string]string{
   868  			"ccCmd":   gccCmd(flags.toolchain, "gcc"),
   869  			"cFlags":  flags.globalFlags,
   870  			"libName": libName,
   871  		},
   872  	})
   873  }
   874  
   875  func gccCmd(toolchain config.Toolchain, cmd string) string {
   876  	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
   877  }
   878  
   879  func splitListForSize(list android.Paths, limit int) (lists []android.Paths, err error) {
   880  	var i int
   881  
   882  	start := 0
   883  	bytes := 0
   884  	for i = range list {
   885  		l := len(list[i].String())
   886  		if l > limit {
   887  			return nil, fmt.Errorf("list element greater than size limit (%d)", limit)
   888  		}
   889  		if bytes+l > limit {
   890  			lists = append(lists, list[start:i])
   891  			start = i
   892  			bytes = 0
   893  		}
   894  		bytes += l + 1 // count a space between each list element
   895  	}
   896  
   897  	lists = append(lists, list[start:])
   898  
   899  	totalLen := 0
   900  	for _, l := range lists {
   901  		totalLen += len(l)
   902  	}
   903  	if totalLen != len(list) {
   904  		panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen))
   905  	}
   906  	return lists, nil
   907  }