1*8fb009dcSAndroid Build Coastguard Worker// Copyright (c) 2024, Google Inc. 2*8fb009dcSAndroid Build Coastguard Worker// 3*8fb009dcSAndroid Build Coastguard Worker// Permission to use, copy, modify, and/or distribute this software for any 4*8fb009dcSAndroid Build Coastguard Worker// purpose with or without fee is hereby granted, provided that the above 5*8fb009dcSAndroid Build Coastguard Worker// copyright notice and this permission notice appear in all copies. 6*8fb009dcSAndroid Build Coastguard Worker// 7*8fb009dcSAndroid Build Coastguard Worker// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8*8fb009dcSAndroid Build Coastguard Worker// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9*8fb009dcSAndroid Build Coastguard Worker// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10*8fb009dcSAndroid Build Coastguard Worker// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11*8fb009dcSAndroid Build Coastguard Worker// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12*8fb009dcSAndroid Build Coastguard Worker// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13*8fb009dcSAndroid Build Coastguard Worker// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14*8fb009dcSAndroid Build Coastguard Worker 15*8fb009dcSAndroid Build Coastguard Workerpackage main 16*8fb009dcSAndroid Build Coastguard Worker 17*8fb009dcSAndroid Build Coastguard Workerimport ( 18*8fb009dcSAndroid Build Coastguard Worker "bytes" 19*8fb009dcSAndroid Build Coastguard Worker "os" 20*8fb009dcSAndroid Build Coastguard Worker "os/exec" 21*8fb009dcSAndroid Build Coastguard Worker "path" 22*8fb009dcSAndroid Build Coastguard Worker "path/filepath" 23*8fb009dcSAndroid Build Coastguard Worker) 24*8fb009dcSAndroid Build Coastguard Worker 25*8fb009dcSAndroid Build Coastguard Workertype Task interface { 26*8fb009dcSAndroid Build Coastguard Worker // Destination returns the destination path for this task, using forward 27*8fb009dcSAndroid Build Coastguard Worker // slashes and relative to the source directory. That is, use the "path" 28*8fb009dcSAndroid Build Coastguard Worker // package, not "path/filepath". 29*8fb009dcSAndroid Build Coastguard Worker Destination() string 30*8fb009dcSAndroid Build Coastguard Worker 31*8fb009dcSAndroid Build Coastguard Worker // Run computes the output for this task. It should be written to the 32*8fb009dcSAndroid Build Coastguard Worker // destination path. 33*8fb009dcSAndroid Build Coastguard Worker Run() ([]byte, error) 34*8fb009dcSAndroid Build Coastguard Worker} 35*8fb009dcSAndroid Build Coastguard Worker 36*8fb009dcSAndroid Build Coastguard Workertype SimpleTask struct { 37*8fb009dcSAndroid Build Coastguard Worker Dst string 38*8fb009dcSAndroid Build Coastguard Worker RunFunc func() ([]byte, error) 39*8fb009dcSAndroid Build Coastguard Worker} 40*8fb009dcSAndroid Build Coastguard Worker 41*8fb009dcSAndroid Build Coastguard Workerfunc (t *SimpleTask) Destination() string { return t.Dst } 42*8fb009dcSAndroid Build Coastguard Workerfunc (t *SimpleTask) Run() ([]byte, error) { return t.RunFunc() } 43*8fb009dcSAndroid Build Coastguard Worker 44*8fb009dcSAndroid Build Coastguard Workerfunc NewSimpleTask(dst string, runFunc func() ([]byte, error)) *SimpleTask { 45*8fb009dcSAndroid Build Coastguard Worker return &SimpleTask{Dst: dst, RunFunc: runFunc} 46*8fb009dcSAndroid Build Coastguard Worker} 47*8fb009dcSAndroid Build Coastguard Worker 48*8fb009dcSAndroid Build Coastguard Workertype PerlasmTask struct { 49*8fb009dcSAndroid Build Coastguard Worker Src, Dst string 50*8fb009dcSAndroid Build Coastguard Worker Args []string 51*8fb009dcSAndroid Build Coastguard Worker} 52*8fb009dcSAndroid Build Coastguard Worker 53*8fb009dcSAndroid Build Coastguard Workerfunc (t *PerlasmTask) Destination() string { return t.Dst } 54*8fb009dcSAndroid Build Coastguard Workerfunc (t *PerlasmTask) Run() ([]byte, error) { 55*8fb009dcSAndroid Build Coastguard Worker base := path.Base(t.Dst) 56*8fb009dcSAndroid Build Coastguard Worker out, err := os.CreateTemp("", "*."+base) 57*8fb009dcSAndroid Build Coastguard Worker if err != nil { 58*8fb009dcSAndroid Build Coastguard Worker return nil, err 59*8fb009dcSAndroid Build Coastguard Worker } 60*8fb009dcSAndroid Build Coastguard Worker defer os.Remove(out.Name()) 61*8fb009dcSAndroid Build Coastguard Worker 62*8fb009dcSAndroid Build Coastguard Worker args := make([]string, 0, 2+len(t.Args)) 63*8fb009dcSAndroid Build Coastguard Worker args = append(args, filepath.FromSlash(t.Src)) 64*8fb009dcSAndroid Build Coastguard Worker args = append(args, t.Args...) 65*8fb009dcSAndroid Build Coastguard Worker args = append(args, out.Name()) 66*8fb009dcSAndroid Build Coastguard Worker cmd := exec.Command(*perlPath, args...) 67*8fb009dcSAndroid Build Coastguard Worker cmd.Stderr = os.Stderr 68*8fb009dcSAndroid Build Coastguard Worker cmd.Stdout = os.Stdout 69*8fb009dcSAndroid Build Coastguard Worker if err := cmd.Run(); err != nil { 70*8fb009dcSAndroid Build Coastguard Worker return nil, err 71*8fb009dcSAndroid Build Coastguard Worker } 72*8fb009dcSAndroid Build Coastguard Worker 73*8fb009dcSAndroid Build Coastguard Worker data, err := os.ReadFile(out.Name()) 74*8fb009dcSAndroid Build Coastguard Worker if err != nil { 75*8fb009dcSAndroid Build Coastguard Worker return nil, err 76*8fb009dcSAndroid Build Coastguard Worker } 77*8fb009dcSAndroid Build Coastguard Worker 78*8fb009dcSAndroid Build Coastguard Worker // On Windows, perl emits CRLF line endings. Normalize this so that the tool 79*8fb009dcSAndroid Build Coastguard Worker // can be run on Windows too. 80*8fb009dcSAndroid Build Coastguard Worker data = bytes.ReplaceAll(data, []byte("\r\n"), []byte("\n")) 81*8fb009dcSAndroid Build Coastguard Worker return data, nil 82*8fb009dcSAndroid Build Coastguard Worker} 83