Use Go modules with delocate.
This makes running go test, etc., in util/fipstools/delocate work! This
adds a go_executable command to CMake like:
go_executable(delocate boringssl.googlesource.com/boringssl/util/fipstools/delocate)
which internally gets dependencies and whatnot so it behaves like usual
Go.
Update-Note: delocate has been rearranged a bit.
Change-Id: I244a7317dd8d4f2ab77a0daa624ed3e0b385faef
Reviewed-on: https://boringssl-review.googlesource.com/31885
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c614a65..1586d34 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -334,6 +334,43 @@
add_definitions(-DOPENSSL_SMALL)
endif()
+function(go_executable dest package)
+ set(godeps "${CMAKE_SOURCE_DIR}/util/godeps.go")
+ if(${CMAKE_VERSION} VERSION_LESS "3.7" OR
+ NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
+ # The DEPFILE parameter to add_custom_command is new as of CMake 3.7 and
+ # only works with Ninja. Query the sources at configure time. Additionally,
+ # everything depends on go.mod. That affects what external packages to use.
+ execute_process(COMMAND ${GO_EXECUTABLE} run ${godeps} -format cmake
+ -pkg ${package}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ OUTPUT_VARIABLE sources
+ RESULT_VARIABLE godeps_result)
+ add_custom_command(OUTPUT ${dest}
+ COMMAND ${GO_EXECUTABLE} build
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ DEPENDS ${sources} ${CMAKE_SOURCE_DIR}/go.mod)
+ else()
+ # Ninja expects the target in the depfile to match the output. This is a
+ # relative path from the build directory.
+ string(LENGTH "${CMAKE_BINARY_DIR}" root_dir_length)
+ math(EXPR root_dir_length "${root_dir_length} + 1")
+ string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}" ${root_dir_length} -1 target)
+ set(target "${target}/${dest}")
+
+ set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d")
+ add_custom_command(OUTPUT ${dest}
+ COMMAND ${GO_EXECUTABLE} build
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package}
+ COMMAND ${GO_EXECUTABLE} run ${godeps} -format depfile
+ -target ${target} -pkg ${package} -out ${depfile}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ DEPENDS ${godeps} ${CMAKE_SOURCE_DIR}/go.mod
+ DEPFILE ${depfile})
+ endif()
+endfunction()
+
# CMake's iOS support uses Apple's multiple-architecture toolchain. It takes an
# architecture list from CMAKE_OSX_ARCHITECTURES, leaves CMAKE_SYSTEM_PROCESSOR
# alone, and expects all architecture-specific logic to be conditioned within
diff --git a/crypto/fipsmodule/CMakeLists.txt b/crypto/fipsmodule/CMakeLists.txt
index 1242aa2..9868dd8 100644
--- a/crypto/fipsmodule/CMakeLists.txt
+++ b/crypto/fipsmodule/CMakeLists.txt
@@ -141,21 +141,12 @@
set_target_properties(bcm_c_generated_asm PROPERTIES COMPILE_OPTIONS "-S")
set_target_properties(bcm_c_generated_asm PROPERTIES POSITION_INDEPENDENT_CODE ON)
- function(prepend_path values prefix output)
- set(result)
- foreach(value ${values})
- list(APPEND result "${prefix}/${value}")
- endforeach(value)
- set(${output} ${result} PARENT_SCOPE)
- endfunction()
-
- prepend_path("${BCM_ASM_SOURCES}" "${CMAKE_CURRENT_BINARY_DIR}" DELOCATE_ASM_ARGS)
-
+ go_executable(delocate boringssl.googlesource.com/boringssl/util/fipstools/delocate)
add_custom_command(
OUTPUT bcm-delocated.S
- COMMAND ${GO_EXECUTABLE} run util/fipstools/delocate.go util/fipstools/delocate.peg.go util/fipstools/ar.go util/fipstools/const.go -a $<TARGET_FILE:bcm_c_generated_asm> -o ${CMAKE_CURRENT_BINARY_DIR}/bcm-delocated.S ${DELOCATE_ASM_ARGS}
- DEPENDS bcm_c_generated_asm ${BCM_ASM_SOURCES} ${CMAKE_SOURCE_DIR}/util/fipstools/delocate.go ${CMAKE_SOURCE_DIR}/util/fipstools/delocate.peg.go ${CMAKE_SOURCE_DIR}/util/fipstools/ar.go ${CMAKE_SOURCE_DIR}/util/fipstools/const.go
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND ./delocate -a $<TARGET_FILE:bcm_c_generated_asm> -o bcm-delocated.S ${BCM_ASM_SOURCES}
+ DEPENDS bcm_c_generated_asm delocate ${BCM_ASM_SOURCES}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_library(
@@ -171,11 +162,13 @@
set_target_properties(bcm_hashunset PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(bcm_hashunset PROPERTIES LINKER_LANGUAGE C)
+ go_executable(inject-hash
+ boringssl.googlesource.com/boringssl/util/fipstools/inject-hash)
add_custom_command(
OUTPUT bcm.o
- COMMAND ${GO_EXECUTABLE} run util/fipstools/inject-hash.go util/fipstools/ar.go util/fipstools/const.go -o ${CMAKE_CURRENT_BINARY_DIR}/bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
- DEPENDS bcm_hashunset ${CMAKE_SOURCE_DIR}/util/fipstools/inject-hash.go ${CMAKE_SOURCE_DIR}/util/fipstools/ar.go ${CMAKE_SOURCE_DIR}/util/fipstools/const.go
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND ./inject-hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
+ DEPENDS bcm_hashunset inject-hash
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
# The outputs of add_custom_command cannot be referenced outside of the
diff --git a/util/fipstools/delocate.go b/util/fipstools/delocate/delocate.go
similarity index 99%
rename from util/fipstools/delocate.go
rename to util/fipstools/delocate/delocate.go
index d58e5be..a8c4fd0 100644
--- a/util/fipstools/delocate.go
+++ b/util/fipstools/delocate/delocate.go
@@ -25,6 +25,8 @@
"sort"
"strconv"
"strings"
+
+ "boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
)
// inputFile represents a textual assembly file.
@@ -1405,7 +1407,7 @@
w.WriteString(".type BORINGSSL_bcm_text_hash, @object\n")
w.WriteString(".size BORINGSSL_bcm_text_hash, 64\n")
w.WriteString("BORINGSSL_bcm_text_hash:\n")
- for _, b := range uninitHashValue {
+ for _, b := range fipscommon.UninitHashValue {
w.WriteString(".byte 0x" + strconv.FormatUint(uint64(b), 16) + "\n")
}
@@ -1423,7 +1425,7 @@
}
defer arFile.Close()
- ar, err := ParseAR(arFile)
+ ar, err := fipscommon.ParseAR(arFile)
if err != nil {
return err
}
diff --git a/util/fipstools/delocate.peg b/util/fipstools/delocate/delocate.peg
similarity index 100%
rename from util/fipstools/delocate.peg
rename to util/fipstools/delocate/delocate.peg
diff --git a/util/fipstools/delocate.peg.go b/util/fipstools/delocate/delocate.peg.go
similarity index 100%
rename from util/fipstools/delocate.peg.go
rename to util/fipstools/delocate/delocate.peg.go
diff --git a/util/fipstools/delocate_test.go b/util/fipstools/delocate/delocate_test.go
similarity index 100%
rename from util/fipstools/delocate_test.go
rename to util/fipstools/delocate/delocate_test.go
diff --git a/util/fipstools/testdata/ppc64le-GlobalEntry/in.s b/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-GlobalEntry/in.s
rename to util/fipstools/delocate/testdata/ppc64le-GlobalEntry/in.s
diff --git a/util/fipstools/testdata/ppc64le-GlobalEntry/out.s b/util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-GlobalEntry/out.s
rename to util/fipstools/delocate/testdata/ppc64le-GlobalEntry/out.s
diff --git a/util/fipstools/testdata/ppc64le-LoadToR0/in.s b/util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-LoadToR0/in.s
rename to util/fipstools/delocate/testdata/ppc64le-LoadToR0/in.s
diff --git a/util/fipstools/testdata/ppc64le-LoadToR0/out.s b/util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-LoadToR0/out.s
rename to util/fipstools/delocate/testdata/ppc64le-LoadToR0/out.s
diff --git a/util/fipstools/testdata/ppc64le-Sample/in.s b/util/fipstools/delocate/testdata/ppc64le-Sample/in.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-Sample/in.s
rename to util/fipstools/delocate/testdata/ppc64le-Sample/in.s
diff --git a/util/fipstools/testdata/ppc64le-Sample/out.s b/util/fipstools/delocate/testdata/ppc64le-Sample/out.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-Sample/out.s
rename to util/fipstools/delocate/testdata/ppc64le-Sample/out.s
diff --git a/util/fipstools/testdata/ppc64le-Sample2/in.s b/util/fipstools/delocate/testdata/ppc64le-Sample2/in.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-Sample2/in.s
rename to util/fipstools/delocate/testdata/ppc64le-Sample2/in.s
diff --git a/util/fipstools/testdata/ppc64le-Sample2/out.s b/util/fipstools/delocate/testdata/ppc64le-Sample2/out.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-Sample2/out.s
rename to util/fipstools/delocate/testdata/ppc64le-Sample2/out.s
diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/in.s b/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-TOCWithOffset/in.s
rename to util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/in.s
diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s b/util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s
similarity index 100%
rename from util/fipstools/testdata/ppc64le-TOCWithOffset/out.s
rename to util/fipstools/delocate/testdata/ppc64le-TOCWithOffset/out.s
diff --git a/util/fipstools/testdata/x86_64-BSS/in.s b/util/fipstools/delocate/testdata/x86_64-BSS/in.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-BSS/in.s
rename to util/fipstools/delocate/testdata/x86_64-BSS/in.s
diff --git a/util/fipstools/testdata/x86_64-BSS/out.s b/util/fipstools/delocate/testdata/x86_64-BSS/out.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-BSS/out.s
rename to util/fipstools/delocate/testdata/x86_64-BSS/out.s
diff --git a/util/fipstools/testdata/x86_64-Basic/in.s b/util/fipstools/delocate/testdata/x86_64-Basic/in.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-Basic/in.s
rename to util/fipstools/delocate/testdata/x86_64-Basic/in.s
diff --git a/util/fipstools/testdata/x86_64-Basic/out.s b/util/fipstools/delocate/testdata/x86_64-Basic/out.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-Basic/out.s
rename to util/fipstools/delocate/testdata/x86_64-Basic/out.s
diff --git a/util/fipstools/testdata/x86_64-GOTRewrite/in.s b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-GOTRewrite/in.s
rename to util/fipstools/delocate/testdata/x86_64-GOTRewrite/in.s
diff --git a/util/fipstools/testdata/x86_64-GOTRewrite/out.s b/util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-GOTRewrite/out.s
rename to util/fipstools/delocate/testdata/x86_64-GOTRewrite/out.s
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/in1.s b/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-LabelRewrite/in1.s
rename to util/fipstools/delocate/testdata/x86_64-LabelRewrite/in1.s
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/in2.s b/util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-LabelRewrite/in2.s
rename to util/fipstools/delocate/testdata/x86_64-LabelRewrite/in2.s
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/out.s b/util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-LabelRewrite/out.s
rename to util/fipstools/delocate/testdata/x86_64-LabelRewrite/out.s
diff --git a/util/fipstools/testdata/x86_64-Sections/in.s b/util/fipstools/delocate/testdata/x86_64-Sections/in.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-Sections/in.s
rename to util/fipstools/delocate/testdata/x86_64-Sections/in.s
diff --git a/util/fipstools/testdata/x86_64-Sections/out.s b/util/fipstools/delocate/testdata/x86_64-Sections/out.s
similarity index 100%
rename from util/fipstools/testdata/x86_64-Sections/out.s
rename to util/fipstools/delocate/testdata/x86_64-Sections/out.s
diff --git a/util/fipstools/ar.go b/util/fipstools/fipscommon/ar.go
similarity index 99%
rename from util/fipstools/ar.go
rename to util/fipstools/fipscommon/ar.go
index 51e7aa5..85b378d 100644
--- a/util/fipstools/ar.go
+++ b/util/fipstools/fipscommon/ar.go
@@ -14,7 +14,7 @@
// ar.go contains functions for parsing .a archive files.
-package main
+package fipscommon
import (
"bytes"
diff --git a/util/fipstools/const.go b/util/fipstools/fipscommon/const.go
similarity index 91%
rename from util/fipstools/const.go
rename to util/fipstools/fipscommon/const.go
index 2e009ac..5693414 100644
--- a/util/fipstools/const.go
+++ b/util/fipstools/fipscommon/const.go
@@ -12,11 +12,11 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-package main
+package fipscommon
-// uninitHashValue is the default hash value that we inject into the module.
+// UninitHashValue is the default hash value that we inject into the module.
// This value need only be distinct, i.e. so that we can safely
// search-and-replace it in an object file.
-var uninitHashValue = [64]byte{
+var UninitHashValue = [64]byte{
0xae, 0x2c, 0xea, 0x2a, 0xbd, 0xa6, 0xf3, 0xec, 0x97, 0x7f, 0x9b, 0xf6, 0x94, 0x9a, 0xfc, 0x83, 0x68, 0x27, 0xcb, 0xa0, 0xa0, 0x9f, 0x6b, 0x6f, 0xde, 0x52, 0xcd, 0xe2, 0xcd, 0xff, 0x31, 0x80, 0xa2, 0xd4, 0xc3, 0x66, 0x0f, 0xc2, 0x6a, 0x7b, 0xf4, 0xbe, 0x39, 0xa2, 0xd7, 0x25, 0xdb, 0x21, 0x98, 0xe9, 0xd5, 0x53, 0xbf, 0x5c, 0x32, 0x06, 0x83, 0x34, 0x0c, 0x65, 0x89, 0x52, 0xbd, 0x1f,
}
diff --git a/util/fipstools/inject-hash.go b/util/fipstools/inject-hash/inject-hash.go
similarity index 94%
rename from util/fipstools/inject-hash.go
rename to util/fipstools/inject-hash/inject-hash.go
index 688024d..14418a3 100644
--- a/util/fipstools/inject-hash.go
+++ b/util/fipstools/inject-hash/inject-hash.go
@@ -28,6 +28,8 @@
"io"
"io/ioutil"
"os"
+
+ "boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
)
func do(outPath, oInput string, arInput string) error {
@@ -43,7 +45,7 @@
}
defer arFile.Close()
- ar, err := ParseAR(arFile)
+ ar, err := fipscommon.ParseAR(arFile)
if err != nil {
return err
}
@@ -145,12 +147,12 @@
// Replace the default hash value in the object with the calculated
// value and write it out.
- offset := bytes.Index(objectBytes, uninitHashValue[:])
+ offset := bytes.Index(objectBytes, fipscommon.UninitHashValue[:])
if offset < 0 {
return errors.New("did not find uninitialised hash value in object file")
}
- if bytes.Index(objectBytes[offset+1:], uninitHashValue[:]) >= 0 {
+ if bytes.Index(objectBytes[offset+1:], fipscommon.UninitHashValue[:]) >= 0 {
return errors.New("found two occurrences of uninitialised hash value in object file")
}
diff --git a/util/godeps.go b/util/godeps.go
new file mode 100644
index 0000000..960faa4
--- /dev/null
+++ b/util/godeps.go
@@ -0,0 +1,203 @@
+// 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)
+ }
+}