github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/cmd/link/internal/ld/config.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ld
     6  
     7  import (
     8  	"cmd/internal/objabi"
     9  	"cmd/internal/sys"
    10  	"fmt"
    11  	"log"
    12  )
    13  
    14  var (
    15  	Linkmode  LinkMode
    16  	Buildmode BuildMode
    17  )
    18  
    19  // A BuildMode indicates the sort of object we are building.
    20  //
    21  // Possible build modes are the same as those for the -buildmode flag
    22  // in cmd/go, and are documented in 'go help buildmode'.
    23  type BuildMode uint8
    24  
    25  const (
    26  	BuildmodeUnset BuildMode = iota
    27  	BuildmodeExe
    28  	BuildmodePIE
    29  	BuildmodeCArchive
    30  	BuildmodeCShared
    31  	BuildmodeShared
    32  	BuildmodePlugin
    33  )
    34  
    35  func (mode *BuildMode) Set(s string) error {
    36  	badmode := func() error {
    37  		return fmt.Errorf("buildmode %s not supported on %s/%s", s, objabi.GOOS, objabi.GOARCH)
    38  	}
    39  	switch s {
    40  	default:
    41  		return fmt.Errorf("invalid buildmode: %q", s)
    42  	case "exe":
    43  		*mode = BuildmodeExe
    44  	case "pie":
    45  		switch objabi.GOOS {
    46  		case "android", "linux":
    47  		case "darwin":
    48  			switch objabi.GOARCH {
    49  			case "amd64":
    50  			default:
    51  				return badmode()
    52  			}
    53  		default:
    54  			return badmode()
    55  		}
    56  		*mode = BuildmodePIE
    57  	case "c-archive":
    58  		switch objabi.GOOS {
    59  		case "darwin", "linux":
    60  		case "windows":
    61  			switch objabi.GOARCH {
    62  			case "amd64", "386":
    63  			default:
    64  				return badmode()
    65  			}
    66  		default:
    67  			return badmode()
    68  		}
    69  		*mode = BuildmodeCArchive
    70  	case "c-shared":
    71  		switch objabi.GOARCH {
    72  		case "386", "amd64", "arm", "arm64", "ppc64le":
    73  		default:
    74  			return badmode()
    75  		}
    76  		*mode = BuildmodeCShared
    77  	case "shared":
    78  		switch objabi.GOOS {
    79  		case "linux":
    80  			switch objabi.GOARCH {
    81  			case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
    82  			default:
    83  				return badmode()
    84  			}
    85  		default:
    86  			return badmode()
    87  		}
    88  		*mode = BuildmodeShared
    89  	case "plugin":
    90  		switch objabi.GOOS {
    91  		case "linux":
    92  			switch objabi.GOARCH {
    93  			case "386", "amd64", "arm", "arm64", "s390x":
    94  			default:
    95  				return badmode()
    96  			}
    97  		case "darwin":
    98  			switch objabi.GOARCH {
    99  			case "amd64":
   100  			default:
   101  				return badmode()
   102  			}
   103  		default:
   104  			return badmode()
   105  		}
   106  		*mode = BuildmodePlugin
   107  	}
   108  	return nil
   109  }
   110  
   111  func (mode *BuildMode) String() string {
   112  	switch *mode {
   113  	case BuildmodeUnset:
   114  		return "" // avoid showing a default in usage message
   115  	case BuildmodeExe:
   116  		return "exe"
   117  	case BuildmodePIE:
   118  		return "pie"
   119  	case BuildmodeCArchive:
   120  		return "c-archive"
   121  	case BuildmodeCShared:
   122  		return "c-shared"
   123  	case BuildmodeShared:
   124  		return "shared"
   125  	case BuildmodePlugin:
   126  		return "plugin"
   127  	}
   128  	return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
   129  }
   130  
   131  // LinkMode indicates whether an external linker is used for the final link.
   132  type LinkMode uint8
   133  
   134  const (
   135  	LinkAuto LinkMode = iota
   136  	LinkInternal
   137  	LinkExternal
   138  )
   139  
   140  func (mode *LinkMode) Set(s string) error {
   141  	switch s {
   142  	default:
   143  		return fmt.Errorf("invalid linkmode: %q", s)
   144  	case "auto":
   145  		*mode = LinkAuto
   146  	case "internal":
   147  		*mode = LinkInternal
   148  	case "external":
   149  		*mode = LinkExternal
   150  	}
   151  	return nil
   152  }
   153  
   154  func (mode *LinkMode) String() string {
   155  	switch *mode {
   156  	case LinkAuto:
   157  		return "auto"
   158  	case LinkInternal:
   159  		return "internal"
   160  	case LinkExternal:
   161  		return "external"
   162  	}
   163  	return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
   164  }
   165  
   166  // mustLinkExternal reports whether the program being linked requires
   167  // the external linker be used to complete the link.
   168  func mustLinkExternal(ctxt *Link) (res bool, reason string) {
   169  	if ctxt.Debugvlog > 1 {
   170  		defer func() {
   171  			if res {
   172  				log.Printf("external linking is forced by: %s\n", reason)
   173  			}
   174  		}()
   175  	}
   176  
   177  	switch objabi.GOOS {
   178  	case "android":
   179  		return true, "android"
   180  	case "darwin":
   181  		if SysArch.InFamily(sys.ARM, sys.ARM64) {
   182  			return true, "iOS"
   183  		}
   184  	}
   185  
   186  	if *flagMsan {
   187  		return true, "msan"
   188  	}
   189  
   190  	// Internally linking cgo is incomplete on some architectures.
   191  	// https://golang.org/issue/10373
   192  	// https://golang.org/issue/14449
   193  	if iscgo && SysArch.InFamily(sys.ARM64, sys.MIPS64, sys.MIPS) {
   194  		return true, objabi.GOARCH + " does not support internal cgo"
   195  	}
   196  
   197  	// Some build modes require work the internal linker cannot do (yet).
   198  	switch Buildmode {
   199  	case BuildmodeCArchive:
   200  		return true, "buildmode=c-archive"
   201  	case BuildmodeCShared:
   202  		return true, "buildmode=c-shared"
   203  	case BuildmodePIE:
   204  		switch objabi.GOOS + "/" + objabi.GOARCH {
   205  		case "linux/amd64":
   206  		default:
   207  			// Internal linking does not support TLS_IE.
   208  			return true, "buildmode=pie"
   209  		}
   210  	case BuildmodePlugin:
   211  		return true, "buildmode=plugin"
   212  	case BuildmodeShared:
   213  		return true, "buildmode=shared"
   214  	}
   215  	if *FlagLinkshared {
   216  		return true, "dynamically linking with a shared library"
   217  	}
   218  
   219  	return false, ""
   220  }
   221  
   222  // determineLinkMode sets Linkmode.
   223  //
   224  // It is called after flags are processed and inputs are processed,
   225  // so the Linkmode variable has an initial value from the -linkmode
   226  // flag and the iscgo externalobj variables are set.
   227  func determineLinkMode(ctxt *Link) {
   228  	switch Linkmode {
   229  	case LinkAuto:
   230  		// The environment variable GO_EXTLINK_ENABLED controls the
   231  		// default value of -linkmode. If it is not set when the
   232  		// linker is called we take the value it was set to when
   233  		// cmd/link was compiled. (See make.bash.)
   234  		switch objabi.Getgoextlinkenabled() {
   235  		case "0":
   236  			if needed, reason := mustLinkExternal(ctxt); needed {
   237  				Exitf("internal linking requested via GO_EXTLINK_ENABLED, but external linking required: %s", reason)
   238  			}
   239  			Linkmode = LinkInternal
   240  		case "1":
   241  			Linkmode = LinkExternal
   242  		default:
   243  			if needed, _ := mustLinkExternal(ctxt); needed {
   244  				Linkmode = LinkExternal
   245  			} else if iscgo && externalobj {
   246  				Linkmode = LinkExternal
   247  			} else if Buildmode == BuildmodePIE {
   248  				Linkmode = LinkExternal // https://golang.org/issue/18968
   249  			} else {
   250  				Linkmode = LinkInternal
   251  			}
   252  		}
   253  	case LinkInternal:
   254  		if needed, reason := mustLinkExternal(ctxt); needed {
   255  			Exitf("internal linking requested but external linking required: %s", reason)
   256  		}
   257  	}
   258  }