2015-01-31 02:27:36 +01:00
|
|
|
// Copyright 2015 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package cc
|
|
|
|
|
|
|
|
// This file generates the final rules for compiling all C/C++. All properties related to
|
|
|
|
// compiling should have been translated into builderFlags or another argument to the Transform*
|
|
|
|
// functions.
|
|
|
|
|
|
|
|
import (
|
|
|
|
"android/soong/common"
|
|
|
|
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2015-03-26 22:43:45 +01:00
|
|
|
|
|
|
|
"github.com/google/blueprint"
|
|
|
|
"github.com/google/blueprint/pathtools"
|
2015-01-31 02:27:36 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
sharedLibraryExtension = ".so"
|
|
|
|
staticLibraryExtension = ".a"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
pctx = blueprint.NewPackageContext("android/soong/cc")
|
|
|
|
|
|
|
|
cc = pctx.StaticRule("cc",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Depfile: "${out}.d",
|
|
|
|
Deps: blueprint.DepsGCC,
|
|
|
|
Command: "$ccCmd $incFlags -c $cFlags -MD -MF ${out}.d -o $out $in",
|
|
|
|
Description: "cc $out",
|
|
|
|
},
|
|
|
|
"ccCmd", "incFlags", "cFlags")
|
|
|
|
|
|
|
|
ld = pctx.StaticRule("ld",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "$ldCmd ${ldDirFlags} ${crtBegin} ${in} " +
|
|
|
|
"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${ldLibs}",
|
|
|
|
Description: "ld $out",
|
|
|
|
},
|
|
|
|
"ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags", "ldLibs")
|
|
|
|
|
|
|
|
partialLd = pctx.StaticRule("partialLd",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "$ldCmd -r ${in} -o ${out}",
|
|
|
|
Description: "partialLd $out",
|
|
|
|
},
|
|
|
|
"ldCmd")
|
|
|
|
|
|
|
|
ar = pctx.StaticRule("ar",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Command: "rm -f ${out} && $arCmd $arFlags $out $in",
|
|
|
|
Description: "ar $out",
|
|
|
|
},
|
|
|
|
"arCmd", "arFlags")
|
|
|
|
|
|
|
|
copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
|
|
|
|
|
|
|
|
copyGccLib = pctx.StaticRule("copyGccLib",
|
|
|
|
blueprint.RuleParams{
|
|
|
|
Depfile: "${out}.d",
|
|
|
|
Deps: blueprint.DepsGCC,
|
|
|
|
Command: "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
|
|
|
|
Description: "copy gcc $out",
|
|
|
|
},
|
|
|
|
"ccCmd", "cFlags", "libName")
|
|
|
|
)
|
|
|
|
|
|
|
|
type builderFlags struct {
|
|
|
|
globalFlags string
|
|
|
|
asFlags string
|
|
|
|
cFlags string
|
|
|
|
conlyFlags string
|
|
|
|
cppFlags string
|
|
|
|
ldFlags string
|
|
|
|
ldLibs string
|
|
|
|
incFlags string
|
|
|
|
nocrt bool
|
2015-03-24 01:50:24 +01:00
|
|
|
toolchain Toolchain
|
2015-01-31 02:27:36 +01:00
|
|
|
clang bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
|
|
|
|
func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
|
|
|
|
flags builderFlags) (objFiles []string) {
|
|
|
|
|
|
|
|
objFiles = make([]string, len(srcFiles))
|
|
|
|
objDir := common.ModuleObjDir(ctx)
|
|
|
|
if subdir != "" {
|
|
|
|
objDir = filepath.Join(objDir, subdir)
|
|
|
|
}
|
|
|
|
|
|
|
|
cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
|
|
|
|
cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
|
|
|
|
asflags := flags.globalFlags + " " + flags.asFlags
|
|
|
|
|
|
|
|
for i, srcFile := range srcFiles {
|
|
|
|
objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx))
|
|
|
|
objFile = filepath.Join(objDir, objFile)
|
|
|
|
objFile = pathtools.ReplaceExtension(objFile, "o")
|
|
|
|
|
|
|
|
objFiles[i] = objFile
|
|
|
|
|
|
|
|
var moduleCflags string
|
|
|
|
var ccCmd string
|
|
|
|
|
|
|
|
switch filepath.Ext(srcFile) {
|
|
|
|
case ".S", ".s":
|
|
|
|
ccCmd = "gcc"
|
|
|
|
moduleCflags = asflags
|
|
|
|
case ".c":
|
|
|
|
ccCmd = "gcc"
|
|
|
|
moduleCflags = cflags
|
|
|
|
case ".cpp", ".cc":
|
|
|
|
ccCmd = "g++"
|
|
|
|
moduleCflags = cppflags
|
|
|
|
default:
|
|
|
|
ctx.ModuleErrorf("File %s has unknown extension", srcFile)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if flags.clang {
|
|
|
|
switch ccCmd {
|
|
|
|
case "gcc":
|
|
|
|
ccCmd = "clang"
|
|
|
|
case "g++":
|
|
|
|
ccCmd = "clang++"
|
|
|
|
default:
|
|
|
|
panic("unrecoginzied ccCmd")
|
|
|
|
}
|
|
|
|
|
|
|
|
ccCmd = "${clangPath}" + ccCmd
|
|
|
|
} else {
|
|
|
|
ccCmd = gccCmd(flags.toolchain, ccCmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: cc,
|
|
|
|
Outputs: []string{objFile},
|
|
|
|
Inputs: []string{srcFile},
|
|
|
|
Implicits: []string{ccCmd},
|
|
|
|
Args: map[string]string{
|
|
|
|
"cFlags": moduleCflags,
|
|
|
|
"incFlags": flags.incFlags,
|
|
|
|
"ccCmd": ccCmd,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return objFiles
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate a rule for compiling multiple .o files to a static library (.a)
|
|
|
|
func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
|
|
|
|
flags builderFlags, outputFile string) {
|
|
|
|
|
|
|
|
arCmd := gccCmd(flags.toolchain, "ar")
|
|
|
|
arFlags := "crsPD"
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: ar,
|
|
|
|
Outputs: []string{outputFile},
|
|
|
|
Inputs: objFiles,
|
|
|
|
Implicits: []string{arCmd},
|
|
|
|
Args: map[string]string{
|
|
|
|
"arFlags": arFlags,
|
|
|
|
"arCmd": arCmd,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
|
|
|
|
// and shared libraires, to a shared library (.so) or dynamic executable
|
|
|
|
func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
|
2015-03-17 00:15:49 +01:00
|
|
|
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs []string,
|
2015-03-26 22:43:45 +01:00
|
|
|
crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
var ldCmd string
|
|
|
|
if flags.clang {
|
|
|
|
ldCmd = "${clangPath}clang++"
|
|
|
|
} else {
|
|
|
|
ldCmd = gccCmd(flags.toolchain, "g++")
|
|
|
|
}
|
|
|
|
|
|
|
|
var ldDirs []string
|
|
|
|
var libFlagsList []string
|
|
|
|
|
|
|
|
if len(wholeStaticLibs) > 0 {
|
|
|
|
libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
|
|
|
|
libFlagsList = append(libFlagsList, wholeStaticLibs...)
|
|
|
|
libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
|
|
|
|
}
|
|
|
|
|
|
|
|
libFlagsList = append(libFlagsList, staticLibs...)
|
|
|
|
|
|
|
|
for _, lib := range sharedLibs {
|
|
|
|
dir, file := filepath.Split(lib)
|
|
|
|
if !strings.HasPrefix(file, "lib") {
|
|
|
|
panic("shared library " + lib + " does not start with lib")
|
|
|
|
}
|
|
|
|
if !strings.HasSuffix(file, sharedLibraryExtension) {
|
|
|
|
panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
|
|
|
|
}
|
|
|
|
libFlagsList = append(libFlagsList,
|
|
|
|
"-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
|
|
|
|
ldDirs = append(ldDirs, dir)
|
|
|
|
}
|
|
|
|
|
2015-03-26 22:43:45 +01:00
|
|
|
if groupLate {
|
|
|
|
libFlagsList = append(libFlagsList, "-Wl,--start-group")
|
|
|
|
}
|
2015-03-17 00:15:49 +01:00
|
|
|
libFlagsList = append(libFlagsList, lateStaticLibs...)
|
2015-03-26 22:43:45 +01:00
|
|
|
if groupLate {
|
|
|
|
libFlagsList = append(libFlagsList, "-Wl,--end-group")
|
|
|
|
}
|
2015-03-17 00:15:49 +01:00
|
|
|
|
2015-01-31 02:27:36 +01:00
|
|
|
deps := []string{ldCmd}
|
|
|
|
deps = append(deps, sharedLibs...)
|
|
|
|
deps = append(deps, staticLibs...)
|
2015-03-17 18:47:08 +01:00
|
|
|
deps = append(deps, lateStaticLibs...)
|
2015-01-31 02:27:36 +01:00
|
|
|
deps = append(deps, wholeStaticLibs...)
|
|
|
|
if crtBegin != "" {
|
|
|
|
deps = append(deps, crtBegin, crtEnd)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: ld,
|
|
|
|
Outputs: []string{outputFile},
|
|
|
|
Inputs: objFiles,
|
|
|
|
Implicits: deps,
|
|
|
|
Args: map[string]string{
|
|
|
|
"ldCmd": ldCmd,
|
|
|
|
"ldDirFlags": ldDirsToFlags(ldDirs),
|
|
|
|
"crtBegin": crtBegin,
|
|
|
|
"libFlags": strings.Join(libFlagsList, " "),
|
|
|
|
"ldFlags": flags.ldFlags,
|
|
|
|
"crtEnd": crtEnd,
|
|
|
|
"ldLibs": flags.ldLibs,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate a rule for compiling multiple .o files to a .o using ld partial linking
|
|
|
|
func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
|
|
|
|
flags builderFlags, outputFile string) {
|
|
|
|
|
|
|
|
ldCmd := gccCmd(flags.toolchain, "ld")
|
|
|
|
|
|
|
|
deps := []string{ldCmd}
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: partialLd,
|
|
|
|
Outputs: []string{outputFile},
|
|
|
|
Inputs: objFiles,
|
|
|
|
Implicits: deps,
|
|
|
|
Args: map[string]string{
|
|
|
|
"ldCmd": ldCmd,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func CopyGccLib(ctx common.AndroidModuleContext, libName string,
|
|
|
|
flags builderFlags, outputFile string) {
|
|
|
|
|
|
|
|
ctx.Build(pctx, blueprint.BuildParams{
|
|
|
|
Rule: copyGccLib,
|
|
|
|
Outputs: []string{outputFile},
|
|
|
|
Implicits: []string{
|
|
|
|
"$copyGccLibPath",
|
|
|
|
gccCmd(flags.toolchain, "gcc"),
|
|
|
|
},
|
|
|
|
Args: map[string]string{
|
|
|
|
"ccCmd": gccCmd(flags.toolchain, "gcc"),
|
|
|
|
"cFlags": flags.globalFlags,
|
|
|
|
"libName": libName,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-03-24 01:50:24 +01:00
|
|
|
func gccCmd(toolchain Toolchain, cmd string) string {
|
2015-01-31 02:27:36 +01:00
|
|
|
return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
|
|
|
|
}
|