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 }