|
|
@@ -0,0 +1,238 @@
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "flag"
|
|
|
+ "fmt"
|
|
|
+ "io/ioutil"
|
|
|
+ "os"
|
|
|
+ "os/exec"
|
|
|
+ "path/filepath"
|
|
|
+ "runtime"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ targetOS = flag.String("os", runtime.GOOS, "Target OS of this build.")
|
|
|
+ targetArch = flag.String("arch", runtime.GOARCH, "Target CPU arch of this build.")
|
|
|
+ archive = flag.Bool("zip", false, "Whether to make an archive of files or not.")
|
|
|
+
|
|
|
+ GOPATH string
|
|
|
+ repoRoot string
|
|
|
+)
|
|
|
+
|
|
|
+type OS string
|
|
|
+
|
|
|
+const (
|
|
|
+ Windows = OS("windows")
|
|
|
+ MacOS = OS("darwin")
|
|
|
+ Linux = OS("linux")
|
|
|
+)
|
|
|
+
|
|
|
+type Architecture string
|
|
|
+
|
|
|
+const (
|
|
|
+ X86 = Architecture("386")
|
|
|
+ Amd64 = Architecture("amd64")
|
|
|
+ Arm = Architecture("arm")
|
|
|
+ Arm64 = Architecture("arm64")
|
|
|
+)
|
|
|
+
|
|
|
+func getRepoVersion() (string, error) {
|
|
|
+ revHead, err := exec.Command("git", "rev-parse", "HEAD").Output()
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ version, err := exec.Command("git", "name-rev", "--tags", "--name-only", strings.TrimSpace(string(revHead))).Output()
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ verStr := strings.TrimSpace(string(version))
|
|
|
+ if strings.HasSuffix(verStr, "^0") {
|
|
|
+ verStr = verStr[:len(verStr)-2]
|
|
|
+ }
|
|
|
+ if verStr == "undefined" {
|
|
|
+ verStr = "custom"
|
|
|
+ }
|
|
|
+ return verStr, nil
|
|
|
+}
|
|
|
+
|
|
|
+func getOS() OS {
|
|
|
+ if targetOS == nil {
|
|
|
+ panic("OS is not specified.")
|
|
|
+ }
|
|
|
+ osStr := strings.ToLower(*targetOS)
|
|
|
+ if osStr == "windows" || osStr == "win" {
|
|
|
+ return Windows
|
|
|
+ }
|
|
|
+ if osStr == "darwin" || osStr == "mac" || osStr == "macos" || osStr == "osx" {
|
|
|
+ return MacOS
|
|
|
+ }
|
|
|
+ if osStr == "linux" || osStr == "debian" || osStr == "ubuntu" || osStr == "redhat" || osStr == "centos" {
|
|
|
+ return Linux
|
|
|
+ }
|
|
|
+ panic("Unknown OS " + *targetOS)
|
|
|
+}
|
|
|
+
|
|
|
+func getArch() Architecture {
|
|
|
+ if targetArch == nil {
|
|
|
+ panic("Arch is not specified.")
|
|
|
+ }
|
|
|
+ archStr := strings.ToLower(*targetArch)
|
|
|
+ if archStr == "x86" || archStr == "386" || archStr == "i386" {
|
|
|
+ return X86
|
|
|
+ }
|
|
|
+ if archStr == "amd64" || archStr == "x86-64" || archStr == "x64" {
|
|
|
+ return Amd64
|
|
|
+ }
|
|
|
+ if archStr == "arm" {
|
|
|
+ return Arm
|
|
|
+ }
|
|
|
+ if archStr == "arm64" {
|
|
|
+ return Arm64
|
|
|
+ }
|
|
|
+ panic("Unknown Arch " + *targetArch)
|
|
|
+}
|
|
|
+
|
|
|
+func getSuffix(vos OS, arch Architecture) string {
|
|
|
+ suffix := "-custom"
|
|
|
+ switch vos {
|
|
|
+ case Windows:
|
|
|
+ switch arch {
|
|
|
+ case X86:
|
|
|
+ suffix = "-windows-32"
|
|
|
+ case Amd64:
|
|
|
+ suffix = "-windows-64"
|
|
|
+ }
|
|
|
+ case MacOS:
|
|
|
+ suffix = "-macos"
|
|
|
+ case Linux:
|
|
|
+ switch arch {
|
|
|
+ case X86:
|
|
|
+ suffix = "-linux-32"
|
|
|
+ case Amd64:
|
|
|
+ suffix = "-linux-64"
|
|
|
+ case Arm:
|
|
|
+ suffix = "-linux-arm"
|
|
|
+ case Arm64:
|
|
|
+ suffix = "-linux-arm64"
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return suffix
|
|
|
+}
|
|
|
+
|
|
|
+func createTargetDirectory(version string, vos OS, arch Architecture) (string, error) {
|
|
|
+ suffix := "-custom"
|
|
|
+ if version != "custom" {
|
|
|
+ suffix = getSuffix(vos, arch)
|
|
|
+ }
|
|
|
+ targetDir := filepath.Join(GOPATH, "bin", "v2ray"+suffix)
|
|
|
+ if version != "custom" {
|
|
|
+ os.RemoveAll(targetDir)
|
|
|
+ }
|
|
|
+ err := os.MkdirAll(targetDir, os.ModeDir|0777)
|
|
|
+ return targetDir, err
|
|
|
+}
|
|
|
+
|
|
|
+func getTargetFile(vos OS, arch Architecture) string {
|
|
|
+ suffix := getSuffix(vos, arch)
|
|
|
+ if vos == "Windows" {
|
|
|
+ suffix += ".exe"
|
|
|
+ }
|
|
|
+ return "v2ray" + suffix
|
|
|
+}
|
|
|
+
|
|
|
+func normalizedContent(content []byte, vos OS) []byte {
|
|
|
+ str := strings.Replace(string(content), "\r\n", "\n", -1)
|
|
|
+ if vos == Windows {
|
|
|
+ str = strings.Replace(str, "\n", "\r\n", -1)
|
|
|
+ }
|
|
|
+ return []byte(str)
|
|
|
+}
|
|
|
+
|
|
|
+func copyConfigFiles(dir string, version string, vos OS, arch Architecture) error {
|
|
|
+ clientConfig, err := ioutil.ReadFile(filepath.Join(repoRoot, "release", "config", "vpoint_socks_vmess.json"))
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ clientConfig = normalizedContent(clientConfig, vos)
|
|
|
+ clientConfigName := "vpoint_socks_vmess.json"
|
|
|
+ if vos == Windows || vos == MacOS {
|
|
|
+ clientConfigName = "config.json"
|
|
|
+ }
|
|
|
+ err = ioutil.WriteFile(filepath.Join(dir, clientConfigName), clientConfig, 0777)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ if vos == Windows || vos == MacOS {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ serverConfig, err := ioutil.ReadFile(filepath.Join(repoRoot, "release", "config", "vpoint_vmess_freedom.json"))
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ serverConfig = normalizedContent(serverConfig, vos)
|
|
|
+ err = ioutil.WriteFile(filepath.Join(dir, "vpoint_vmess_freedom.json"), serverConfig, 0777)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func buildV2Ray(targetDir, targetFile string, version string, vos OS, arch Architecture) error {
|
|
|
+ ldFlags := "-s"
|
|
|
+ if version != "custom" {
|
|
|
+ year, month, day := time.Now().UTC().Date()
|
|
|
+ today := fmt.Sprintf("%04d%02d%02d", year, int(month), day)
|
|
|
+ ldFlags = ldFlags + " -X github.com/v2ray/v2ray-core.version=" + version + " -X github.com/v2ray/v2ray-core.build=" + today
|
|
|
+ }
|
|
|
+ target := filepath.Join(targetDir, targetFile)
|
|
|
+ fmt.Println("Building to " + target)
|
|
|
+ cmd := exec.Command("go", "build", "-o", target, "-compiler", "gc", "-ldflags", "\""+ldFlags+"\"", "github.com/v2ray/v2ray-core/release/server")
|
|
|
+ cmd.Env = append(cmd.Env, "GOOS="+string(vos), "GOARCH="+string(arch))
|
|
|
+ cmd.Env = append(cmd.Env, os.Environ()...)
|
|
|
+ _, err := cmd.Output()
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
+func main() {
|
|
|
+ flag.Parse()
|
|
|
+
|
|
|
+ v2rayOS := getOS()
|
|
|
+ v2rayArch := getArch()
|
|
|
+
|
|
|
+ if err := os.Chdir(repoRoot); err != nil {
|
|
|
+ fmt.Println("Unable to switch to V2Ray repo: " + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ version, err := getRepoVersion()
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Unable to detect V2Ray version: " + err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ fmt.Printf("Building V2Ray (%s) for %s %s\n", version, v2rayOS, v2rayArch)
|
|
|
+
|
|
|
+ targetDir, err := createTargetDirectory(version, v2rayOS, v2rayArch)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Unable to create directory " + targetDir + ": " + err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
+ targetFile := getTargetFile(v2rayOS, v2rayArch)
|
|
|
+ err = buildV2Ray(targetDir, targetFile, version, v2rayOS, v2rayArch)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Unable to build V2Ray: " + err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
+ err = copyConfigFiles(targetDir, version, v2rayOS, v2rayArch)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Unable to copy config files: " + err.Error())
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func init() {
|
|
|
+ GOPATH = os.Getenv("GOPATH")
|
|
|
+ repoRoot = filepath.Join(GOPATH, "src", "github.com", "v2ray", "v2ray-core")
|
|
|
+}
|