main.go 4.6 KB

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