From d3ed5cb941d83a7fe723c0a464930f455ab7b15a Mon Sep 17 00:00:00 2001 From: Peefy Date: Tue, 19 Mar 2024 14:04:48 +0800 Subject: [PATCH] feat: disable shared lib install at the code level (#259) Signed-off-by: peefy --- pkg/env/env.go | 91 ++++++++++++++++++++++++++++++++++++++++++++ pkg/native/loader.go | 5 +++ pkg/path/lazypath.go | 8 +--- pkg/runtime/init.go | 18 ++------- pkg/runtime/kclvm.go | 20 +++++++--- pkg/utils/utils.go | 18 +++++++++ 6 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 pkg/env/env.go diff --git a/pkg/env/env.go b/pkg/env/env.go new file mode 100644 index 00000000..e1c168b2 --- /dev/null +++ b/pkg/env/env.go @@ -0,0 +1,91 @@ +package env + +import ( + "os" + "strconv" + "sync" +) + +var ( + once sync.Once + mu sync.Mutex + env *EnvSettings +) + +// EnvSettings represents environment settings for the KCL Go SDK. +type EnvSettings struct { + LibHome string + DisableInstallArtifact bool + DisableUseArtifactInPath bool +} + +// Instance returns a singleton instance of EnvSettings. +func instance() *EnvSettings { + once.Do(func() { + env = &EnvSettings{ + LibHome: os.Getenv("KCL_LIB_HOME"), + DisableInstallArtifact: envBoolOr("KCL_GO_DISABLE_INSTALL_ARTIFACT", false), + DisableUseArtifactInPath: envBoolOr("KCL_GO_DISABLE_ARTIFACT_IN_PATH", false), + } + }) + return env +} + +// GetLibHome returns the LibHome value from the singleton instance of EnvSettings. +func GetLibHome() string { + return instance().LibHome +} + +// SetLibHome sets the LibHome value in the singleton instance of EnvSettings. +func SetLibHome(value string) { + mu.Lock() + defer mu.Unlock() + instance().LibHome = value +} + +// SetDisableInstallArtifact sets the DisableInstallArtifact value in the singleton instance of EnvSettings. +func SetDisableInstallArtifact(value bool) { + mu.Lock() + defer mu.Unlock() + instance().DisableInstallArtifact = value +} + +// GetDisableInstallArtifact returns the DisableInstallArtifact value from the singleton instance of EnvSettings. +func GetDisableInstallArtifact() bool { + return instance().DisableInstallArtifact +} + +// GetDisableUseArtifactInPath returns the DisableUseArtifactInPath value from the singleton instance of EnvSettings. +func GetDisableUseArtifactInPath() bool { + return instance().DisableUseArtifactInPath +} + +// SetDisableUseArtifactInPath sets the DisableUseArtifactInPath value in the singleton instance of EnvSettings. +func SetDisableUseArtifactInPath(value bool) { + mu.Lock() + defer mu.Unlock() + instance().DisableUseArtifactInPath = value +} + +// envOr returns the value of the specified environment variable, or the +// default value if it does not exist. +func envOr(name, def string) string { + if v, ok := os.LookupEnv(name); ok { + return v + } + return def +} + +// envBoolOr returns the boolean value of the specified environment variable, +// or the default value if it does not exist. +func envBoolOr(name string, def bool) bool { + if name == "" { + return def + } + envVal := envOr(name, strconv.FormatBool(def)) + ret, err := strconv.ParseBool(envVal) + if err != nil { + return def + } + return ret +} diff --git a/pkg/native/loader.go b/pkg/native/loader.go index 78f6677f..f29fe763 100644 --- a/pkg/native/loader.go +++ b/pkg/native/loader.go @@ -7,6 +7,7 @@ import ( "kcl-lang.io/kcl-go/pkg/3rdparty/dlopen" kcl_runtime "kcl-lang.io/kcl-go/pkg/runtime" + "kcl-lang.io/kcl-go/pkg/utils" ) const libName = "kclvm_cli_cdylib" @@ -24,6 +25,10 @@ func loadServiceNativeLib() *dlopen.LibHandle { } libPath := filepath.Join(root, "bin", fullLibName) + if !utils.FileExists(libPath) { + libPath = filepath.Join(root, "lib", fullLibName) + } + libPaths = append(libPaths, libPath) h, err := dlopen.GetHandle(libPaths) diff --git a/pkg/path/lazypath.go b/pkg/path/lazypath.go index ee164962..6b63385d 100644 --- a/pkg/path/lazypath.go +++ b/pkg/path/lazypath.go @@ -16,12 +16,8 @@ package path import ( "os" "path/filepath" -) -const ( - // LibHomeEnvVar is the environment variable used by kcl - // for the lib install directory. When no value is set a default is used. - LibHomeEnvVar = "KCL_LIB_HOME" + "kcl-lang.io/kcl-go/pkg/env" ) // lazypath is an lazy-loaded path buffer for the XDG base directory specification. @@ -45,5 +41,5 @@ func (l lazypath) path(envVar string, defaultFn func() string, elem ...string) s // libPath defines the base directory relative to which user specific non-essential data files // should be stored. func (l lazypath) libPath(elem ...string) string { - return l.path(LibHomeEnvVar, libHome, filepath.Join(elem...)) + return l.path(env.GetLibHome(), libHome, filepath.Join(elem...)) } diff --git a/pkg/runtime/init.go b/pkg/runtime/init.go index 0d9d6648..ec0fe4aa 100644 --- a/pkg/runtime/init.go +++ b/pkg/runtime/init.go @@ -4,8 +4,6 @@ package runtime import ( "fmt" - "os" - "path/filepath" "runtime" "sync" @@ -13,10 +11,9 @@ import ( ) var ( - Debug bool - rpcRuntime *Runtime - once sync.Once - UseKCLPluginEnvVar = "KCL_GO_USE_PLUGIN" + Debug bool + rpcRuntime *Runtime + once sync.Once ) const tip = "Tip: Have you used a binary version of KCL in your PATH that is not consistent with the KCL Go SDK? You can upgrade or reduce the KCL version or delete the KCL in your PATH" @@ -47,14 +44,7 @@ func initRuntime(maxProc int) { panic(ErrKclvmRootNotFound) } - if os.Getenv(UseKCLPluginEnvVar) != "" { - os.Setenv("PYTHONHOME", "") - os.Setenv("PYTHONPATH", filepath.Join(g_KclvmRoot, "lib", "site-packages")) - rpcRuntime = NewRuntime(int(maxProc), MustGetKclvmPath(), "-m", "kclvm.program.rpc-server") - } else { - rpcRuntime = NewRuntime(int(maxProc), "kclvm_cli", "server") - } - + rpcRuntime = NewRuntime(int(maxProc), "kclvm_cli", "server") rpcRuntime.Start() client := &BuiltinServiceClient{ diff --git a/pkg/runtime/kclvm.go b/pkg/runtime/kclvm.go index 6b6d0179..b643777e 100644 --- a/pkg/runtime/kclvm.go +++ b/pkg/runtime/kclvm.go @@ -13,20 +13,24 @@ import ( "time" "github.com/gofrs/flock" + "kcl-lang.io/kcl-go/pkg/env" "kcl-lang.io/kcl-go/pkg/logger" "kcl-lang.io/kcl-go/pkg/path" "kcl-lang.io/lib" ) -const ( - DisableArtifactEnvVar = "KCL_GO_DISABLE_ARTIFACT" -) - func init() { - if os.Getenv(DisableArtifactEnvVar) == "" && os.Getenv(UseKCLPluginEnvVar) == "" { + if !env.GetDisableInstallArtifact() { installKclArtifact() } - g_KclvmRoot = findKclvmRoot() + if env.GetDisableUseArtifactInPath() { + // Must use the artifact installed by kcl-go + // Get the install lib path. + g_KclvmRoot = findInstalledArtifactRoot() + } else { + // Get kclvm root path in PATH + g_KclvmRoot = findKclvmRoot() + } } func installKclArtifact() { @@ -112,3 +116,7 @@ func findKclvmRoot() string { } return "" } + +func findInstalledArtifactRoot() string { + return filepath.Join(path.LibPath(), "bin") +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 5f86e8a1..70180e35 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -1,3 +1,21 @@ // Copyright The KCL Authors. All rights reserved. package utils + +import "os" + +func FileExists(path string) bool { + fi, err := os.Lstat(path) + if err != nil || fi.IsDir() { + return false + } + return true +} + +func DirExists(path string) bool { + fi, err := os.Lstat(path) + if err != nil || !fi.IsDir() { + return false + } + return true +}