diff --git a/Blueprints b/Blueprints index 31b4fa86d..945d2f493 100644 --- a/Blueprints +++ b/Blueprints @@ -116,6 +116,7 @@ bootstrap_go_package { "cc/builder.go", "cc/cc.go", "cc/clang.go", + "cc/gen.go", "cc/toolchain.go", "cc/util.go", diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go index 3009d4649..028396aff 100644 --- a/androidmk/cmd/androidmk/android.go +++ b/androidmk/cmd/androidmk/android.go @@ -42,6 +42,7 @@ var listProperties = map[string]string{ "LOCAL_MODULE_TAGS": "tags", "LOCAL_LDLIBS": "host_ldlibs", "LOCAL_CLANG_CFLAGS": "clang_cflags", + "LOCAL_YACCFLAGS": "yaccflags", "LOCAL_JAVA_RESOURCE_DIRS": "resource_dirs", "LOCAL_JAVACFLAGS": "javacflags", diff --git a/build.ninja.in b/build.ninja.in index cdc72fcd8..81f6522d1 100644 --- a/build.ninja.in +++ b/build.ninja.in @@ -53,7 +53,7 @@ rule g.bootstrap.link # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:170:1 +# Defined: build/soong/Blueprints:171:1 build .bootstrap/androidmk/obj/androidmk.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/androidmk/cmd/androidmk/android.go $ @@ -79,7 +79,7 @@ default .bootstrap/bin/androidmk # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:183:1 +# Defined: build/soong/Blueprints:184:1 build .bootstrap/androidmk-parser/pkg/android/soong/androidmk/parser.a: $ g.bootstrap.gc $ @@ -316,6 +316,7 @@ build .bootstrap/soong-cc/pkg/android/soong/cc.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cc/builder.go $ ${g.bootstrap.srcDir}/build/soong/cc/cc.go $ ${g.bootstrap.srcDir}/build/soong/cc/clang.go $ + ${g.bootstrap.srcDir}/build/soong/cc/gen.go $ ${g.bootstrap.srcDir}/build/soong/cc/toolchain.go $ ${g.bootstrap.srcDir}/build/soong/cc/util.go $ ${g.bootstrap.srcDir}/build/soong/cc/arm_device.go $ @@ -405,7 +406,7 @@ default .bootstrap/soong-env/pkg/android/soong/env.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:129:1 +# Defined: build/soong/Blueprints:130:1 build .bootstrap/soong-genrule/pkg/android/soong/genrule.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/genrule/genrule.go | $ @@ -443,7 +444,7 @@ default .bootstrap/soong-glob/pkg/android/soong/glob.a # Variant: # Type: bootstrap_go_package # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule -# Defined: build/soong/Blueprints:150:1 +# Defined: build/soong/Blueprints:151:1 build .bootstrap/soong-java/pkg/android/soong/java.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/java/builder.go $ @@ -553,7 +554,7 @@ default .bootstrap/bin/soong_glob # Variant: # Type: bootstrap_go_binary # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule -# Defined: build/soong/Blueprints:143:1 +# Defined: build/soong/Blueprints:144:1 build .bootstrap/soong_jar/obj/soong_jar.a: g.bootstrap.gc $ ${g.bootstrap.srcDir}/build/soong/cmd/soong_jar/soong_jar.go | $ diff --git a/cc/builder.go b/cc/builder.go index cb2bf9ac0..8fc428cd2 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -99,6 +99,7 @@ type builderFlags struct { ldFlags string ldLibs string incFlags string + yaccFlags string nocrt bool toolchain Toolchain clang bool @@ -106,7 +107,10 @@ type builderFlags struct { // 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) { + flags builderFlags, deps []string) (objFiles []string) { + + srcRoot := ctx.Config().(Config).SrcDir() + intermediatesRoot := ctx.Config().(Config).IntermediatesDir() objFiles = make([]string, len(srcFiles)) objDir := common.ModuleObjDir(ctx) @@ -119,8 +123,18 @@ func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFil asflags := flags.globalFlags + " " + flags.asFlags for i, srcFile := range srcFiles { - objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx)) - objFile = filepath.Join(objDir, objFile) + var objFile string + if strings.HasPrefix(srcFile, srcRoot) { + objFile = strings.TrimPrefix(srcFile, srcRoot) + objFile = filepath.Join(objDir, objFile) + } else if strings.HasPrefix(srcFile, intermediatesRoot) { + objFile = strings.TrimPrefix(srcFile, intermediatesRoot) + objFile = filepath.Join(objDir, "gen", objFile) + } else { + ctx.ModuleErrorf("source file %q is not in source directory %q", srcFile, srcRoot) + continue + } + objFile = pathtools.ReplaceExtension(objFile, "o") objFiles[i] = objFile @@ -158,11 +172,13 @@ func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFil ccCmd = gccCmd(flags.toolchain, ccCmd) } + deps = append([]string{ccCmd}, deps...) + ctx.Build(pctx, blueprint.BuildParams{ Rule: cc, Outputs: []string{objFile}, Inputs: []string{srcFile}, - Implicits: []string{ccCmd}, + Implicits: deps, Args: map[string]string{ "cFlags": moduleCflags, "incFlags": flags.incFlags, diff --git a/cc/cc.go b/cc/cc.go index e9a183ef1..b0dd7920a 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -32,6 +32,7 @@ import ( type Config interface { SrcDir() string + IntermediatesDir() string PrebuiltOS() string } @@ -126,6 +127,9 @@ type ccProperties struct { // asflags: list of module-specific flags that will be used for .S compiles Asflags []string `android:"arch_variant"` + // yaccflags: list of module-specific flags that will be used for .y and .yy compiles + Yaccflags []string + // ldflags: list of module-specific flags that will be used for all link steps Ldflags []string `android:"arch_variant"` @@ -257,6 +261,7 @@ type CCFlags struct { CFlags []string ConlyFlags []string CppFlags []string + YaccFlags []string LdFlags []string LdLibs []string IncludeDirs []string @@ -311,12 +316,12 @@ func (c *ccBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) { flags.IncludeDirs = append(flags.IncludeDirs, deps.IncludeDirs...) - objFiles := c.compileObjs(ctx, flags, deps) + objFiles := c.compileObjs(ctx, flags) if ctx.Failed() { return } - generatedObjFiles := c.compileGeneratedObjs(ctx, flags, deps) + generatedObjFiles := c.compileGeneratedObjs(ctx, flags) if ctx.Failed() { return } @@ -388,6 +393,7 @@ func (c *ccBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha ConlyFlags: c.properties.Conlyflags, LdFlags: c.properties.Ldflags, AsFlags: c.properties.Asflags, + YaccFlags: c.properties.Yaccflags, Nocrt: c.properties.Nocrt, Toolchain: toolchain, Clang: c.properties.Clang, @@ -521,28 +527,29 @@ func (c *ccBase) Flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags { // Compile a list of source files into objects a specified subdirectory func (c *ccBase) customCompileObjs(ctx common.AndroidModuleContext, flags CCFlags, - deps CCDeps, subdir string, srcFiles []string) []string { + subdir string, srcFiles []string) []string { + + buildFlags := ccFlagsToBuilderFlags(flags) srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx)) srcFiles = common.ExpandGlobs(ctx, srcFiles) + srcFiles, deps := genSources(ctx, srcFiles, buildFlags) - return TransformSourceToObj(ctx, subdir, srcFiles, ccFlagsToBuilderFlags(flags)) + return TransformSourceToObj(ctx, subdir, srcFiles, buildFlags, deps) } // Compile files listed in c.properties.Srcs into objects -func (c *ccBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags, - deps CCDeps) []string { +func (c *ccBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags) []string { if c.properties.SkipCompileObjs { return nil } - return c.customCompileObjs(ctx, flags, deps, "", c.properties.Srcs) + return c.customCompileObjs(ctx, flags, "", c.properties.Srcs) } // Compile generated source files from dependencies -func (c *ccBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCFlags, - deps CCDeps) []string { +func (c *ccBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCFlags) []string { var srcs []string if c.properties.SkipCompileObjs { @@ -559,7 +566,7 @@ func (c *ccBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCF return nil } - return TransformSourceToObj(ctx, "", srcs, ccFlagsToBuilderFlags(flags)) + return TransformSourceToObj(ctx, "", srcs, ccFlagsToBuilderFlags(flags), nil) } func (c *ccBase) outputFile() string { @@ -1013,7 +1020,7 @@ func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext, staticFlags := flags staticFlags.CFlags = append(staticFlags.CFlags, c.LibraryProperties.Static.Cflags...) - objFilesStatic := c.customCompileObjs(ctx, staticFlags, deps, common.DeviceStaticLibrary, + objFilesStatic := c.customCompileObjs(ctx, staticFlags, common.DeviceStaticLibrary, c.LibraryProperties.Static.Srcs) objFiles = append(objFiles, objFilesStatic...) @@ -1036,7 +1043,7 @@ func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext, sharedFlags := flags sharedFlags.CFlags = append(sharedFlags.CFlags, c.LibraryProperties.Shared.Cflags...) - objFilesShared := c.customCompileObjs(ctx, sharedFlags, deps, common.DeviceSharedLibrary, + objFilesShared := c.customCompileObjs(ctx, sharedFlags, common.DeviceSharedLibrary, c.LibraryProperties.Shared.Srcs) objFiles = append(objFiles, objFilesShared...) diff --git a/cc/gen.go b/cc/gen.go new file mode 100644 index 000000000..bd91d647a --- /dev/null +++ b/cc/gen.go @@ -0,0 +1,109 @@ +// 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 ( + "path/filepath" + "strings" + + "github.com/google/blueprint" + "github.com/google/blueprint/pathtools" + + "android/soong/common" +) + +func init() { + pctx.StaticVariable("lexCmd", "${SrcDir}/prebuilts/misc/${HostPrebuiltTag}/flex/flex-2.5.39") + pctx.StaticVariable("yaccCmd", "${SrcDir}/prebuilts/misc/${HostPrebuiltTag}/bison/bison") + pctx.StaticVariable("yaccDataDir", "${SrcDir}/external/bison/data") +} + +var ( + yacc = pctx.StaticRule("yacc", + blueprint.RuleParams{ + Command: "BISON_PKGDATADIR=$yaccDataDir $yaccCmd -d $yaccFlags -o $cppFile $in && " + + "cp -f $hppFile $hFile", + Description: "yacc $out", + }, + "yaccFlags", "cppFile", "hppFile", "hFile") + + lex = pctx.StaticRule("lex", + blueprint.RuleParams{ + Command: "$lexCmd -o$out $in", + Description: "lex $out", + }) +) + +func genYacc(ctx common.AndroidModuleContext, yaccFile, yaccFlags string) (cppFile, headerFile string) { + cppFile = strings.TrimPrefix(yaccFile, common.ModuleSrcDir(ctx)) + cppFile = filepath.Join(common.ModuleGenDir(ctx), cppFile) + cppFile = pathtools.ReplaceExtension(cppFile, "cpp") + hppFile := pathtools.ReplaceExtension(cppFile, "hpp") + headerFile = pathtools.ReplaceExtension(cppFile, "h") + + ctx.Build(pctx, blueprint.BuildParams{ + Rule: yacc, + Outputs: []string{cppFile, headerFile}, + Inputs: []string{yaccFile}, + Implicits: []string{"$yaccCmd"}, + Args: map[string]string{ + "yaccFlags": yaccFlags, + "cppFile": cppFile, + "hppFile": hppFile, + "hFile": headerFile, + }, + }) + + return cppFile, headerFile +} + +func genLex(ctx common.AndroidModuleContext, lexFile string) (cppFile string) { + cppFile = strings.TrimPrefix(lexFile, common.ModuleSrcDir(ctx)) + cppFile = filepath.Join(common.ModuleGenDir(ctx), cppFile) + cppFile = pathtools.ReplaceExtension(cppFile, "cpp") + + ctx.Build(pctx, blueprint.BuildParams{ + Rule: lex, + Outputs: []string{cppFile}, + Inputs: []string{lexFile}, + Implicits: []string{"$lexCmd"}, + }) + + return cppFile +} + +func genSources(ctx common.AndroidModuleContext, srcFiles []string, + buildFlags builderFlags) ([]string, []string) { + + var deps []string + + for i, srcFile := range srcFiles { + switch filepath.Ext(srcFile) { + case ".y", ".yy": + cppFile, headerFile := genYacc(ctx, srcFile, buildFlags.yaccFlags) + srcFiles[i] = cppFile + deps = append(deps, headerFile) + case ".l", ".ll": + cppFile := genLex(ctx, srcFile) + srcFiles[i] = cppFile + } + } + + return srcFiles, deps +} diff --git a/cc/util.go b/cc/util.go index db14c748b..7440c256e 100644 --- a/cc/util.go +++ b/cc/util.go @@ -98,6 +98,7 @@ func ccFlagsToBuilderFlags(in CCFlags) builderFlags { cFlags: strings.Join(in.CFlags, " "), conlyFlags: strings.Join(in.ConlyFlags, " "), cppFlags: strings.Join(in.CppFlags, " "), + yaccFlags: strings.Join(in.YaccFlags, " "), ldFlags: strings.Join(in.LdFlags, " "), ldLibs: strings.Join(in.LdLibs, " "), incFlags: includeDirsToFlags(in.IncludeDirs), diff --git a/common/module.go b/common/module.go index c008d7de7..e61d31317 100644 --- a/common/module.go +++ b/common/module.go @@ -23,6 +23,7 @@ import ( type Config interface { CpPreserveSymlinksFlags() string SrcDir() string + IntermediatesDir() string Getenv(string) string EnvDeps() map[string]string DeviceOut() string diff --git a/common/paths.go b/common/paths.go index abe67bf52..b052feff2 100644 --- a/common/paths.go +++ b/common/paths.go @@ -22,7 +22,8 @@ import ( // ModuleOutDir returns the path to the module-specific output directory. func ModuleOutDir(ctx AndroidModuleContext) string { - return filepath.Join(".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) + config := ctx.Config().(Config) + return filepath.Join(config.IntermediatesDir(), ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) } // ModuleSrcDir returns the path of the directory that all source file paths are diff --git a/config/config.go b/config/config.go index c08707026..e324e42d7 100644 --- a/config/config.go +++ b/config/config.go @@ -123,6 +123,10 @@ func (c *Config) SrcDir() string { return c.srcDir } +func (c *Config) IntermediatesDir() string { + return ".intermediates" +} + // HostGoOS returns the OS of the system that the Go toolchain is being run on. func (c *Config) HostGoOS() string { return runtime.GOOS