Chromium Code Reviews| Index: mojom/mojom_parser/generators/deps/deps_generator.go |
| diff --git a/mojom/mojom_parser/generators/deps/deps_generator.go b/mojom/mojom_parser/generators/deps/deps_generator.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ee13a3e00fb69218a7b526fa97ce56ea58b2936d |
| --- /dev/null |
| +++ b/mojom/mojom_parser/generators/deps/deps_generator.go |
| @@ -0,0 +1,107 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package main |
| + |
| +// deps_generator.go implements the main function of the deps generator. |
| +// The deps generator generates .d files. The syntax is that which is used to |
| +// specify dependencies in makefiles. |
|
rudominer
2016/02/27 01:28:10
Can you give a link to something that defines a .d
azani
2016/02/29 21:28:32
Sorry, not really. The format seems to be indirect
|
| + |
| +import ( |
| + "log" |
| + "os" |
| + "path" |
| + "path/filepath" |
| + |
| + "mojom/mojom_parser/generators/common" |
| +) |
| + |
| +func main() { |
| + config := common.GetCliConfig(os.Args) |
| + common.GenerateOutput(WriteDepsFile, GetOutputFile, config) |
| +} |
| + |
| +// WriteDepsFile writes a .d file for the specified file to the specified writer. |
| +func WriteDepsFile(fileName string, config common.GeneratorConfig, writer common.Writer) { |
| + dFileName := fileName[:len(fileName)-len(filepath.Ext(fileName))] + ".d" |
| + writer.WriteString(path.Base(dFileName)) |
| + writer.WriteString(" : ") |
| + |
| + imports := GetTransitiveClosure(fileName, config) |
| + for _, imported := range imports { |
| + writer.WriteString(imported) |
| + writer.WriteString(" ") |
| + } |
| + writer.WriteString("\n") |
| +} |
| + |
| +// GetOutputFile returns a writer to which the generator output should be |
| +// written for that specified file. |
| +// In this case, the writer writes to a file whose relative path from |
| +// config.OutputDir() if equivalent to the relative path from config.SrcRootPath() |
| +// to fileName. |
| +// |
| +// e.g. If |
| +// fileName = /alpha/beta/gamma/file.mojom |
| +// SrcRootPath = /alpha/ |
| +// OutputDir = /some/output/path/ |
| +// |
| +// The writer writes to /some/output/path/beta/gamma/file.d |
| +// |
| +// TODO(azani): This is likely to be a common pattern to for the output path of |
| +// the generated code. Refactor into something re-usable before writing the next |
| +// generator. |
| +func GetOutputFile(fileName string, config common.GeneratorConfig) (file common.Writer) { |
|
rudominer
2016/02/27 01:28:10
Seems like this or something like it should go in
azani
2016/02/29 21:28:32
Done.
|
| + // Switch the file's extension to .d |
| + fileName = fileName[:len(fileName)-len(filepath.Ext(fileName))] + ".d" |
| + |
| + var err error |
| + relFileName, err := filepath.Rel(config.SrcRootPath(), fileName) |
| + if err != nil { |
| + log.Fatalln(err.Error()) |
| + } |
| + outPath := filepath.Join(config.OutputDir(), relFileName) |
| + |
| + // Create the directory that will contain the output. |
| + outDir := path.Dir(outPath) |
| + if err := os.MkdirAll(outDir, os.ModeDir|0770); err != nil && !os.IsExist(err) { |
| + log.Fatalln(err.Error()) |
| + } |
| + |
| + file, err = os.OpenFile(outPath, os.O_WRONLY, 0660) |
| + if err != nil { |
| + log.Fatalln(err.Error()) |
| + } |
| + |
| + return |
| +} |
| + |
| +// GetTransitiveClosure gets the list of transitive imports starting with |
| +// rootFile. rootFile itself is not included. |
| +// The imports are specified as paths relative to the directory in which |
| +// rootFile is found. |
| +func GetTransitiveClosure(rootFile string, config common.GeneratorConfig) (result []string) { |
|
rudominer
2016/02/27 01:28:10
Should this also be a common utility?
azani
2016/02/29 21:28:32
Looking at the other current generators, I don't t
|
| + fileGraph := config.FileGraph() |
| + toVisit := []string{rootFile} |
| + rootFileDir := path.Dir(rootFile) |
| + |
| + for len(toVisit) > 0 { |
| + curFileName := toVisit[len(toVisit)-1] |
| + toVisit = toVisit[1:len(toVisit)] |
| + |
| + curFile := fileGraph.Files[curFileName] |
| + rel, err := filepath.Rel(rootFileDir, curFileName) |
| + if err != nil { |
| + log.Fatalln(err.Error()) |
| + } |
| + result = append(result, rel) |
| + |
| + if curFile.Imports != nil { |
| + for _, importFileName := range *curFile.Imports { |
| + toVisit = append(toVisit, importFileName) |
| + } |
| + } |
| + } |
| + return |
| +} |