Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
5.0 KiB
203 lines
5.0 KiB
// Copyright (c) 2018, Google Inc. |
|
// |
|
// Permission to use, copy, modify, and/or distribute this software for any |
|
// purpose with or without fee is hereby granted, provided that the above |
|
// copyright notice and this permission notice appear in all copies. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
|
|
// godeps prints out dependencies of a package in either CMake or Make depfile |
|
// format, for incremental rebuilds. |
|
// |
|
// The depfile format is preferred. It works correctly when new files are added. |
|
// However, CMake only supports depfiles for custom commands with Ninja and |
|
// starting CMake 3.7. For other configurations, we also support CMake's format, |
|
// but CMake must be rerun when file lists change. |
|
package main |
|
|
|
import ( |
|
"flag" |
|
"fmt" |
|
"go/build" |
|
"os" |
|
"path/filepath" |
|
"sort" |
|
"strings" |
|
) |
|
|
|
var ( |
|
format = flag.String("format", "cmake", "The format to output to, either 'cmake' or 'depfile'") |
|
mainPkg = flag.String("pkg", "", "The package to print dependencies for") |
|
target = flag.String("target", "", "The name of the output file") |
|
out = flag.String("out", "", "The path to write the output to. If unset, this is stdout") |
|
) |
|
|
|
func cMakeQuote(in string) string { |
|
// See https://cmake.org/cmake/help/v3.0/manual/cmake-language.7.html#quoted-argument |
|
var b strings.Builder |
|
b.Grow(len(in)) |
|
// Iterate over in as bytes. |
|
for i := 0; i < len(in); i++ { |
|
switch c := in[i]; c { |
|
case '\\', '"': |
|
b.WriteByte('\\') |
|
b.WriteByte(c) |
|
case '\t': |
|
b.WriteString("\\t") |
|
case '\r': |
|
b.WriteString("\\r") |
|
case '\n': |
|
b.WriteString("\\n") |
|
default: |
|
b.WriteByte(in[i]) |
|
} |
|
} |
|
return b.String() |
|
} |
|
|
|
func writeCMake(outFile *os.File, files []string) error { |
|
for i, file := range files { |
|
if i != 0 { |
|
if _, err := outFile.WriteString(";"); err != nil { |
|
return err |
|
} |
|
} |
|
if _, err := outFile.WriteString(cMakeQuote(file)); err != nil { |
|
return err |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
func makeQuote(in string) string { |
|
// See https://www.gnu.org/software/make/manual/make.html#Rule-Syntax |
|
var b strings.Builder |
|
b.Grow(len(in)) |
|
// Iterate over in as bytes. |
|
for i := 0; i < len(in); i++ { |
|
switch c := in[i]; c { |
|
case '$': |
|
b.WriteString("$$") |
|
case '#', '\\', ' ': |
|
b.WriteByte('\\') |
|
b.WriteByte(c) |
|
default: |
|
b.WriteByte(c) |
|
} |
|
} |
|
return b.String() |
|
} |
|
|
|
func writeDepfile(outFile *os.File, files []string) error { |
|
if _, err := fmt.Fprintf(outFile, "%s:", makeQuote(*target)); err != nil { |
|
return err |
|
} |
|
for _, file := range files { |
|
if _, err := fmt.Fprintf(outFile, " %s", makeQuote(file)); err != nil { |
|
return err |
|
} |
|
} |
|
_, err := outFile.WriteString("\n") |
|
return err |
|
} |
|
|
|
func appendPrefixed(list, newFiles []string, prefix string) []string { |
|
for _, file := range newFiles { |
|
list = append(list, filepath.Join(prefix, file)) |
|
} |
|
return list |
|
} |
|
|
|
func main() { |
|
flag.Parse() |
|
|
|
if len(*mainPkg) == 0 { |
|
fmt.Fprintf(os.Stderr, "-pkg argument is required.\n") |
|
os.Exit(1) |
|
} |
|
|
|
var isDepfile bool |
|
switch *format { |
|
case "depfile": |
|
isDepfile = true |
|
case "cmake": |
|
isDepfile = false |
|
default: |
|
fmt.Fprintf(os.Stderr, "Unknown format: %q\n", *format) |
|
os.Exit(1) |
|
} |
|
|
|
if isDepfile && len(*target) == 0 { |
|
fmt.Fprintf(os.Stderr, "-target argument is required for depfile.\n") |
|
os.Exit(1) |
|
} |
|
|
|
done := make(map[string]struct{}) |
|
var files []string |
|
var recurse func(pkgName string) error |
|
recurse = func(pkgName string) error { |
|
pkg, err := build.Default.Import(pkgName, ".", 0) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Skip standard packages. |
|
if pkg.Goroot { |
|
return nil |
|
} |
|
|
|
// Skip already-visited packages. |
|
if _, ok := done[pkg.Dir]; ok { |
|
return nil |
|
} |
|
done[pkg.Dir] = struct{}{} |
|
|
|
files = appendPrefixed(files, pkg.GoFiles, pkg.Dir) |
|
files = appendPrefixed(files, pkg.CgoFiles, pkg.Dir) |
|
// Include ignored Go files. A subsequent change may cause them |
|
// to no longer be ignored. |
|
files = appendPrefixed(files, pkg.IgnoredGoFiles, pkg.Dir) |
|
|
|
// Recurse into imports. |
|
for _, importName := range pkg.Imports { |
|
if err := recurse(importName); err != nil { |
|
return err |
|
} |
|
} |
|
return nil |
|
} |
|
if err := recurse(*mainPkg); err != nil { |
|
fmt.Fprintf(os.Stderr, "Error getting dependencies: %s\n", err) |
|
os.Exit(1) |
|
} |
|
|
|
sort.Strings(files) |
|
|
|
outFile := os.Stdout |
|
if len(*out) != 0 { |
|
var err error |
|
outFile, err = os.Create(*out) |
|
if err != nil { |
|
fmt.Fprintf(os.Stderr, "Error writing output: %s\n", err) |
|
os.Exit(1) |
|
} |
|
defer outFile.Close() |
|
} |
|
|
|
var err error |
|
if isDepfile { |
|
err = writeDepfile(outFile, files) |
|
} else { |
|
err = writeCMake(outFile, files) |
|
} |
|
if err != nil { |
|
fmt.Fprintf(os.Stderr, "Error writing output: %s\n", err) |
|
os.Exit(1) |
|
} |
|
}
|
|
|