logo
0
0
WeChat Login
docs: 添加静态库构建说明和实现

onnxruntime_go 跨平台 ONNX Runtime Go 封装库(支持加密模型)

Go Reference

概述

本库提供了使用 Microsoft onnxruntime 加载和执行 ONNX 神经网络的 Go 接口。在原版 yalue/onnxruntime_go 基础上扩展了:

  • 加密模型支持 - AES-256-GCM 加密保护模型
  • 授权集成 - 与 machineid/cert 集成实现企业授权
  • 机器绑定 - 从机器 ID 派生加密密钥,实现硬件锁定

特性

  • 跨平台支持(Windows、Linux、macOS)
  • 多执行提供程序(CUDA、TensorRT、CoreML、DirectML、OpenVINO)
  • 基于 Go 泛型的张量支持
  • 动态和静态会话模式
  • 模型加密和解密
  • 基于授权的模型访问控制

安装

go get cnb.cool/svn/onnxruntime

还需要下载对应平台的 ONNX Runtime 共享库,从 onnxruntime releases 获取。

快速开始

基础推理

package main import ( "fmt" ort "cnb.cool/svn/onnxruntime" ) func main() { // 设置库路径 ort.SetSharedLibraryPath("/path/to/libonnxruntime.so") // 初始化环境 if err := ort.InitializeEnvironment(); err != nil { panic(err) } defer ort.DestroyEnvironment() // 创建输入张量 inputShape := ort.NewShape(1, 3, 224, 224) inputData := make([]float32, inputShape.FlattenedSize()) inputTensor, _ := ort.NewTensor(inputShape, inputData) defer inputTensor.Destroy() // 创建输出张量 outputShape := ort.NewShape(1, 1000) outputTensor, _ := ort.NewEmptyTensor[float32](outputShape) defer outputTensor.Destroy() // 创建会话并运行 session, _ := ort.NewAdvancedSession("model.onnx", []string{"input"}, []string{"output"}, []ort.Value{inputTensor}, []ort.Value{outputTensor}, nil) defer session.Destroy() session.Run() result := outputTensor.GetData() fmt.Println("结果:", result[:10]) }

加密模型推理

package main import ( ort "cnb.cool/svn/onnxruntime" ) func main() { ort.SetSharedLibraryPath("/path/to/libonnxruntime.so") ort.InitializeEnvironment() defer ort.DestroyEnvironment() // 加密密钥(AES-256 需要 32 字节) key := []byte("your-32-byte-secret-key-here!!") // 加密模型(一次性操作) ort.EncryptModel("model.onnx", "model.onnx.enc", key) // 从加密文件获取模型信息 inputs, outputs, _ := ort.GetInputOutputInfoFromEncryptedFile("model.onnx.enc", key) // 从加密模型创建会话 session, _ := ort.NewDynamicAdvancedSessionFromEncryptedFile( "model.onnx.enc", key, []string{inputs[0].Name}, []string{outputs[0].Name}, nil) defer session.Destroy() // 执行推理... }

机器绑定加密模型

package main import ( "github.com/darkit/machineid" ort "cnb.cool/svn/onnxruntime" ) func main() { ort.SetSharedLibraryPath("/path/to/libonnxruntime.so") ort.InitializeEnvironment() defer ort.DestroyEnvironment() // 获取机器 ID machineID, _ := machineid.ID() moduleName := "ai.model.classifier" salt := []byte("app-specific-salt") // 为当前机器加密模型 ort.EncryptModelForMachine("model.onnx", "model.onnx.enc", machineID, moduleName, salt) // 派生密钥并创建会话 key := ort.DeriveModelKey(machineID, moduleName, salt) session, _ := ort.NewDynamicAdvancedSessionFromEncryptedFile( "model.onnx.enc", key, inputNames, outputNames, nil) defer session.Destroy() }

API 参考

环境管理

SetSharedLibraryPath

func SetSharedLibraryPath(path string)

设置 ONNX Runtime 共享库路径。必须在 InitializeEnvironment() 之前调用。

InitializeEnvironment

func InitializeEnvironment(opts ...EnvironmentOption) error

初始化 ONNX Runtime 环境。必须在创建任何会话之前调用。

选项:

  • WithLogLevelVerbose() - 启用详细日志
  • WithLogLevelInfo() - 启用信息日志
  • WithLogLevelWarning() - 启用警告日志(默认)
  • WithLogLevelError() - 仅启用错误日志
  • WithLogLevelFatal() - 仅启用致命错误日志

DestroyEnvironment

func DestroyEnvironment() error

清理 ONNX Runtime 环境。使用完毕后应调用此函数。

IsInitialized

func IsInitialized() bool

返回环境是否已初始化。

GetVersion

func GetVersion() string

返回 ONNX Runtime 版本字符串。

DisableTelemetry / EnableTelemetry

func DisableTelemetry() error func EnableTelemetry() error

控制 ONNX Runtime 遥测数据收集。

SetEnvironmentLogLevel

func SetEnvironmentLogLevel(level LoggingLevel) error

设置环境日志级别。


形状 (Shape)

NewShape

func NewShape(dimensions ...int64) Shape

从给定维度创建新的张量形状。

Shape 方法

func (s Shape) FlattenedSize() int64 // 元素总数 func (s Shape) Validate() error // 验证维度为正数 func (s Shape) Clone() Shape // 创建副本 func (s Shape) String() string // 字符串表示 func (s Shape) Equals(other Shape) bool // 比较两个形状

张量类型

Tensor[T]

数值数据类型的泛型张量。

func NewTensor[T TensorData](s Shape, data []T) (*Tensor[T], error) func NewEmptyTensor[T TensorData](s Shape) (*Tensor[T], error)

支持的类型 (TensorData):

  • float32, float64
  • int8, int16, int32, int64
  • uint8, uint16, uint32, uint64

方法:

func (t *Tensor[T]) GetData() []T // 获取底层数据切片 func (t *Tensor[T]) GetShape() Shape // 获取张量形状 func (t *Tensor[T]) Clone() (*Tensor[T], error) // 创建副本 func (t *Tensor[T]) ZeroContents() // 清零所有元素 func (t *Tensor[T]) Destroy() error // 释放资源 func (t *Tensor[T]) GetONNXType() ONNXType // 返回 ONNXTypeTensor func (t *Tensor[T]) DataType() ONNXTensorElementDataType

Scalar[T]

单值张量(0 维)。

func NewScalar[T TensorData](data T) (*Scalar[T], error) func NewEmptyScalar[T TensorData]() (*Scalar[T], error)

方法:

func (s *Scalar[T]) GetData() T // 获取标量值 func (s *Scalar[T]) Set(value T) // 设置标量值 func (s *Scalar[T]) Destroy() error

StringTensor

包含字符串数据的张量。

func NewStringTensor(shape Shape) (*StringTensor, error)

方法:

func (t *StringTensor) SetContents(contents []string) error func (t *StringTensor) GetContents() ([]string, error) func (t *StringTensor) SetElement(index int64, s string) error func (t *StringTensor) GetElement(index int64) (string, error) func (t *StringTensor) Destroy() error

CustomDataTensor

自定义二进制数据和元素类型的张量。

func NewCustomDataTensor(s Shape, data []byte, dataType TensorElementDataType) (*CustomDataTensor, error)

方法:

func (t *CustomDataTensor) GetData() []byte func (t *CustomDataTensor) Destroy() error

容器类型

Sequence

ONNX 序列容器。

func NewSequence(contents []Value) (*Sequence, error)

方法:

func (s *Sequence) GetValues() ([]Value, error) func (s *Sequence) Destroy() error

Map

ONNX 映射容器。

func NewMap(keys, values Value) (*Map, error) func NewMapFromGoMap[K, V TensorData](m map[K]V) (*Map, error)

方法:

func (m *Map) GetKeysAndValues() (Value, Value, error) func (m *Map) Destroy() error

会话

AdvancedSession

预绑定输入/输出张量的静态会话。

func NewAdvancedSession(onnxFilePath string, inputNames, outputNames []string, inputs, outputs []Value, options *SessionOptions) (*AdvancedSession, error) func NewAdvancedSessionWithONNXData(onnxData []byte, inputNames, outputNames []string, inputs, outputs []Value, options *SessionOptions) (*AdvancedSession, error)

方法:

func (s *AdvancedSession) Run() error func (s *AdvancedSession) RunWithOptions(opts *RunOptions) error func (s *AdvancedSession) GetModelMetadata() (*ModelMetadata, error) func (s *AdvancedSession) Destroy() error

DynamicAdvancedSession

运行时指定输入/输出的动态会话。

func NewDynamicAdvancedSession(onnxFilePath string, inputNames, outputNames []string, options *SessionOptions) (*DynamicAdvancedSession, error) func NewDynamicAdvancedSessionWithONNXData(onnxData []byte, inputNames, outputNames []string, options *SessionOptions) (*DynamicAdvancedSession, error)

方法:

func (s *DynamicAdvancedSession) Run(inputs, outputs []Value) error func (s *DynamicAdvancedSession) RunWithOptions(inputs, outputs []Value, opts *RunOptions) error func (s *DynamicAdvancedSession) RunWithBinding(b *IoBinding) error func (s *DynamicAdvancedSession) CreateIoBinding() (*IoBinding, error) func (s *DynamicAdvancedSession) GetModelMetadata() (*ModelMetadata, error) func (s *DynamicAdvancedSession) Destroy() error

IoBinding

用于优化内存管理的 I/O 绑定。

func (s *DynamicAdvancedSession) CreateIoBinding() (*IoBinding, error)

方法:

func (b *IoBinding) BindInput(name string, value Value) error func (b *IoBinding) BindOutput(name string, value Value) error func (b *IoBinding) GetBoundOutputNames() ([]string, error) func (b *IoBinding) GetBoundOutputValues() ([]Value, error) func (b *IoBinding) ClearBoundInputs() func (b *IoBinding) ClearBoundOutputs() func (b *IoBinding) Destroy() error

会话选项

SessionOptions

func NewSessionOptions() (*SessionOptions, error)

方法:

// 执行配置 func (o *SessionOptions) SetExecutionMode(mode ExecutionMode) error func (o *SessionOptions) SetGraphOptimizationLevel(level GraphOptimizationLevel) error func (o *SessionOptions) SetLogSeverityLevel(level LoggingLevel) error func (o *SessionOptions) SetIntraOpNumThreads(n int) error func (o *SessionOptions) SetInterOpNumThreads(n int) error func (o *SessionOptions) SetCpuMemArena(isEnabled bool) error func (o *SessionOptions) SetMemPattern(isEnabled bool) error // 会话配置项 func (o *SessionOptions) HasSessionConfigEntry(key string) (bool, error) func (o *SessionOptions) GetSessionConfigEntry(key string) (string, error) func (o *SessionOptions) AddSessionConfigEntry(key, value string) error // 执行提供程序 func (o *SessionOptions) AppendExecutionProviderCUDA(cudaOptions *CUDAProviderOptions) error func (o *SessionOptions) AppendExecutionProviderTensorRT(tensorrtOptions *TensorRTProviderOptions) error func (o *SessionOptions) AppendExecutionProviderCoreML(flags uint32) error func (o *SessionOptions) AppendExecutionProviderCoreMLV2(options map[string]string) error func (o *SessionOptions) AppendExecutionProviderDirectML(deviceID int) error func (o *SessionOptions) AppendExecutionProviderOpenVINO(options map[string]string) error func (o *SessionOptions) AppendExecutionProvider(providerName string, options map[string]string) error func (o *SessionOptions) Destroy() error

ExecutionMode(执行模式):

  • ExecutionModeSequential - 顺序执行
  • ExecutionModeParallel - 并行执行

GraphOptimizationLevel(图优化级别):

  • GraphOptLevelDisableAll - 无优化
  • GraphOptLevelBasic - 基础优化
  • GraphOptLevelExtended - 扩展优化
  • GraphOptLevelAll - 全部优化

RunOptions

func NewRunOptions() (*RunOptions, error)

方法:

func (o *RunOptions) Terminate() error // 请求终止 func (o *RunOptions) UnsetTerminate() error // 清除终止标志 func (o *RunOptions) Destroy() error

执行提供程序

CUDAProviderOptions

func NewCUDAProviderOptions() (*CUDAProviderOptions, error)

方法:

func (o *CUDAProviderOptions) Update(options map[string]string) error func (o *CUDAProviderOptions) Destroy() error

常用选项:

  • "device_id" - GPU 设备 ID
  • "gpu_mem_limit" - 内存限制(字节)
  • "arena_extend_strategy" - 内存分配策略

TensorRTProviderOptions

func NewTensorRTProviderOptions() (*TensorRTProviderOptions, error)

方法:

func (o *TensorRTProviderOptions) Update(options map[string]string) error func (o *TensorRTProviderOptions) Destroy() error

常用选项:

  • "device_id" - GPU 设备 ID
  • "trt_max_workspace_size" - 最大工作空间大小
  • "trt_fp16_enable" - 启用 FP16 精度
  • "trt_int8_enable" - 启用 INT8 精度

模型信息

GetInputOutputInfo

func GetInputOutputInfo(path string) ([]InputOutputInfo, []InputOutputInfo, error) func GetInputOutputInfoWithOptions(path string, options *SessionOptions) ([]InputOutputInfo, []InputOutputInfo, error) func GetInputOutputInfoWithONNXData(data []byte) ([]InputOutputInfo, []InputOutputInfo, error)

返回模型的输入和输出张量信息。

InputOutputInfo

type InputOutputInfo struct { Name string DataType TensorElementDataType Dimensions []int64 } func (n *InputOutputInfo) String() string

GetModelMetadata

func GetModelMetadata(path string) (*ModelMetadata, error)

ModelMetadata 方法

func (m *ModelMetadata) GetProducerName() (string, error) func (m *ModelMetadata) GetGraphName() (string, error) func (m *ModelMetadata) GetDomain() (string, error) func (m *ModelMetadata) GetDescription() (string, error) func (m *ModelMetadata) GetVersion() (int64, error) func (m *ModelMetadata) GetCustomMetadataMapKeys() ([]string, error) func (m *ModelMetadata) LookupCustomMetadataMap(key string) (string, bool, error) func (m *ModelMetadata) Destroy() error

模型加密

基础加密

// 加密模型文件 func EncryptModel(inputPath, outputPath string, key []byte) error // 解密模型文件 func DecryptModel(inputPath, outputPath string, key []byte) error // 在内存中加密模型数据 func EncryptModelData(plaintext, key []byte) ([]byte, error) // 在内存中解密模型数据 func DecryptModelData(data, key []byte) ([]byte, error) // 生成随机 32 字节加密密钥 func GenerateEncryptionKey() ([]byte, error)

加密格式: AES-256-GCM,魔数头 ORTENC01

加密会话

// 从加密文件创建会话 func NewAdvancedSessionFromEncryptedFile(encryptedPath string, key []byte, inputNames, outputNames []string, inputs, outputs []Value, options *SessionOptions) (*AdvancedSession, error) func NewDynamicAdvancedSessionFromEncryptedFile(encryptedPath string, key []byte, inputNames, outputNames []string, options *SessionOptions) (*DynamicAdvancedSession, error) // 从加密数据创建会话 func NewAdvancedSessionFromEncryptedData(encryptedData, key []byte, inputNames, outputNames []string, inputs, outputs []Value, options *SessionOptions) (*AdvancedSession, error) func NewDynamicAdvancedSessionFromEncryptedData(encryptedData, key []byte, inputNames, outputNames []string, options *SessionOptions) (*DynamicAdvancedSession, error) // 从加密文件获取模型信息 func GetInputOutputInfoFromEncryptedFile(encryptedPath string, key []byte) ( []InputOutputInfo, []InputOutputInfo, error)

机器绑定加密

// 从机器 ID 派生加密密钥 func DeriveModelKey(machineID, moduleName string, salt []byte) []byte // 从 Authorization 对象派生密钥 func DeriveModelKeyFromAuth(auth Authorization, moduleName string, salt []byte) ([]byte, error) // 为特定机器加密模型 func EncryptModelForMachine(inputPath, outputPath, machineID, moduleName string, salt []byte) error // 为特定机器加密模型数据 func EncryptModelDataForMachine(plaintext []byte, machineID, moduleName string, salt []byte) ([]byte, error)

授权集成

machineid/cert 包集成,实现企业授权。

Authorization 接口

type Authorization interface { Validate(machineID string) error HasModule(name string) bool GetModuleQuota(name string) int ValidateModule(name string) error ExpiresAt() time.Time MachineIDs() []string }

SecurityChecker 接口

type SecurityChecker interface { Check() error // 反调试、虚拟机检测等 }

AuthorizedModelConfig

type AuthorizedModelConfig struct { ModuleName string // 授权模块名称 MachineID string // 当前机器 ID Authorization Authorization // 授权对象 SecurityChecker SecurityChecker // 可选安全检查器 KeyDerivationSalt []byte // 密钥派生盐值 ValidateOnEveryRun bool // 每次推理前验证 QuotaTracker QuotaTracker // 可选配额追踪 }

AuthorizedSession

func NewAuthorizedSession(encryptedPath string, config AuthorizedModelConfig, inputNames, outputNames []string, options *SessionOptions) (*AuthorizedSession, error) func NewAuthorizedSessionFromData(encryptedData []byte, config AuthorizedModelConfig, inputNames, outputNames []string, options *SessionOptions) (*AuthorizedSession, error)

方法:

func (s *AuthorizedSession) Run(inputs, outputs []Value) error func (s *AuthorizedSession) GetSession() *DynamicAdvancedSession func (s *AuthorizedSession) Destroy() error

QuotaTracker 接口

type QuotaTracker interface { Increment(moduleName string) (int, error) GetCount(moduleName string) int Reset(moduleName string) } // 内置实现 func NewInMemoryQuotaTracker() *InMemoryQuotaTracker

ModelAuthorizationInfo

type ModelAuthorizationInfo struct { ModuleName string `json:"module_name"` Salt []byte `json:"salt"` ModelHash []byte `json:"model_hash,omitempty"` InputNames []string `json:"input_names"` OutputNames []string `json:"output_names"` Description string `json:"description,omitempty"` Version string `json:"version,omitempty"` } func (info *ModelAuthorizationInfo) ValidateModelHash(encryptedData []byte) bool

常量和类型

TensorElementDataType

const ( TensorElementDataTypeUndefined TensorElementDataType = iota TensorElementDataTypeFloat // float32 TensorElementDataTypeUint8 // uint8 TensorElementDataTypeInt8 // int8 TensorElementDataTypeUint16 // uint16 TensorElementDataTypeInt16 // int16 TensorElementDataTypeInt32 // int32 TensorElementDataTypeInt64 // int64 TensorElementDataTypeString // string TensorElementDataTypeBool // bool TensorElementDataTypeFloat16 // float16 TensorElementDataTypeDouble // float64 TensorElementDataTypeUint32 // uint32 TensorElementDataTypeUint64 // uint64 TensorElementDataTypeComplex64 // complex64 TensorElementDataTypeComplex128 // complex128 TensorElementDataTypeBFloat16 // bfloat16 )

ONNXType

const ( ONNXTypeUnknown ONNXType = iota ONNXTypeTensor ONNXTypeSequence ONNXTypeMap ONNXTypeOpaque ONNXTypeSparseTensor ONNXTypeOptional )

LoggingLevel

const ( LoggingLevelVerbose LoggingLevel = iota // 详细 LoggingLevelInfo // 信息 LoggingLevelWarning // 警告 LoggingLevelError // 错误 LoggingLevelFatal // 致命 )

加密常量

const ( EncryptedModelMagic = "ORTENC01" // 加密文件魔数头 AESKeySize = 32 // AES-256 密钥长度 GCMNonceSize = 12 // GCM nonce 长度 )

已弃用 API

以下 API 已弃用,但为向后兼容而保留:

// 请使用 AdvancedSession 代替 type Session[T TensorData] struct{} type DynamicSession[In, Out TensorData] struct{} func NewSession[T TensorData](...) (*Session[T], error) func NewDynamicSession[In, Out TensorData](...) (*DynamicSession[In, Out], error) func NewSessionWithONNXData[T TensorData](...) (*Session[T], error) func NewDynamicSessionWithONNXData[In, Out TensorData](...) (*DynamicSession[In, Out], error) // Training API(onnxruntime 1.20+ 已弃用) type TrainingSession struct{} func NewTrainingSession(...) (*TrainingSession, error) func IsTrainingSupported() bool // 始终返回 false

示例

CUDA 加速

cudaOpts, _ := ort.NewCUDAProviderOptions() defer cudaOpts.Destroy() cudaOpts.Update(map[string]string{ "device_id": "0", }) sessionOpts, _ := ort.NewSessionOptions() defer sessionOpts.Destroy() sessionOpts.AppendExecutionProviderCUDA(cudaOpts) session, _ := ort.NewAdvancedSession("model.onnx", inputNames, outputNames, inputs, outputs, sessionOpts)

TensorRT 加速

trtOpts, _ := ort.NewTensorRTProviderOptions() defer trtOpts.Destroy() trtOpts.Update(map[string]string{ "device_id": "0", "trt_fp16_enable": "1", "trt_max_workspace_size": "2147483648", }) sessionOpts, _ := ort.NewSessionOptions() defer sessionOpts.Destroy() sessionOpts.AppendExecutionProviderTensorRT(trtOpts) session, _ := ort.NewDynamicAdvancedSession("model.onnx", inputNames, outputNames, sessionOpts)

与 machineid/cert 集成授权

import ( "github.com/darkit/machineid" "github.com/darkit/machineid/cert" ort "cnb.cool/svn/onnxruntime" ) func main() { // 获取机器 ID machineID, _ := machineid.ID() // 创建授权验证器并加载证书 authorizer, _ := cert.NewAuthorizer(). WithCA(caPEM, caKeyPEM). Build() certAuth, _ := cert.NewCertAuthorization(certPEM, authorizer) // 创建安全检查器 securityMgr := cert.NewSecurityManager(cert.SecurityLevelAdvanced) // 配置授权会话 config := ort.AuthorizedModelConfig{ ModuleName: "ai.model.classifier", MachineID: machineID, Authorization: certAuth, // 实现 ort.Authorization 接口 SecurityChecker: securityMgr, KeyDerivationSalt: []byte("app-salt"), ValidateOnEveryRun: true, QuotaTracker: ort.NewInMemoryQuotaTracker(), } session, _ := ort.NewAuthorizedSession("model.onnx.enc", config, inputNames, outputNames, nil) defer session.Destroy() // 带授权检查的推理 session.Run(inputs, outputs) }

测试

# 运行所有测试 go test -v # 运行基准测试 go test -v -bench=. # 使用自定义 onnxruntime 库 ONNXRUNTIME_SHARED_LIBRARY_PATH=/path/to/libonnxruntime.so go test -v

版本兼容性

本库使用 ONNX Runtime C API 版本 1.23.2。如需使用其他版本:

  1. 替换 onnxruntime_c_api.honnxruntime_ep_c_api.h 为对应版本
  2. 替换 test_data/ 中的共享库
  3. 如需要,验证 DirectML API 兼容性

许可证

请参阅原版 yalue/onnxruntime_go 仓库的许可证信息。

相关项目


静态库构建

默认情况下,本库在运行时动态加载 ONNX Runtime。要使用静态链接的 ONNX Runtime 库,请使用 static 构建标签。

使用静态库构建

# 设置头文件和库路径 export CGO_CFLAGS="-I/opt/onnxruntime/include" export CGO_LDFLAGS="-L/opt/onnxruntime/lib -l:libonnxruntime.a -lstdc++ -lm -lpthread -ldl" # 使用 static 标签构建 go build -tags static ./...

各平台示例

Linux (仅 CPU):

export CGO_CFLAGS="-I/opt/onnxruntime/include" export CGO_LDFLAGS="-L/opt/onnxruntime/lib -l:libonnxruntime.a -lstdc++ -lm -lpthread -ldl" go build -tags static ./...

Linux (带 CUDA):

export CGO_CFLAGS="-I/opt/onnxruntime/include -I/usr/local/cuda/include" export CGO_LDFLAGS="-L/opt/onnxruntime/lib -L/usr/local/cuda/lib64 \ -l:libonnxruntime.a -lcudart -lcublas -lcublasLt -lcudnn \ -lstdc++ -lm -lpthread -ldl" go build -tags static ./...

Linux (带 TensorRT):

export CGO_CFLAGS="-I/opt/onnxruntime/include -I/usr/local/cuda/include -I/opt/TensorRT/include" export CGO_LDFLAGS="-L/opt/onnxruntime/lib -L/usr/local/cuda/lib64 -L/opt/TensorRT/lib \ -l:libonnxruntime.a -lcudart -lcublas -lcublasLt -lcudnn \ -lnvinfer -lnvinfer_plugin -lnvonnxparser \ -lstdc++ -lm -lpthread -ldl" go build -tags static ./...

macOS:

export CGO_CFLAGS="-I/opt/onnxruntime/include" export CGO_LDFLAGS="-L/opt/onnxruntime/lib -lonnxruntime -lc++ \ -framework Foundation -framework CoreML" go build -tags static ./...

Windows (MinGW):

set CGO_CFLAGS=-I/opt/onnxruntime/include set CGO_LDFLAGS=-L/opt/onnxruntime/lib -lonnxruntime -lstdc++ -lm -lpthread go build -tags static ./...

代码差异

使用静态构建时,不需要调用 SetSharedLibraryPath()

package main import ( ort "github.com/yalue/onnxruntime_go" ) func main() { // 静态构建:无需设置库路径 // 静态模式下 ort.SetSharedLibraryPath() 会被忽略 // 检查是否使用静态构建 if ort.IsStaticBuild() { println("使用静态库") } // 正常初始化 if err := ort.InitializeEnvironment(); err != nil { panic(err) } defer ort.DestroyEnvironment() // ... 其余代码 }

检查构建模式

// IsStaticBuild 返回是否使用 -tags static 编译 func IsStaticBuild() bool

混合链接(静态 + 动态)

可以混合使用静态和动态链接以获得最佳部署效果:

链接器参数说明

# -l:libxxx.a 强制静态链接指定库 # -lxxx 优先动态链接,找不到则静态 # -Wl,-Bstatic 后续库使用静态链接 # -Wl,-Bdynamic 后续库使用动态链接

示例:ONNX Runtime 静态 + CUDA 动态(推荐)

export CGO_CFLAGS="-I/opt/onnxruntime/include -I/usr/local/cuda/include" export CGO_LDFLAGS="\ -L/opt/onnxruntime/lib \ -L/usr/local/cuda/lib64 \ -Wl,-Bstatic -lonnxruntime \ -Wl,-Bdynamic -lcudart -lcublas -lcublasLt -lcudnn \ -lstdc++ -lm -lpthread -ldl" go build -tags static ./...

示例:ONNX Runtime 静态 + TensorRT 动态

export CGO_LDFLAGS="\ -L/opt/onnxruntime/lib \ -L/usr/local/cuda/lib64 \ -L/opt/TensorRT/lib \ -Wl,-Bstatic -lonnxruntime \ -Wl,-Bdynamic -lcudart -lcublas -lcudnn \ -lnvinfer -lnvinfer_plugin \ -lstdc++ -lm -lpthread -ldl"

示例:最大静态化(核心静态,系统库动态)

export CGO_LDFLAGS="\ -L/opt/onnxruntime/lib \ -L/usr/local/cuda/lib64/stubs \ -Wl,-Bstatic \ -lonnxruntime \ -lcudart_static -lcublas_static -lcublasLt_static \ -Wl,-Bdynamic \ -ldl -lpthread -lrt -lm"

验证链接方式

# Linux - 查看动态依赖 ldd ./myapp # 查看所有符号(包括静态链接的) nm ./myapp | grep -i onnx # macOS otool -L ./myapp

混合链接的优缺点

优点缺点
核心功能便携配置较复杂
GPU 库可随系统更新需要理解链接器行为
可执行文件相对较小部分库仍需部署
兼顾便携性和灵活性调试时需注意版本匹配

推荐配置

# onnxruntime 静态(核心功能便携) # CUDA/cuDNN 动态(跟随驱动版本) # 系统库动态(libc, libm, libpthread) CGO_LDFLAGS="\ -Wl,-Bstatic -l:libonnxruntime.a \ -Wl,-Bdynamic -lcudart -lcudnn -lcublas \ -lstdc++ -lm -lpthread -ldl"

这样编译出的程序:

  • 不需要分发 libonnxruntime.so
  • 需要目标机器安装对应版本的 CUDA 驱动
  • 使用目标机器的系统库,兼容性好