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