...

Source file src/github.com/bazelbuild/rules_go/go/tools/builders/asm.go

Documentation: github.com/bazelbuild/rules_go/go/tools/builders

     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  	"go/build"
    19  	"io/ioutil"
    20  	"os"
    21  	"path/filepath"
    22  	"regexp"
    23  	"runtime"
    24  	"strconv"
    25  	"strings"
    26  )
    27  
    28  var ASM_DEFINES = []string{
    29  	"-D", "GOOS_" + build.Default.GOOS,
    30  	"-D", "GOARCH_" + build.Default.GOARCH,
    31  	"-D", "GOOS_GOARCH_" + build.Default.GOOS + "_" + build.Default.GOARCH,
    32  }
    33  
    34  // buildSymabisFile generates a file from assembly files that is consumed
    35  // by the compiler. This is only needed in go1.12+ when there is at least one
    36  // .s file. If the symabis file is not needed, no file will be generated,
    37  // and "", nil will be returned.
    38  func buildSymabisFile(goenv *env, packagePath string, sFiles, hFiles []fileInfo, asmhdr string) (string, error) {
    39  	if len(sFiles) == 0 {
    40  		return "", nil
    41  	}
    42  
    43  	// Check version. The symabis file is only required and can only be built
    44  	// starting at go1.12.
    45  	version := runtime.Version()
    46  	if strings.HasPrefix(version, "go1.") {
    47  		minor := version[len("go1."):]
    48  		if i := strings.IndexByte(minor, '.'); i >= 0 {
    49  			minor = minor[:i]
    50  		}
    51  		n, err := strconv.Atoi(minor)
    52  		if err == nil && n <= 11 {
    53  			return "", nil
    54  		}
    55  		// Fall through if the version can't be parsed. It's probably a newer
    56  		// development version.
    57  	}
    58  
    59  	// Create an empty go_asm.h file. The compiler will write this later, but
    60  	// we need one to exist now.
    61  	asmhdrFile, err := os.Create(asmhdr)
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  	if err := asmhdrFile.Close(); err != nil {
    66  		return "", err
    67  	}
    68  	asmhdrDir := filepath.Dir(asmhdr)
    69  
    70  	// Create a temporary output file. The caller is responsible for deleting it.
    71  	var symabisName string
    72  	symabisFile, err := ioutil.TempFile("", "symabis")
    73  	if err != nil {
    74  		return "", err
    75  	}
    76  	symabisName = symabisFile.Name()
    77  	symabisFile.Close()
    78  
    79  	// Run the assembler.
    80  	wd, err := os.Getwd()
    81  	if err != nil {
    82  		return symabisName, err
    83  	}
    84  	asmargs := goenv.goTool("asm")
    85  	asmargs = append(asmargs, "-trimpath", wd)
    86  	asmargs = append(asmargs, "-I", wd)
    87  	asmargs = append(asmargs, "-I", filepath.Join(os.Getenv("GOROOT"), "pkg", "include"))
    88  	asmargs = append(asmargs, "-I", asmhdrDir)
    89  	seenHdrDirs := map[string]bool{wd: true, asmhdrDir: true}
    90  	for _, hFile := range hFiles {
    91  		hdrDir := filepath.Dir(abs(hFile.filename))
    92  		if !seenHdrDirs[hdrDir] {
    93  			asmargs = append(asmargs, "-I", hdrDir)
    94  			seenHdrDirs[hdrDir] = true
    95  		}
    96  	}
    97  	// The package path has to be specified as of Go 1.22 or the resulting
    98  	// object will be unlinkable, but the -p flag is only required in
    99  	// preparing symabis since Go1.22, however, go build has been
   100  	// emitting -p for both symabi and actual assembly since at least Go1.19
   101  	if packagePath != "" && isGo119OrHigher() {
   102  		asmargs = append(asmargs, "-p", packagePath)
   103  	}
   104  	asmargs = append(asmargs, ASM_DEFINES...)
   105  	asmargs = append(asmargs, "-gensymabis", "-o", symabisName, "--")
   106  	for _, sFile := range sFiles {
   107  		asmargs = append(asmargs, sFile.filename)
   108  	}
   109  
   110  	err = goenv.runCommand(asmargs)
   111  	return symabisName, err
   112  }
   113  
   114  func asmFile(goenv *env, srcPath, packagePath string, asmFlags []string, outPath string) error {
   115  	args := goenv.goTool("asm")
   116  	args = append(args, asmFlags...)
   117  	// The package path has to be specified as of Go 1.19 or the resulting
   118  	// object will be unlinkable, but the -p flag is also only available
   119  	// since Go 1.19.
   120  	if packagePath != "" && isGo119OrHigher() {
   121  		args = append(args, "-p", packagePath)
   122  	}
   123  	args = append(args, ASM_DEFINES...)
   124  	args = append(args, "-trimpath", ".")
   125  	args = append(args, "-o", outPath)
   126  	args = append(args, "--", srcPath)
   127  	absArgs(args, []string{"-I", "-o", "-trimpath"})
   128  	return goenv.runCommand(args)
   129  }
   130  
   131  var goMinorVersionRegexp = regexp.MustCompile(`^go1\.(\d+)`)
   132  
   133  func isGo119OrHigher() bool {
   134  	match := goMinorVersionRegexp.FindStringSubmatch(runtime.Version())
   135  	if match == nil {
   136  		// Developer version or something with an unparseable version string,
   137  		// assume Go 1.19 or higher.
   138  		return true
   139  	}
   140  	minorVersion, err := strconv.Atoi(match[1])
   141  	if err != nil {
   142  		return true
   143  	}
   144  	return minorVersion >= 19
   145  }
   146  

View as plain text