sdk.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package build_shared
  2. import (
  3. "go/build"
  4. "os"
  5. "path/filepath"
  6. "runtime"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. "github.com/sagernet/sing-box/log"
  11. "github.com/sagernet/sing/common"
  12. E "github.com/sagernet/sing/common/exceptions"
  13. "github.com/sagernet/sing/common/rw"
  14. "github.com/sagernet/sing/common/shell"
  15. )
  16. var (
  17. androidSDKPath string
  18. androidNDKPath string
  19. )
  20. func FindSDK() {
  21. searchPath := []string{
  22. "$ANDROID_HOME",
  23. "$HOME/Android/Sdk",
  24. "$HOME/.local/lib/android/sdk",
  25. "$HOME/Library/Android/sdk",
  26. }
  27. for _, path := range searchPath {
  28. path = os.ExpandEnv(path)
  29. if rw.IsFile(filepath.Join(path, "licenses", "android-sdk-license")) {
  30. androidSDKPath = path
  31. break
  32. }
  33. }
  34. if androidSDKPath == "" {
  35. log.Fatal("android SDK not found")
  36. }
  37. if !findNDK() {
  38. log.Fatal("android NDK not found")
  39. }
  40. javaVersion, err := shell.Exec("java", "--version").ReadOutput()
  41. if err != nil {
  42. log.Fatal(E.Cause(err, "check java version"))
  43. }
  44. if !strings.Contains(javaVersion, "openjdk 17") {
  45. log.Fatal("java version should be openjdk 17")
  46. }
  47. os.Setenv("ANDROID_HOME", androidSDKPath)
  48. os.Setenv("ANDROID_SDK_HOME", androidSDKPath)
  49. os.Setenv("ANDROID_NDK_HOME", androidNDKPath)
  50. os.Setenv("NDK", androidNDKPath)
  51. os.Setenv("PATH", os.Getenv("PATH")+":"+filepath.Join(androidNDKPath, "toolchains", "llvm", "prebuilt", runtime.GOOS+"-x86_64", "bin"))
  52. }
  53. func findNDK() bool {
  54. const fixedVersion = "26.2.11394342"
  55. const versionFile = "source.properties"
  56. if fixedPath := filepath.Join(androidSDKPath, "ndk", fixedVersion); rw.IsFile(filepath.Join(fixedPath, versionFile)) {
  57. androidNDKPath = fixedPath
  58. return true
  59. }
  60. ndkVersions, err := os.ReadDir(filepath.Join(androidSDKPath, "ndk"))
  61. if err != nil {
  62. return false
  63. }
  64. versionNames := common.Map(ndkVersions, os.DirEntry.Name)
  65. if len(versionNames) == 0 {
  66. return false
  67. }
  68. sort.Slice(versionNames, func(i, j int) bool {
  69. iVersions := strings.Split(versionNames[i], ".")
  70. jVersions := strings.Split(versionNames[j], ".")
  71. for k := 0; k < len(iVersions) && k < len(jVersions); k++ {
  72. iVersion, _ := strconv.Atoi(iVersions[k])
  73. jVersion, _ := strconv.Atoi(jVersions[k])
  74. if iVersion != jVersion {
  75. return iVersion > jVersion
  76. }
  77. }
  78. return true
  79. })
  80. for _, versionName := range versionNames {
  81. currentNDKPath := filepath.Join(androidSDKPath, "ndk", versionName)
  82. if rw.IsFile(filepath.Join(androidSDKPath, versionFile)) {
  83. androidNDKPath = currentNDKPath
  84. log.Warn("reproducibility warning: using NDK version " + versionName + " instead of " + fixedVersion)
  85. return true
  86. }
  87. }
  88. return false
  89. }
  90. var GoBinPath string
  91. func FindMobile() {
  92. goBin := filepath.Join(build.Default.GOPATH, "bin")
  93. if runtime.GOOS == "windows" {
  94. if !rw.IsFile(filepath.Join(goBin, "gobind.exe")) {
  95. log.Fatal("missing gomobile installation")
  96. }
  97. } else {
  98. if !rw.IsFile(filepath.Join(goBin, "gobind")) {
  99. log.Fatal("missing gomobile installation")
  100. }
  101. }
  102. GoBinPath = goBin
  103. }