github.com/yunabe/lgo@v0.0.0-20190709125917-42c42d410fdf/cmd/lgo/install/main.go (about)

     1  package install
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"os/exec"
     9  	"path"
    10  	"path/filepath"
    11  	"runtime"
    12  
    13  	"github.com/yunabe/lgo/cmd/install"
    14  	"github.com/yunabe/lgo/core" // This import is also important to install the core package to GOPATH when lgo-install is installed.
    15  )
    16  
    17  // recordStderr invokes `tee` command to store logs and stderr of this command to install.log.
    18  // `tee` process is used instead of internal pipes and goroutine so that logs are stored properly
    19  // when this process is killed with SIGINT or os.Exit.
    20  func recordStderr(logPath string) error {
    21  	if err := func() error {
    22  		f, err := os.Create(logPath)
    23  		if err != nil {
    24  			return err
    25  		}
    26  		return f.Close()
    27  	}(); err != nil {
    28  		return fmt.Errorf("Failed to create a log file: %v", err)
    29  	}
    30  
    31  	r, w, err := os.Pipe()
    32  	if err != nil {
    33  		return err
    34  	}
    35  	tee := exec.Command("tee", "-i", logPath)
    36  	tee.Stdout = os.Stderr
    37  	tee.Stderr = os.Stderr
    38  	tee.Stdin = r
    39  	os.Stderr = w
    40  	log.SetOutput(w)
    41  	return tee.Start()
    42  }
    43  
    44  func checkEnv(logFileName string) string {
    45  	if runtime.GOOS != "linux" {
    46  		log.Fatal("lgo only supports Linux")
    47  	}
    48  	root := os.Getenv("LGOPATH")
    49  	if root == "" {
    50  		log.Fatalf("LGOPATH environ variable is not set")
    51  	}
    52  	root, err := filepath.Abs(root)
    53  	if err != nil {
    54  		log.Fatalf("Failed to get the abspath of LGOPATH: %v", err)
    55  	}
    56  	if err := os.MkdirAll(root, 0766); err != nil {
    57  		log.Fatalf("Failed to create a directory on $LGOPATH: %v", err)
    58  	}
    59  	// Record logs into logFileName and stderr.
    60  	if err := recordStderr(filepath.Join(root, logFileName)); err != nil {
    61  		log.Fatalf("Failed to record logs to install.log in %s: %v", root, err)
    62  	}
    63  	return root
    64  }
    65  
    66  func InstallMain() {
    67  	fSet := flag.NewFlagSet(os.Args[0]+" install", flag.ExitOnError)
    68  	cleanBeforeInstall := fSet.Bool("clean", false, "If true, clean existing files before install")
    69  	// Ignore errors; fSet is set for ExitOnError.
    70  	fSet.Parse(os.Args[2:])
    71  
    72  	root := checkEnv("install.log")
    73  	log.Printf("Install lgo to %s", root)
    74  	binDir := path.Join(root, "bin")
    75  	pkgDir := path.Join(root, "pkg")
    76  	if *cleanBeforeInstall {
    77  		log.Printf("Clean %s before install", root)
    78  		if err := os.RemoveAll(binDir); err != nil {
    79  			log.Fatalf("Failed to clean bin dir: %v", err)
    80  		}
    81  		if err := os.RemoveAll(pkgDir); err != nil {
    82  			log.Fatalf("Failed to clean pkg dir: %v", err)
    83  		}
    84  	}
    85  	if err := os.MkdirAll(binDir, 0766); err != nil {
    86  		log.Fatalf("Failed to create bin dir: %v", err)
    87  	}
    88  
    89  	if err := os.MkdirAll(pkgDir, 0766); err != nil {
    90  		log.Fatalf("Failed to clean pkg dir: %v", err)
    91  	}
    92  
    93  	log.Print("Building libstd.so")
    94  	// Note: From go1.10, libstd.so should be installed with -linkshared to avoid recompiling std libraries.
    95  	//       go1.8 and go1.9 work regardless of the existence of -linkshared here.
    96  	cmd := exec.Command("go", "install", "-buildmode=shared", "-linkshared", "-pkgdir", pkgDir, "std")
    97  	cmd.Stderr = os.Stderr
    98  	cmd.Stdout = os.Stdout
    99  	if err := cmd.Run(); err != nil {
   100  		log.Fatalf("Failed to build libstd.so: %v", err)
   101  	}
   102  
   103  	log.Print("Building lgo core package")
   104  	cmd = exec.Command("go", "install", "-buildmode=shared", "-linkshared", "-pkgdir", pkgDir, core.SelfPkgPath)
   105  	cmd.Stderr = os.Stderr
   106  	cmd.Stdout = os.Stdout
   107  	if err := cmd.Run(); err != nil {
   108  		log.Fatalf("Failed to build the shared object of the core library: %v", err)
   109  	}
   110  
   111  	log.Print("Building third-party packages in $GOPATH")
   112  	// buildThirdPartyPackages(pkgDir, newPackageBlackList(*packageBlacklists))
   113  
   114  	log.Print("Installing lgo-internal")
   115  	cmd = exec.Command("go", "build", "-pkgdir", pkgDir, "-linkshared",
   116  		"-o", path.Join(binDir, "lgo-internal"), "github.com/yunabe/lgo/cmd/lgo-internal")
   117  	cmd.Stderr = os.Stderr
   118  	cmd.Stdout = os.Stdout
   119  
   120  	if err := cmd.Run(); err != nil {
   121  		log.Fatalf("Failed to build lgo-internal: %v", err)
   122  	}
   123  	log.Printf("lgo was installed in %s successfully", root)
   124  }
   125  
   126  func InstallPkgMain() {
   127  	fSet := flag.NewFlagSet(os.Args[0]+" pkginstall", flag.ExitOnError)
   128  	// Ignore errors; fSet is set for ExitOnError.
   129  	fSet.Parse(os.Args[2:])
   130  
   131  	root := checkEnv("installpkg.log")
   132  
   133  	var args []string
   134  	ok := true
   135  	for _, arg := range fSet.Args() {
   136  		if install.IsStdPkg(arg) {
   137  			log.Printf("Can not install std packages: %v", arg)
   138  			ok = false
   139  		}
   140  		args = append(args, arg)
   141  	}
   142  	if !ok {
   143  		os.Exit(1)
   144  	}
   145  	if err := install.NewSOInstaller(root).Install(args...); err != nil {
   146  		log.Fatal(err)
   147  	}
   148  }