github.com/ajguerrer/rules_go@v0.20.3/go/tools/builders/asm.go (about) 1 // Copyright 2017 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 main 16 17 import ( 18 "flag" 19 "fmt" 20 "go/build" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "runtime" 25 "strconv" 26 "strings" 27 ) 28 29 // asm builds a single .s file with "go tool asm". It is invoked by the 30 // Go rules as an action. 31 func asm(args []string) error { 32 // Parse arguments. 33 args, err := readParamsFiles(args) 34 if err != nil { 35 return err 36 } 37 builderArgs, asmFlags := splitArgs(args) 38 var outPath string 39 flags := flag.NewFlagSet("GoAsm", flag.ExitOnError) 40 flags.StringVar(&outPath, "o", "", "The output archive file to write") 41 goenv := envFlags(flags) 42 if err := flags.Parse(builderArgs); err != nil { 43 return err 44 } 45 if err := goenv.checkFlags(); err != nil { 46 return err 47 } 48 if flags.NArg() != 1 { 49 return fmt.Errorf("wanted exactly 1 source file; got %d", flags.NArg()) 50 } 51 source := flags.Args()[0] 52 53 // Filter the input file. 54 metadata, err := readFileInfo(build.Default, source, false) 55 if err != nil { 56 return err 57 } 58 if !metadata.matched { 59 source = os.DevNull 60 } 61 62 // Build source with the assembler. 63 return asmFile(goenv, source, asmFlags, outPath) 64 } 65 66 // buildSymabisFile generates a file from assembly files that is consumed 67 // by the compiler. This is only needed in go1.12+ when there is at least one 68 // .s file. If the symabis file is not needed, no file will be generated, 69 // and "", nil will be returned. 70 func buildSymabisFile(goenv *env, sFiles, hFiles []fileInfo, asmhdr string) (string, error) { 71 if len(sFiles) == 0 { 72 return "", nil 73 } 74 75 // Check version. The symabis file is only required and can only be built 76 // starting at go1.12. 77 version := runtime.Version() 78 if strings.HasPrefix(version, "go1.") { 79 minor := version[len("go1."):] 80 if i := strings.IndexByte(minor, '.'); i >= 0 { 81 minor = minor[:i] 82 } 83 n, err := strconv.Atoi(minor) 84 if err == nil && n <= 11 { 85 return "", nil 86 } 87 // Fall through if the version can't be parsed. It's probably a newer 88 // development version. 89 } 90 91 // Create an empty go_asm.h file. The compiler will write this later, but 92 // we need one to exist now. 93 asmhdrFile, err := os.Create(asmhdr) 94 if err != nil { 95 return "", err 96 } 97 if err := asmhdrFile.Close(); err != nil { 98 return "", err 99 } 100 asmhdrDir := filepath.Dir(asmhdr) 101 102 // Create a temporary output file. The caller is responsible for deleting it. 103 var symabisName string 104 symabisFile, err := ioutil.TempFile("", "symabis") 105 if err != nil { 106 return "", err 107 } 108 symabisName = symabisFile.Name() 109 symabisFile.Close() 110 111 // Run the assembler. 112 wd, err := os.Getwd() 113 if err != nil { 114 return symabisName, err 115 } 116 asmargs := goenv.goTool("asm") 117 asmargs = append(asmargs, "-trimpath", wd) 118 asmargs = append(asmargs, "-I", wd) 119 asmargs = append(asmargs, "-I", filepath.Join(os.Getenv("GOROOT"), "pkg", "include")) 120 asmargs = append(asmargs, "-I", asmhdrDir) 121 seenHdrDirs := map[string]bool{wd: true, asmhdrDir: true} 122 for _, hFile := range hFiles { 123 hdrDir := filepath.Dir(abs(hFile.filename)) 124 if !seenHdrDirs[hdrDir] { 125 asmargs = append(asmargs, "-I", hdrDir) 126 seenHdrDirs[hdrDir] = true 127 } 128 } 129 // TODO(#1894): define GOOS_goos, GOARCH_goarch, both here and in the 130 // GoAsm action. 131 asmargs = append(asmargs, "-gensymabis", "-o", symabisName, "--") 132 for _, sFile := range sFiles { 133 asmargs = append(asmargs, sFile.filename) 134 } 135 136 err = goenv.runCommand(asmargs) 137 return symabisName, err 138 } 139 140 func asmFile(goenv *env, srcPath string, asmFlags []string, outPath string) error { 141 args := goenv.goTool("asm") 142 args = append(args, asmFlags...) 143 args = append(args, "-trimpath", ".") 144 args = append(args, "-o", outPath) 145 args = append(args, "--", srcPath) 146 absArgs(args, []string{"-I", "-o", "-trimpath"}) 147 return goenv.runCommand(args) 148 }