1// Copyright 2018 The Bazel Authors. 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 15// Package nativelib creates the native library zip. 16package nativelib 17 18import ( 19 "archive/zip" 20 "bufio" 21 "errors" 22 "flag" 23 "fmt" 24 "io/ioutil" 25 "log" 26 "os" 27 "path/filepath" 28 "sort" 29 "strings" 30 "sync" 31 32 "src/common/golang/fileutils" 33 "src/common/golang/flags" 34 "src/common/golang/ziputils" 35 "src/tools/ak/types" 36) 37 38var ( 39 // Cmd defines the command to run nativelib. 40 Cmd = types.Command{ 41 Init: Init, 42 Run: Run, 43 Desc: desc, 44 Flags: []string{"lib", "native_libs_zip", "out"}, 45 } 46 47 // Variables to hold flag values 48 nativeLibs flags.StringList 49 nativeLibsZip flags.StringList 50 out string 51 52 initOnce sync.Once 53) 54 55// Init initializes nativelib. 56func Init() { 57 initOnce.Do(func() { 58 flag.Var(&nativeLibs, "lib", "Path to native lib.") 59 flag.Var(&nativeLibsZip, "native_libs_zip", "Zip(s) containing native libs.") 60 flag.StringVar(&out, "out", "", "Native libraries files.") 61 }) 62} 63 64func desc() string { 65 return "Nativelib creates the native lib zip." 66} 67 68// Run is the entry point for nativelib. 69func Run() { 70 if nativeLibsZip != nil { 71 dstDir, err := ioutil.TempDir("", "ziplibs") 72 if err != nil { 73 log.Fatalf("Error creating native lib zip: %v", err) 74 } 75 76 for _, native := range nativeLibsZip { 77 libs, err := extractLibs(native, dstDir) 78 if err != nil { 79 log.Fatalf("Error creating native lib zip: %v", err) 80 } 81 nativeLibs = append(nativeLibs, libs...) 82 } 83 } 84 85 if err := doWork(nativeLibs, out); err != nil { 86 log.Fatalf("Error creating native lib zip: %v", err) 87 } 88} 89 90func extractLibs(libZip, dstDir string) ([]string, error) { 91 zr, err := zip.OpenReader(libZip) 92 if err != nil { 93 return nil, err 94 } 95 defer zr.Close() 96 97 libs := []string{} 98 for _, f := range zr.File { 99 if f.Mode().IsDir() { 100 continue 101 } 102 arch := filepath.Base(filepath.Dir(f.Name)) 103 libs = append(libs, fmt.Sprintf("%s:%s", arch, filepath.Join(dstDir, f.Name))) 104 } 105 if err := ziputils.Unzip(libZip, dstDir); err != nil { 106 return nil, err 107 } 108 return libs, nil 109} 110 111func doWork(nativeLibs []string, out string) error { 112 nativeDir, err := ioutil.TempDir("", "nativelib") 113 if err != nil { 114 return err 115 } 116 defer os.RemoveAll(nativeDir) 117 nativePaths, err := copyNativeLibs(nativeLibs, nativeDir) 118 if err != nil { 119 return err 120 } 121 zipFile, err := os.Create(out) 122 if err != nil { 123 return err 124 } 125 writer := bufio.NewWriter(zipFile) 126 zipWriter := zip.NewWriter(writer) 127 sort.Strings(nativePaths) 128 for _, f := range nativePaths { 129 p, err := filepath.Rel(nativeDir, f) 130 if err != nil { 131 return err 132 } 133 ziputils.WriteFile(zipWriter, f, p) 134 } 135 zipWriter.Close() 136 return nil 137} 138 139func copyNativeLibs(nativeLibs []string, dir string) ([]string, error) { 140 var paths []string 141 for _, cpuNativeLib := range nativeLibs { 142 r := strings.SplitN(cpuNativeLib, ":", 2) 143 if len(r) != 2 { 144 return nil, errors.New("error parsing native lib") 145 } 146 arch := r[0] 147 nativeLib := r[1] 148 if arch == "armv7a" { 149 arch = "armeabi-v7a" 150 } 151 libOutDir := filepath.Join(dir, "lib", arch) 152 if err := os.MkdirAll(libOutDir, 0777); err != nil && !os.IsExist(err) { 153 return nil, err 154 } 155 outNativeLibPath := filepath.Join(libOutDir, filepath.Base(nativeLib)) 156 if err := fileutils.Copy(nativeLib, outNativeLibPath); err != nil { 157 return nil, err 158 } 159 paths = append(paths, outNativeLibPath) 160 } 161 return paths, nil 162} 163