2017-10-13 03:19:14 +08:00
|
|
|
// Copyright 2015 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"runtime"
|
2018-09-28 06:04:24 +08:00
|
|
|
"runtime/pprof"
|
|
|
|
"runtime/trace"
|
2018-09-19 07:51:43 +08:00
|
|
|
"strconv"
|
2017-10-13 03:19:14 +08:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"android/soong/zip"
|
|
|
|
)
|
|
|
|
|
|
|
|
type uniqueSet map[string]bool
|
|
|
|
|
|
|
|
func (u *uniqueSet) String() string {
|
|
|
|
return `""`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *uniqueSet) Set(s string) error {
|
|
|
|
if _, found := (*u)[s]; found {
|
|
|
|
return fmt.Errorf("File %q was specified twice as a file to not deflate", s)
|
|
|
|
} else {
|
|
|
|
(*u)[s] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type file struct{}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (file) String() string { return `""` }
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (file) Set(s string) error {
|
|
|
|
fileArgsBuilder.File(s)
|
|
|
|
return nil
|
2017-10-13 03:19:14 +08:00
|
|
|
}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
type listFiles struct{}
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (listFiles) String() string { return `""` }
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (listFiles) Set(s string) error {
|
|
|
|
fileArgsBuilder.List(s)
|
2017-10-13 03:19:14 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
type dir struct{}
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (dir) String() string { return `""` }
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (dir) Set(s string) error {
|
|
|
|
fileArgsBuilder.Dir(s)
|
2017-10-13 03:19:14 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
type relativeRoot struct{}
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (relativeRoot) String() string { return "" }
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (relativeRoot) Set(s string) error {
|
|
|
|
fileArgsBuilder.SourcePrefixToStrip(s)
|
2017-10-13 03:19:14 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
type junkPaths struct{}
|
2018-09-19 07:51:43 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (junkPaths) IsBoolFlag() bool { return true }
|
|
|
|
func (junkPaths) String() string { return "" }
|
2018-09-19 07:51:43 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (junkPaths) Set(s string) error {
|
|
|
|
v, err := strconv.ParseBool(s)
|
|
|
|
fileArgsBuilder.JunkPaths(v)
|
|
|
|
return err
|
2018-09-19 07:51:43 +08:00
|
|
|
}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
type rootPrefix struct{}
|
2018-09-19 07:51:43 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (rootPrefix) String() string { return "" }
|
2018-09-19 07:51:43 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
func (rootPrefix) Set(s string) error {
|
|
|
|
fileArgsBuilder.PathPrefixInZip(s)
|
|
|
|
return nil
|
2018-09-19 07:51:43 +08:00
|
|
|
}
|
|
|
|
|
2017-10-13 03:19:14 +08:00
|
|
|
var (
|
2018-09-28 06:00:07 +08:00
|
|
|
fileArgsBuilder = zip.NewFileArgsBuilder()
|
2017-10-13 03:19:14 +08:00
|
|
|
nonDeflatedFiles = make(uniqueSet)
|
|
|
|
)
|
|
|
|
|
|
|
|
func usage() {
|
2018-09-28 06:00:07 +08:00
|
|
|
fmt.Fprintf(os.Stderr, "usage: soong_zip -o zipfile [-m manifest] [-C dir] [-f|-l file] [-D dir]...\n")
|
2017-10-13 03:19:14 +08:00
|
|
|
flag.PrintDefaults()
|
|
|
|
os.Exit(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
Add Respfile support for soong_zip.
Sometime the size of our command line passed to soong_zip go program
exceeds the cmdline size limit. So add an RespFile support with "@" special
character prefix.
The args in the cmdline will be considered together with the
args in RespFile during soong_zip running.
Test: real tests in my local machine, and compare the
res/libphonenumber.jar before and after changes.
./cmd -o test.zip '""'-C -> [./cmd,-o,test.zip,""-C]
./cmd -o test.zip '-C -f -> [./cmd,-o,test.zip,-C -f]
./cmd -o test.zip '\"'-C -f -> [./cmd,-o,test.zip,\"-C -f]
./cmd -o test.zip '\\'-C -f -> [./cmd,-o,test.zip,\\-C -f]
./cmd -o test.zip '\a'-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip \'-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip \\-C -> [./cmd,-o,test.zip,\-C]
./cmd -o test.zip \"-C -> [./cmd,-o,test.zip,"-C]
./cmd -o test.zip "'"-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip "\\"-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip "\""-C -f -> [./cmd,-o,test.zip,"a-C -f]
Bug: b/72484223
Change-Id: I83c3630b70c8396c8e8a3f266244d868d754c4e8
2018-01-27 10:30:36 +08:00
|
|
|
var expandedArgs []string
|
|
|
|
for _, arg := range os.Args {
|
|
|
|
if strings.HasPrefix(arg, "@") {
|
|
|
|
bytes, err := ioutil.ReadFile(strings.TrimPrefix(arg, "@"))
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
respArgs := zip.ReadRespFile(bytes)
|
|
|
|
expandedArgs = append(expandedArgs, respArgs...)
|
|
|
|
} else {
|
|
|
|
expandedArgs = append(expandedArgs, arg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flags := flag.NewFlagSet("flags", flag.ExitOnError)
|
2018-09-28 06:00:07 +08:00
|
|
|
flags.Usage = usage
|
Add Respfile support for soong_zip.
Sometime the size of our command line passed to soong_zip go program
exceeds the cmdline size limit. So add an RespFile support with "@" special
character prefix.
The args in the cmdline will be considered together with the
args in RespFile during soong_zip running.
Test: real tests in my local machine, and compare the
res/libphonenumber.jar before and after changes.
./cmd -o test.zip '""'-C -> [./cmd,-o,test.zip,""-C]
./cmd -o test.zip '-C -f -> [./cmd,-o,test.zip,-C -f]
./cmd -o test.zip '\"'-C -f -> [./cmd,-o,test.zip,\"-C -f]
./cmd -o test.zip '\\'-C -f -> [./cmd,-o,test.zip,\\-C -f]
./cmd -o test.zip '\a'-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip \'-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip \\-C -> [./cmd,-o,test.zip,\-C]
./cmd -o test.zip \"-C -> [./cmd,-o,test.zip,"-C]
./cmd -o test.zip "'"-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip "\\"-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip "\""-C -f -> [./cmd,-o,test.zip,"a-C -f]
Bug: b/72484223
Change-Id: I83c3630b70c8396c8e8a3f266244d868d754c4e8
2018-01-27 10:30:36 +08:00
|
|
|
|
|
|
|
out := flags.String("o", "", "file to write zip file to")
|
|
|
|
manifest := flags.String("m", "", "input jar manifest file name")
|
|
|
|
directories := flags.Bool("d", false, "include directories in zip")
|
|
|
|
compLevel := flags.Int("L", 5, "deflate compression level (0-9)")
|
|
|
|
emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'")
|
|
|
|
writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed")
|
2018-09-29 06:16:48 +08:00
|
|
|
ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist")
|
2018-09-22 06:12:39 +08:00
|
|
|
symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them")
|
|
|
|
|
2018-09-19 07:31:09 +08:00
|
|
|
parallelJobs := flags.Int("parallel", runtime.NumCPU(), "number of parallel threads to use")
|
Add Respfile support for soong_zip.
Sometime the size of our command line passed to soong_zip go program
exceeds the cmdline size limit. So add an RespFile support with "@" special
character prefix.
The args in the cmdline will be considered together with the
args in RespFile during soong_zip running.
Test: real tests in my local machine, and compare the
res/libphonenumber.jar before and after changes.
./cmd -o test.zip '""'-C -> [./cmd,-o,test.zip,""-C]
./cmd -o test.zip '-C -f -> [./cmd,-o,test.zip,-C -f]
./cmd -o test.zip '\"'-C -f -> [./cmd,-o,test.zip,\"-C -f]
./cmd -o test.zip '\\'-C -f -> [./cmd,-o,test.zip,\\-C -f]
./cmd -o test.zip '\a'-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip \'-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip \\-C -> [./cmd,-o,test.zip,\-C]
./cmd -o test.zip \"-C -> [./cmd,-o,test.zip,"-C]
./cmd -o test.zip "'"-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip "\\"-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip "\""-C -f -> [./cmd,-o,test.zip,"a-C -f]
Bug: b/72484223
Change-Id: I83c3630b70c8396c8e8a3f266244d868d754c4e8
2018-01-27 10:30:36 +08:00
|
|
|
cpuProfile := flags.String("cpuprofile", "", "write cpu profile to file")
|
|
|
|
traceFile := flags.String("trace", "", "write trace to file")
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
|
Add Respfile support for soong_zip.
Sometime the size of our command line passed to soong_zip go program
exceeds the cmdline size limit. So add an RespFile support with "@" special
character prefix.
The args in the cmdline will be considered together with the
args in RespFile during soong_zip running.
Test: real tests in my local machine, and compare the
res/libphonenumber.jar before and after changes.
./cmd -o test.zip '""'-C -> [./cmd,-o,test.zip,""-C]
./cmd -o test.zip '-C -f -> [./cmd,-o,test.zip,-C -f]
./cmd -o test.zip '\"'-C -f -> [./cmd,-o,test.zip,\"-C -f]
./cmd -o test.zip '\\'-C -f -> [./cmd,-o,test.zip,\\-C -f]
./cmd -o test.zip '\a'-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip \'-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip \\-C -> [./cmd,-o,test.zip,\-C]
./cmd -o test.zip \"-C -> [./cmd,-o,test.zip,"-C]
./cmd -o test.zip "'"-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip "\\"-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip "\""-C -f -> [./cmd,-o,test.zip,"a-C -f]
Bug: b/72484223
Change-Id: I83c3630b70c8396c8e8a3f266244d868d754c4e8
2018-01-27 10:30:36 +08:00
|
|
|
flags.Var(&listFiles{}, "l", "file containing list of .class files")
|
|
|
|
flags.Var(&dir{}, "D", "directory to include in zip")
|
|
|
|
flags.Var(&file{}, "f", "file to include in zip")
|
|
|
|
flags.Var(&nonDeflatedFiles, "s", "file path to be stored within the zip without compression")
|
2018-09-28 06:00:07 +08:00
|
|
|
flags.Var(&relativeRoot{}, "C", "path to use as relative root of files in following -f, -l, or -D arguments")
|
|
|
|
flags.Var(&junkPaths{}, "j", "junk paths, zip files without directory names")
|
Add Respfile support for soong_zip.
Sometime the size of our command line passed to soong_zip go program
exceeds the cmdline size limit. So add an RespFile support with "@" special
character prefix.
The args in the cmdline will be considered together with the
args in RespFile during soong_zip running.
Test: real tests in my local machine, and compare the
res/libphonenumber.jar before and after changes.
./cmd -o test.zip '""'-C -> [./cmd,-o,test.zip,""-C]
./cmd -o test.zip '-C -f -> [./cmd,-o,test.zip,-C -f]
./cmd -o test.zip '\"'-C -f -> [./cmd,-o,test.zip,\"-C -f]
./cmd -o test.zip '\\'-C -f -> [./cmd,-o,test.zip,\\-C -f]
./cmd -o test.zip '\a'-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip \'-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip \\-C -> [./cmd,-o,test.zip,\-C]
./cmd -o test.zip \"-C -> [./cmd,-o,test.zip,"-C]
./cmd -o test.zip "'"-C -> [./cmd,-o,test.zip,'-C]
./cmd -o test.zip "\\"-C -f -> [./cmd,-o,test.zip,\a-C -f]
./cmd -o test.zip "\""-C -f -> [./cmd,-o,test.zip,"a-C -f]
Bug: b/72484223
Change-Id: I83c3630b70c8396c8e8a3f266244d868d754c4e8
2018-01-27 10:30:36 +08:00
|
|
|
|
|
|
|
flags.Parse(expandedArgs[1:])
|
2017-10-13 03:19:14 +08:00
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
if flags.NArg() > 0 {
|
|
|
|
fmt.Fprintf(os.Stderr, "unexpected arguments %s\n", strings.Join(flags.Args(), " "))
|
|
|
|
flags.Usage()
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:04:24 +08:00
|
|
|
if *cpuProfile != "" {
|
|
|
|
f, err := os.Create(*cpuProfile)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
pprof.StartCPUProfile(f)
|
|
|
|
defer pprof.StopCPUProfile()
|
|
|
|
}
|
|
|
|
|
|
|
|
if *traceFile != "" {
|
|
|
|
f, err := os.Create(*traceFile)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
err = trace.Start(f)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
defer trace.Stop()
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:00:07 +08:00
|
|
|
if fileArgsBuilder.Error() != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, fileArgsBuilder.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2018-09-28 06:06:19 +08:00
|
|
|
err := zip.Zip(zip.ZipArgs{
|
2018-09-28 06:00:07 +08:00
|
|
|
FileArgs: fileArgsBuilder.FileArgs(),
|
2017-10-13 03:19:14 +08:00
|
|
|
OutputFilePath: *out,
|
|
|
|
EmulateJar: *emulateJar,
|
|
|
|
AddDirectoryEntriesToZip: *directories,
|
|
|
|
CompressionLevel: *compLevel,
|
|
|
|
ManifestSourcePath: *manifest,
|
|
|
|
NumParallelJobs: *parallelJobs,
|
|
|
|
NonDeflatedFiles: nonDeflatedFiles,
|
2017-11-11 05:11:02 +08:00
|
|
|
WriteIfChanged: *writeIfChanged,
|
2018-09-22 06:12:39 +08:00
|
|
|
StoreSymlinks: *symlinks,
|
2018-09-29 06:16:48 +08:00
|
|
|
IgnoreMissingFiles: *ignoreMissingFiles,
|
2017-10-13 03:19:14 +08:00
|
|
|
})
|
|
|
|
if err != nil {
|
2018-09-22 06:12:39 +08:00
|
|
|
fmt.Fprintln(os.Stderr, "error:", err.Error())
|
2017-10-13 03:19:14 +08:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|