Work around Windows command-line limits in embed_test_data.go.

Change-Id: I020f7c75d2ed160b16a62cb909d2113c318feb3c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41764
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 437870a..c266e12 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -573,10 +573,21 @@
 # themselves as dependencies next to the target definition.
 add_custom_target(all_tests)
 
+# On Windows, CRYPTO_TEST_DATA is too long to fit in command-line limits.
+# TODO(davidben): CMake 3.12 has a list(JOIN) command. Use that when we've
+# updated the minimum version.
+set(EMBED_TEST_DATA_ARGS "")
+foreach(arg ${CRYPTO_TEST_DATA})
+  set(EMBED_TEST_DATA_ARGS "${EMBED_TEST_DATA_ARGS}${arg}\n")
+endforeach()
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/embed_test_data_args.txt"
+     "${EMBED_TEST_DATA_ARGS}")
+
 add_custom_command(
   OUTPUT crypto_test_data.cc
-  COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go ${CRYPTO_TEST_DATA} >
-  ${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc
+  COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go -file-list
+          "${CMAKE_CURRENT_BINARY_DIR}/embed_test_data_args.txt" >
+          "${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc"
   DEPENDS util/embed_test_data.go ${CRYPTO_TEST_DATA}
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 
diff --git a/util/embed_test_data.go b/util/embed_test_data.go
index 5376fdd..a0efdc4 100644
--- a/util/embed_test_data.go
+++ b/util/embed_test_data.go
@@ -18,11 +18,15 @@
 
 import (
 	"bytes"
+	"flag"
 	"fmt"
 	"io/ioutil"
 	"os"
+	"strings"
 )
 
+var fileList = flag.String("file-list", "", "if not empty, the path to a file containing a newline-separated list of files, to work around Windows command-line limits")
+
 func quote(in []byte) string {
 	var buf bytes.Buffer
 	buf.WriteByte('"')
@@ -60,6 +64,20 @@
 }
 
 func main() {
+	flag.Parse()
+
+	var files []string
+	if len(*fileList) != 0 {
+		data, err := ioutil.ReadFile(*fileList)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Error reading %s: %s.\n", *fileList, err)
+			os.Exit(1)
+		}
+		files = strings.FieldsFunc(string(data), func(r rune) bool { return r == '\r' || r == '\n' })
+	}
+
+	files = append(files, flag.Args()...)
+
 	fmt.Printf(`/* Copyright (c) 2017, Google Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -77,7 +95,7 @@
 /* This file is generated by:
 `)
 	fmt.Printf(" *   go run util/embed_test_data.go")
-	for _, arg := range os.Args[1:] {
+	for _, arg := range files {
 		fmt.Printf(" \\\n *       %s", arg)
 	}
 	fmt.Printf(" */\n")
@@ -99,7 +117,7 @@
 	// literal, but this is less compact.
 	const chunkSize = 8192
 
-	for i, arg := range os.Args[1:] {
+	for i, arg := range files {
 		data, err := ioutil.ReadFile(arg)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "Error reading %s: %s.\n", arg, err)
@@ -133,7 +151,7 @@
 
 std::string GetTestData(const char *path) {
 `, chunkSize, chunkSize, chunkSize)
-	for i, arg := range os.Args[1:] {
+	for i, arg := range files {
 		fmt.Printf("  if (strcmp(path, %s) == 0) {\n", quote([]byte(arg)))
 		fmt.Printf("    return AssembleString(kData%d, kLen%d);\n", i, i)
 		fmt.Printf("  }\n")