Files
T
nyaKazuhaandClaude Fable 5 962261ba12 fix(ffi): 统一 cgo 链接与 release 构建 profile
internal/ffi/ffi.go 的 cgo LDFLAGS 硬编码 -L target/debug,而 build-rust 用
--release(产物落 target/release),干净环境下 make build/test-go/ci 必然
报 cannot find -lbat_ffi。

- LDFLAGS 指向 target/release,并加 -Wl,-rpath 让产物运行时无需 LD_LIBRARY_PATH
  即可定位 libbat_ffi.so;删除指向不存在目录的无效 CFLAGS -I(C 声明本就内联)。
- 新增 build-ffi target(cargo build --release -p bat-ffi),build-go 与 test-go
  依赖它,确保链接前 release FFI 库已存在。

验证:make build-go 成功产出并可运行 bin/bat;make test-go 链接并通过;
go vet(check-go)通过。

对应 issue #18 维护清单 1-6。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:46:37 -07:00

65 lines
2.0 KiB
Go

// Package ffi is an optional CGO compatibility wrapper around bat-ffi.
//
// It is not the primary Go integration path. Product CLI orchestration should
// prefer the Rust bat process boundary with --json output, or a future stable
// SDK. Keep this package stateless and limited to coarse JSON helper calls.
package ffi
/*
// Links against the release bat-ffi library built by `cargo build --release -p bat-ffi`
// (see the `build-ffi` Make target). The rpath lets the resulting binary locate
// libbat_ffi.so at runtime without setting LD_LIBRARY_PATH during local development.
#cgo LDFLAGS: -L${SRCDIR}/../../target/release -lbat_ffi -Wl,-rpath,${SRCDIR}/../../target/release
#include <stdlib.h>
typedef char* ccharp;
extern const char* bat_version();
extern void bat_free_string(char* s);
extern char* bat_manifest_inspect_json(const char* raw_json);
extern char* bat_sync_plan_json(const char* current_json, const char* previous_json);
*/
import "C"
import (
"errors"
"unsafe"
)
func Version() (string, error) {
ptr := C.bat_version()
if ptr == nil {
return "", errors.New("bat_version returned nil")
}
defer C.bat_free_string((*C.char)(unsafe.Pointer(ptr)))
return C.GoString(ptr), nil
}
func InspectManifest(rawJSON string) (string, error) {
cRaw := C.CString(rawJSON)
defer C.free(unsafe.Pointer(cRaw))
ptr := C.bat_manifest_inspect_json(cRaw)
if ptr == nil {
return "", errors.New("bat_manifest_inspect_json returned nil")
}
defer C.bat_free_string((*C.char)(unsafe.Pointer(ptr)))
return C.GoString(ptr), nil
}
func BuildSyncPlan(currentJSON, previousJSON string) (string, error) {
cCurrent := C.CString(currentJSON)
defer C.free(unsafe.Pointer(cCurrent))
var cPrevious *C.char
if previousJSON != "" {
cPrevious = C.CString(previousJSON)
defer C.free(unsafe.Pointer(cPrevious))
}
ptr := C.bat_sync_plan_json(cCurrent, cPrevious)
if ptr == nil {
return "", errors.New("bat_sync_plan_json returned nil")
}
defer C.bat_free_string((*C.char)(unsafe.Pointer(ptr)))
return C.GoString(ptr), nil
}