|  | // Copyright 2024 The BoringSSL Authors | 
|  | // | 
|  | // Permission to use, copy, modify, and/or distribute this software for any | 
|  | // purpose with or without fee is hereby granted, provided that the above | 
|  | // copyright notice and this permission notice appear in all copies. | 
|  | // | 
|  | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
|  | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
|  | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | 
|  | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
|  | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | 
|  | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | 
|  | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
|  |  | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "bytes" | 
|  | "os" | 
|  | "os/exec" | 
|  | "path" | 
|  | "path/filepath" | 
|  | ) | 
|  |  | 
|  | type Task interface { | 
|  | // Destination returns the destination path for this task, using forward | 
|  | // slashes and relative to the source directory. That is, use the "path" | 
|  | // package, not "path/filepath". | 
|  | Destination() string | 
|  |  | 
|  | // Run computes the output for this task. It should be written to the | 
|  | // destination path. | 
|  | Run() ([]byte, error) | 
|  | } | 
|  |  | 
|  | type SimpleTask struct { | 
|  | Dst     string | 
|  | RunFunc func() ([]byte, error) | 
|  | } | 
|  |  | 
|  | func (t *SimpleTask) Destination() string  { return t.Dst } | 
|  | func (t *SimpleTask) Run() ([]byte, error) { return t.RunFunc() } | 
|  |  | 
|  | func NewSimpleTask(dst string, runFunc func() ([]byte, error)) *SimpleTask { | 
|  | return &SimpleTask{Dst: dst, RunFunc: runFunc} | 
|  | } | 
|  |  | 
|  | type PerlasmTask struct { | 
|  | Src, Dst string | 
|  | Args     []string | 
|  | } | 
|  |  | 
|  | func (t *PerlasmTask) Destination() string { return t.Dst } | 
|  | func (t *PerlasmTask) Run() ([]byte, error) { | 
|  | base := path.Base(t.Dst) | 
|  | out, err := os.CreateTemp("", "*."+base) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | defer os.Remove(out.Name()) | 
|  |  | 
|  | args := make([]string, 0, 2+len(t.Args)) | 
|  | args = append(args, filepath.FromSlash(t.Src)) | 
|  | args = append(args, t.Args...) | 
|  | args = append(args, out.Name()) | 
|  | cmd := exec.Command(*perlPath, args...) | 
|  | cmd.Stderr = os.Stderr | 
|  | cmd.Stdout = os.Stdout | 
|  | if err := cmd.Run(); err != nil { | 
|  | return nil, err | 
|  | } | 
|  |  | 
|  | data, err := os.ReadFile(out.Name()) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  |  | 
|  | // On Windows, perl emits CRLF line endings. Normalize this so that the tool | 
|  | // can be run on Windows too. | 
|  | data = bytes.ReplaceAll(data, []byte("\r\n"), []byte("\n")) | 
|  | return data, nil | 
|  | } |