From 98af3c0ad63ec4add436d16c21554b3b8b8a70f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Mon, 9 Feb 2026 13:33:15 +0800 Subject: [PATCH] experimental: New FFI --- Makefile | 14 +- cmd/internal/build_libbox_newffi/main.go | 93 +++++++++++++ experimental/libbox/ffi.json | 167 +++++++++++++++++++++++ 3 files changed, 265 insertions(+), 9 deletions(-) create mode 100644 cmd/internal/build_libbox_newffi/main.go create mode 100644 experimental/libbox/ffi.json diff --git a/Makefile b/Makefile index 5f1408b8..b94af10c 100644 --- a/Makefile +++ b/Makefile @@ -206,7 +206,7 @@ update_apple_version: update_macos_version: MACOS_PROJECT_VERSION=$(shell go run -v ./cmd/internal/app_store_connect next_macos_project_version) go run ./cmd/internal/update_apple_version -release_apple: lib_ios update_apple_version release_ios release_macos release_tvos release_macos_standalone +release_apple: lib_apple update_apple_version release_ios release_macos release_tvos release_macos_standalone release_apple_beta: update_apple_version release_ios release_macos release_tvos @@ -234,18 +234,14 @@ test_stdio: lib_android: go run ./cmd/internal/build_libbox -target android -lib_android_debug: - go run ./cmd/internal/build_libbox -target android -debug - lib_apple: go run ./cmd/internal/build_libbox -target apple -lib_ios: - go run ./cmd/internal/build_libbox -target apple -platform ios -debug +lib_android_new: + go run ./cmd/internal/build_libbox_newffi -target android -lib: - go run ./cmd/internal/build_libbox -target android - go run ./cmd/internal/build_libbox -target ios +lib_apple_new: + go run ./cmd/internal/build_libbox_newffi -target apple lib_install: go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.11 diff --git a/cmd/internal/build_libbox_newffi/main.go b/cmd/internal/build_libbox_newffi/main.go new file mode 100644 index 00000000..4df1d465 --- /dev/null +++ b/cmd/internal/build_libbox_newffi/main.go @@ -0,0 +1,93 @@ +package main + +import ( + "flag" + "os" + "os/exec" + "path/filepath" + + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing/common/rw" +) + +var target string + +func init() { + flag.StringVar(&target, "target", "android", "target platform (android or apple)") +} + +func main() { + flag.Parse() + + args := []string{ + "generate", + "-v", + "--config", "experimental/libbox/ffi.json", + "--platform-type", target, + } + command := exec.Command("sing-ffi", args...) + command.Stdout = os.Stdout + command.Stderr = os.Stderr + err := command.Run() + if err != nil { + log.Fatal(err) + } + + copyArtifacts(target) +} + +func copyArtifacts(target string) { + switch target { + case "android": + copyPath := filepath.Join("..", "sing-box-for-android", "app", "libs") + if rw.IsDir(copyPath) { + copyPath, _ = filepath.Abs(copyPath) + for _, name := range []string{"libbox.aar", "libbox-legacy.aar"} { + artifactPath, found := findArtifactPath(name) + if !found { + continue + } + targetPath := filepath.Join(target, artifactPath) + os.RemoveAll(targetPath) + err := os.Rename(artifactPath, targetPath) + if err != nil { + log.Fatal(err) + } + log.Info("copied ", name, " to ", copyPath) + } + } + case "apple": + copyPath := filepath.Join("..", "sing-box-for-apple") + if rw.IsDir(copyPath) { + sourceDir, found := findArtifactPath("Libbox.xcframework") + if !found { + log.Fatal("Libbox.xcframework not found in current directory or experimental/libbox") + } + + targetDir := filepath.Join(copyPath, "Libbox.xcframework") + targetDir, _ = filepath.Abs(targetDir) + err := os.RemoveAll(targetDir) + if err != nil { + log.Fatal(err) + } + err = os.Rename(sourceDir, targetDir) + if err != nil { + log.Fatal(err) + } + log.Info("copied ", sourceDir, " to ", targetDir) + } + } +} + +func findArtifactPath(name string) (string, bool) { + candidates := []string{ + name, + filepath.Join("experimental", "libbox", name), + } + for _, candidate := range candidates { + if rw.IsFile(candidate) || rw.IsDir(candidate) { + return candidate, true + } + } + return "", false +} diff --git a/experimental/libbox/ffi.json b/experimental/libbox/ffi.json new file mode 100644 index 00000000..5c5c72d5 --- /dev/null +++ b/experimental/libbox/ffi.json @@ -0,0 +1,167 @@ +{ + "version": 1, + "packages": [ + { + "id": "libbox", + "path": ".", + "java_package": "io.nekohasekai.libbox", + "apple_prefix": "Libbox" + } + ], + "builds": [ + { + "id": "android-main", + "packages": ["libbox"], + "default": { + "tags": [ + "with_gvisor", + "with_quic", + "with_wireguard", + "with_utls", + "with_naive_outbound", + "with_clash_api", + "with_conntrack", + "badlinkname", + "tfogo_checklinkname0", + "with_tailscale", + "ts_omit_logtail", + "ts_omit_ssh", + "ts_omit_drive", + "ts_omit_taildrop", + "ts_omit_webclient", + "ts_omit_doctor", + "ts_omit_capture", + "ts_omit_kube", + "ts_omit_aws", + "ts_omit_synology", + "ts_omit_bird" + ], + "ldflags": "-X github.com/sagernet/sing-box/constant.Version=$(CGO_ENABLED=0 go run github.com/sagernet/sing-box/cmd/internal/read_tag@latest) -X internal/godebug.defaultGODEBUG=multipathtcp=0 -s -w -buildid= -checklinkname=0", + "trimpath": true + } + }, + { + "id": "android-legacy", + "packages": ["libbox"], + "default": { + "tags": [ + "with_gvisor", + "with_quic", + "with_wireguard", + "with_utls", + "with_clash_api", + "with_conntrack", + "badlinkname", + "tfogo_checklinkname0", + "with_tailscale", + "ts_omit_logtail", + "ts_omit_ssh", + "ts_omit_drive", + "ts_omit_taildrop", + "ts_omit_webclient", + "ts_omit_doctor", + "ts_omit_capture", + "ts_omit_kube", + "ts_omit_aws", + "ts_omit_synology", + "ts_omit_bird" + ], + "ldflags": "-X github.com/sagernet/sing-box/constant.Version=$(CGO_ENABLED=0 go run github.com/sagernet/sing-box/cmd/internal/read_tag@latest) -X internal/godebug.defaultGODEBUG=multipathtcp=0 -s -w -buildid= -checklinkname=0", + "trimpath": true + } + }, + { + "id": "apple", + "packages": ["libbox"], + "default": { + "tags": [ + "with_gvisor", + "with_quic", + "with_wireguard", + "with_utls", + "with_naive_outbound", + "with_clash_api", + "with_conntrack", + "badlinkname", + "tfogo_checklinkname0", + "with_dhcp", + "grpcnotrace", + "with_tailscale", + "ts_omit_logtail", + "ts_omit_ssh", + "ts_omit_drive", + "ts_omit_taildrop", + "ts_omit_webclient", + "ts_omit_doctor", + "ts_omit_capture", + "ts_omit_kube", + "ts_omit_aws", + "ts_omit_synology", + "ts_omit_bird" + ], + "ldflags": "-X github.com/sagernet/sing-box/constant.Version=$(CGO_ENABLED=0 go run github.com/sagernet/sing-box/cmd/internal/read_tag@latest) -X internal/godebug.defaultGODEBUG=multipathtcp=0 -s -w -buildid= -checklinkname=0", + "trimpath": true + }, + "overrides": [ + { + "match": { "os": "ios" }, + "tags_append": ["with_low_memory"] + }, + { + "match": { "os": "tvos" }, + "tags_append": ["with_low_memory"] + } + ] + } + ], + "platforms": [ + { + "type": "android", + "build": "android-main", + "min_sdk": 23, + "lib_name": "box", + "languages": [{ "type": "java" }], + "artifacts": [ + { + "type": "aar", + "output_path": "libbox.aar" + } + ] + }, + { + "type": "android", + "build": "android-legacy", + "min_sdk": 21, + "lib_name": "box", + "languages": [{ "type": "java" }], + "artifacts": [ + { + "type": "aar", + "output_path": "libbox-legacy.aar" + } + ] + }, + { + "type": "apple", + "build": "apple", + "targets": [ + "ios/arm64", + "ios/simulator/arm64", + "ios/simulator/amd64", + "tvos/arm64", + "tvos/simulator/arm64", + "tvos/simulator/amd64", + "macos/arm64", + "macos/amd64" + ], + "languages": [{ "type": "objc" }], + "artifacts": [ + { + "type": "xcframework", + "module_name": "Libbox", + "output_path": "Libbox.xcframework" + } + ] + } + ] +}