main.go 4.4 KB

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