main.go 4.2 KB

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