main.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package main
  2. import (
  3. "flag"
  4. "os"
  5. "os/exec"
  6. "path/filepath"
  7. "strings"
  8. _ "github.com/sagernet/gomobile"
  9. "github.com/sagernet/sing-box/cmd/internal/build_shared"
  10. "github.com/sagernet/sing-box/log"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. "github.com/sagernet/sing/common/rw"
  13. "github.com/sagernet/sing/common/shell"
  14. )
  15. var (
  16. debugEnabled bool
  17. target string
  18. platform string
  19. )
  20. func init() {
  21. flag.BoolVar(&debugEnabled, "debug", false, "enable debug")
  22. flag.StringVar(&target, "target", "android", "target platform")
  23. flag.StringVar(&platform, "platform", "", "specify platform")
  24. }
  25. func main() {
  26. flag.Parse()
  27. build_shared.FindMobile()
  28. switch target {
  29. case "android":
  30. buildAndroid()
  31. case "apple":
  32. buildApple()
  33. }
  34. }
  35. var (
  36. sharedFlags []string
  37. debugFlags []string
  38. sharedTags []string
  39. iosTags []string
  40. memcTags []string
  41. debugTags []string
  42. )
  43. func init() {
  44. sharedFlags = append(sharedFlags, "-trimpath")
  45. sharedFlags = append(sharedFlags, "-buildvcs=false")
  46. currentTag, err := build_shared.ReadTag()
  47. if err != nil {
  48. currentTag = "unknown"
  49. }
  50. sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
  51. debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
  52. sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_clash_api")
  53. iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")
  54. memcTags = append(memcTags, "with_tailscale")
  55. debugTags = append(debugTags, "debug")
  56. }
  57. func buildAndroid() {
  58. build_shared.FindSDK()
  59. var javaPath string
  60. javaHome := os.Getenv("JAVA_HOME")
  61. if javaHome == "" {
  62. javaPath = "java"
  63. } else {
  64. javaPath = filepath.Join(javaHome, "bin", "java")
  65. }
  66. javaVersion, err := shell.Exec(javaPath, "--version").ReadOutput()
  67. if err != nil {
  68. log.Fatal(E.Cause(err, "check java version"))
  69. }
  70. if !strings.Contains(javaVersion, "openjdk 17") {
  71. log.Fatal("java version should be openjdk 17")
  72. }
  73. var bindTarget string
  74. if platform != "" {
  75. bindTarget = platform
  76. } else if debugEnabled {
  77. bindTarget = "android/arm64"
  78. } else {
  79. bindTarget = "android"
  80. }
  81. args := []string{
  82. "bind",
  83. "-v",
  84. "-target", bindTarget,
  85. "-androidapi", "21",
  86. "-javapkg=io.nekohasekai",
  87. "-libname=box",
  88. }
  89. if !debugEnabled {
  90. args = append(args, sharedFlags...)
  91. } else {
  92. args = append(args, debugFlags...)
  93. }
  94. tags := append(sharedTags, memcTags...)
  95. if debugEnabled {
  96. tags = append(tags, debugTags...)
  97. }
  98. args = append(args, "-tags", strings.Join(tags, ","))
  99. args = append(args, "./experimental/libbox")
  100. command := exec.Command(build_shared.GoBinPath+"/gomobile", args...)
  101. command.Stdout = os.Stdout
  102. command.Stderr = os.Stderr
  103. err = command.Run()
  104. if err != nil {
  105. log.Fatal(err)
  106. }
  107. const name = "libbox.aar"
  108. copyPath := filepath.Join("..", "sing-box-for-android", "app", "libs")
  109. if rw.IsDir(copyPath) {
  110. copyPath, _ = filepath.Abs(copyPath)
  111. err = rw.CopyFile(name, filepath.Join(copyPath, name))
  112. if err != nil {
  113. log.Fatal(err)
  114. }
  115. log.Info("copied to ", copyPath)
  116. }
  117. }
  118. func buildApple() {
  119. var bindTarget string
  120. if platform != "" {
  121. bindTarget = platform
  122. } else if debugEnabled {
  123. bindTarget = "ios"
  124. } else {
  125. bindTarget = "ios,tvos,macos"
  126. }
  127. args := []string{
  128. "bind",
  129. "-v",
  130. "-target", bindTarget,
  131. "-libname=box",
  132. "-tags-macos=" + strings.Join(memcTags, ","),
  133. }
  134. if !debugEnabled {
  135. args = append(args, sharedFlags...)
  136. } else {
  137. args = append(args, debugFlags...)
  138. }
  139. tags := append(sharedTags, iosTags...)
  140. if debugEnabled {
  141. tags = append(tags, debugTags...)
  142. }
  143. args = append(args, "-tags", strings.Join(tags, ","))
  144. args = append(args, "./experimental/libbox")
  145. command := exec.Command(build_shared.GoBinPath+"/gomobile", args...)
  146. command.Stdout = os.Stdout
  147. command.Stderr = os.Stderr
  148. err := command.Run()
  149. if err != nil {
  150. log.Fatal(err)
  151. }
  152. copyPath := filepath.Join("..", "sing-box-for-apple")
  153. if rw.IsDir(copyPath) {
  154. targetDir := filepath.Join(copyPath, "Libbox.xcframework")
  155. targetDir, _ = filepath.Abs(targetDir)
  156. os.RemoveAll(targetDir)
  157. os.Rename("Libbox.xcframework", targetDir)
  158. log.Info("copied to ", targetDir)
  159. }
  160. }