main.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright 2015 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // soong_zip is a utility used during the build to create a zip archive by pulling the entries from
  15. // various sources:
  16. // * explicitly specified files
  17. // * files whose paths are read from a file
  18. // * directories traversed recursively
  19. // It can optionally change the recorded path of an entry.
  20. package main
  21. import (
  22. "flag"
  23. "fmt"
  24. "os"
  25. "runtime"
  26. "runtime/pprof"
  27. "runtime/trace"
  28. "strconv"
  29. "strings"
  30. "android/soong/response"
  31. "android/soong/zip"
  32. )
  33. type uniqueSet map[string]bool
  34. func (u *uniqueSet) String() string {
  35. return `""`
  36. }
  37. func (u *uniqueSet) Set(s string) error {
  38. if _, found := (*u)[s]; found {
  39. return fmt.Errorf("File %q was specified twice as a file to not deflate", s)
  40. } else {
  41. (*u)[s] = true
  42. }
  43. return nil
  44. }
  45. type file struct{}
  46. func (file) String() string { return `""` }
  47. func (file) Set(s string) error {
  48. fileArgsBuilder.File(s)
  49. return nil
  50. }
  51. type listFiles struct{}
  52. func (listFiles) String() string { return `""` }
  53. func (listFiles) Set(s string) error {
  54. fileArgsBuilder.List(s)
  55. return nil
  56. }
  57. type rspFiles struct{}
  58. func (rspFiles) String() string { return `""` }
  59. func (rspFiles) Set(s string) error {
  60. fileArgsBuilder.RspFile(s)
  61. return nil
  62. }
  63. type explicitFile struct{}
  64. func (explicitFile) String() string { return `""` }
  65. func (explicitFile) Set(s string) error {
  66. fileArgsBuilder.ExplicitPathInZip(s)
  67. return nil
  68. }
  69. type dir struct{}
  70. func (dir) String() string { return `""` }
  71. func (dir) Set(s string) error {
  72. fileArgsBuilder.Dir(s)
  73. return nil
  74. }
  75. type relativeRoot struct{}
  76. func (relativeRoot) String() string { return "" }
  77. func (relativeRoot) Set(s string) error {
  78. fileArgsBuilder.SourcePrefixToStrip(s)
  79. return nil
  80. }
  81. type junkPaths struct{}
  82. func (junkPaths) IsBoolFlag() bool { return true }
  83. func (junkPaths) String() string { return "" }
  84. func (junkPaths) Set(s string) error {
  85. v, err := strconv.ParseBool(s)
  86. fileArgsBuilder.JunkPaths(v)
  87. return err
  88. }
  89. type rootPrefix struct{}
  90. func (rootPrefix) String() string { return "" }
  91. func (rootPrefix) Set(s string) error {
  92. fileArgsBuilder.PathPrefixInZip(s)
  93. return nil
  94. }
  95. var (
  96. fileArgsBuilder = zip.NewFileArgsBuilder()
  97. nonDeflatedFiles = make(uniqueSet)
  98. )
  99. func main() {
  100. var expandedArgs []string
  101. for _, arg := range os.Args {
  102. if strings.HasPrefix(arg, "@") {
  103. f, err := os.Open(strings.TrimPrefix(arg, "@"))
  104. if err != nil {
  105. fmt.Fprintln(os.Stderr, err.Error())
  106. os.Exit(1)
  107. }
  108. respArgs, err := response.ReadRspFile(f)
  109. f.Close()
  110. if err != nil {
  111. fmt.Fprintln(os.Stderr, err.Error())
  112. os.Exit(1)
  113. }
  114. expandedArgs = append(expandedArgs, respArgs...)
  115. } else {
  116. expandedArgs = append(expandedArgs, arg)
  117. }
  118. }
  119. flags := flag.NewFlagSet("flags", flag.ExitOnError)
  120. flags.Usage = func() {
  121. fmt.Fprintf(os.Stderr, "usage: soong_zip -o zipfile [-m manifest] [-C dir] [-f|-l file] [-D dir]...\n")
  122. flags.PrintDefaults()
  123. os.Exit(2)
  124. }
  125. out := flags.String("o", "", "file to write zip file to")
  126. manifest := flags.String("m", "", "input jar manifest file name")
  127. directories := flags.Bool("d", false, "include directories in zip")
  128. compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
  129. emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
  130. writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
  131. ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist")
  132. symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them")
  133. srcJar := flags.Bool("srcjar", false, "move .java files to locations that match their package statement")
  134. parallelJobs := flags.Int("parallel", runtime.NumCPU(), "number of parallel threads to use")
  135. cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
  136. traceFile := flags.String("trace", "", "write trace to file")
  137. sha256Checksum := flags.Bool("sha256", false, "add a zip header to each file containing its SHA256 digest")
  138. flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
  139. flags.Var(&listFiles{}, "l", "file containing list of files to zip")
  140. flags.Var(&rspFiles{}, "r", "file containing list of files to zip with Ninja rsp file escaping")
  141. flags.Var(&dir{}, "D", "directory to include in zip")
  142. flags.Var(&file{}, "f", "file to include in zip")
  143. flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
  144. flags.Var(&relativeRoot{}, "C", "path to use as relative root of files in following -f, -l, or -D arguments")
  145. flags.Var(&junkPaths{}, "j", "junk paths, zip files without directory names")
  146. flags.Var(&explicitFile{}, "e", "filename to use in the zip file for the next -f argument")
  147. flags.Parse(expandedArgs[1:])
  148. if flags.NArg() > 0 {
  149. fmt.Fprintf(os.Stderr, "unexpected arguments %s\n", strings.Join(flags.Args(), " "))
  150. flags.Usage()
  151. }
  152. if *cpuProfile != "" {
  153. f, err := os.Create(*cpuProfile)
  154. if err != nil {
  155. fmt.Fprintln(os.Stderr, err.Error())
  156. os.Exit(1)
  157. }
  158. defer f.Close()
  159. pprof.StartCPUProfile(f)
  160. defer pprof.StopCPUProfile()
  161. }
  162. if *traceFile != "" {
  163. f, err := os.Create(*traceFile)
  164. if err != nil {
  165. fmt.Fprintln(os.Stderr, err.Error())
  166. os.Exit(1)
  167. }
  168. defer f.Close()
  169. err = trace.Start(f)
  170. if err != nil {
  171. fmt.Fprintln(os.Stderr, err.Error())
  172. os.Exit(1)
  173. }
  174. defer trace.Stop()
  175. }
  176. if fileArgsBuilder.Error() != nil {
  177. fmt.Fprintln(os.Stderr, fileArgsBuilder.Error())
  178. os.Exit(1)
  179. }
  180. err := zip.Zip(zip.ZipArgs{
  181. FileArgs: fileArgsBuilder.FileArgs(),
  182. OutputFilePath: *out,
  183. EmulateJar: *emulateJar,
  184. SrcJar: *srcJar,
  185. AddDirectoryEntriesToZip: *directories,
  186. CompressionLevel: *compLevel,
  187. ManifestSourcePath: *manifest,
  188. NumParallelJobs: *parallelJobs,
  189. NonDeflatedFiles: nonDeflatedFiles,
  190. WriteIfChanged: *writeIfChanged,
  191. StoreSymlinks: *symlinks,
  192. IgnoreMissingFiles: *ignoreMissingFiles,
  193. Sha256Checksum: *sha256Checksum,
  194. })
  195. if err != nil {
  196. fmt.Fprintln(os.Stderr, "error:", err.Error())
  197. os.Exit(1)
  198. }
  199. }