summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-03-17 12:18:03 +0800
committerruki <[email protected]>2019-03-17 12:18:03 +0800
commitfb572ca825d47b0dd3612f824aefbd7eed7ba36a (patch)
tree34817de06cd4eec5b01596c8e81d3911bc0d6272
parent27187f0004a3e93b76431cfb78bcd0e2250263a1 (diff)
enter and leave package envs
-rw-r--r--xmake/actions/require/impl/action/install.lua9
-rw-r--r--xmake/actions/require/impl/environment.lua82
-rw-r--r--xmake/core/package/package.lua70
-rw-r--r--xmake/core/sandbox/modules/import/lib/detect/find_program.lua46
4 files changed, 190 insertions, 17 deletions
diff --git a/xmake/actions/require/impl/action/install.lua b/xmake/actions/require/impl/action/install.lua
index 0e8e8972e..133b03b7d 100644
--- a/xmake/actions/require/impl/action/install.lua
+++ b/xmake/actions/require/impl/action/install.lua
@@ -107,6 +107,9 @@ function main(package)
end
end
+ -- enter the package environments
+ package:envs_enter()
+
-- fetch package and force to flush the cache
local fetchinfo = package:fetch({force = true})
if option.get("verbose") or option.get("diagnosis") then
@@ -118,6 +121,9 @@ function main(package)
if need_test then
test(package)
end
+
+ -- leave the package environments
+ package:envs_leave()
end
-- install package
@@ -143,6 +149,9 @@ function main(package)
-- trace
cprint("${color.failure}${text.failure}")
+ -- leave the package environments
+ package:envs_leave()
+
-- remove the invalid package directory
os.tryrm(package:installdir())
diff --git a/xmake/actions/require/impl/environment.lua b/xmake/actions/require/impl/environment.lua
index febae166e..13a50c44b 100644
--- a/xmake/actions/require/impl/environment.lua
+++ b/xmake/actions/require/impl/environment.lua
@@ -29,9 +29,66 @@ import("core.package.package", {alias = "core_package"})
import("lib.detect.find_tool")
import("package")
+-- enter the package environments
+function _enter_package(package_name, envs, installdir)
+
+ -- save the old environments
+ _g._OLDENVS = _g._OLDENVS or {}
+ local oldenvs = _g._OLDENVS[package_name]
+ if not oldenvs then
+ oldenvs = {}
+ _g._OLDENVS[package_name] = oldenvs
+ end
+
+ -- add the new environments
+ oldenvs.PATH = os.getenv("PATH")
+ os.addenv("PATH", path.join(installdir, "bin"))
+ for name, values in pairs(envs) do
+ oldenvs[name] = oldenvs[name] or os.getenv(name)
+ if name == "PATH" then
+ for _, value in ipairs(values) do
+ os.addenv(name, path.join(installdir, value))
+ end
+ else
+ os.addenv(name, unpack(values))
+ end
+ end
+end
+
+-- leave the package environments
+function _leave_package(package_name)
+ _g._OLDENVS = _g._OLDENVS or {}
+ local oldenvs = _g._OLDENVS[package_name]
+ if oldenvs then
+ for name, values in pairs(oldenvs) do
+ os.setenv(name, values)
+ end
+ _g._OLDENVS[package_name] = nil
+ end
+end
+
+-- enter environment of the given binary packages, git, 7z, ..
+function _enter_packages(...)
+ for _, name in ipairs({...}) do
+ for _, manifest_file in ipairs(os.files(path.join(core_package.installdir(), name:sub(1, 1), name, "*", "*", "manifest.txt"))) do
+ local manifest = io.load(manifest_file)
+ if manifest and manifest.plat == os.host() and manifest.arch == os.arch() then
+ _enter_package(name, manifest.envs, path.directory(manifest_file))
+ end
+ end
+ end
+end
+
+-- leave environment of the given binary packages, git, 7z, ..
+function _leave_packages(...)
+ for _, name in ipairs({...}) do
+ _leave_package(name)
+ end
+end
+
-- enter environment
--
--- ensure that we can find some basic tools: git, make/nmake/cmake, msbuild ...
+-- ensure that we can find some basic tools: git, unzip, ...
--
-- If these tools not exist, we will install it first.
--
@@ -45,20 +102,39 @@ function enter()
raise("unzip not found! we need install it first")
end
+ -- enter the environments of git and 7z
+ _enter_packages("git", "7z")
+
-- git not found? install it first
+ local packages = {}
if not find_tool("git") then
- package.install_packages("git")
+ table.join2(packages, package.install_packages("git"))
end
-- missing the necessary unarchivers for *.gz, *.7z? install them first, e.g. gzip, 7z, tar ..
if not ((find_tool("gzip") and find_tool("tar")) or find_tool("7z")) then
- package.install_packages("7z")
+ table.join2(packages, package.install_packages("7z"))
end
+
+ -- enter the environments of installed packages
+ for _, instance in ipairs(packages) do
+ instance:envs_enter()
+ end
+ _g._PACKAGES = packages
end
-- leave environment
function leave()
+ -- leave the environments of installed packages
+ for _, instance in ipairs(_g._PACKAGES) do
+ instance:envs_leave()
+ end
+ _g._PACKAGES = nil
+
+ -- leave the environments of git and 7z
+ _leave_packages("git", "7z")
+
-- restore search pathes of toolchains
environment.leave("toolchains")
end
diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua
index 9d605d615..fead86f1c 100644
--- a/xmake/core/package/package.lua
+++ b/xmake/core/package/package.lua
@@ -324,6 +324,44 @@ function _instance:envs()
return envs
end
+-- enter the package environments
+function _instance:envs_enter()
+
+ -- save the old environments
+ local oldenvs = self._OLDENVS
+ if not oldenvs then
+ oldenvs = {}
+ self._OLDENVS = oldenvs
+ end
+
+ -- add the new environments
+ local installdir = self:installdir()
+ if self:kind() == "binary" then
+ oldenvs.PATH = os.getenv("PATH")
+ os.addenv("PATH", path.join(installdir, "bin"))
+ end
+ for name, values in pairs(self:envs()) do
+ oldenvs[name] = oldenvs[name] or os.getenv(name)
+ if name == "PATH" then
+ for _, value in ipairs(values) do
+ os.addenv(name, path.join(installdir, value))
+ end
+ else
+ os.addenv(name, unpack(values))
+ end
+ end
+end
+
+-- leave the package environments
+function _instance:envs_leave()
+ if self._OLDENVS then
+ for name, values in pairs(self._OLDENVS) do
+ os.setenv(name, values)
+ end
+ self._OLDENVS = nil
+ end
+end
+
-- get the given environment variable
function _instance:getenv(name)
return self:envs()[name]
@@ -594,6 +632,11 @@ function _instance:fetch(opt)
require_ver = nil
end
+ -- nil: find xmake or system packages
+ -- true: only find system package
+ -- false: only find xmake packages
+ local system = opt.system or self:requireinfo().system
+
-- fetch binary tool?
fetchinfo = nil
local isSys = nil
@@ -602,21 +645,30 @@ function _instance:fetch(opt)
-- import find_tool
self._find_tool = self._find_tool or sandbox_module.import("lib.detect.find_tool", {anonymous = true})
- -- fetch it from the system directories, TODO find the given version
- fetchinfo = self._find_tool(self:name(), {force = opt.force})
- if fetchinfo then
- isSys = true -- ignore self:requireinfo().system
+ -- only fetch it from the xmake repository first
+ if not fetchinfo and system ~= true and not self:is3rd() then
+ fetchinfo = self._find_tool(self:name(), {version = self:version_str(),
+ cachekey = "fetch_package_xmake",
+ buildhash = self:buildhash(),
+ force = opt.force})
+ if fetchinfo then
+ isSys = self._isSys
+ end
+ end
+
+ -- fetch it from the system directories
+ if not fetchinfo and system ~= false then
+ fetchinfo = self._find_tool(self:name(), {cachekey = "fetch_package_system",
+ force = opt.force})
+ if fetchinfo then
+ isSys = true
+ end
end
else
-- import find_package
self._find_package = self._find_package or sandbox_module.import("lib.detect.find_package", {anonymous = true})
- -- nil: find local or system packages
- -- true: only find system package
- -- false: only find local packages
- local system = opt.system or self:requireinfo().system
-
-- only fetch it from the xmake repository first
if not fetchinfo and system ~= true and not self:is3rd() then
fetchinfo = self._find_package("xmake::" .. self:name(), {version = self:version_str(),
diff --git a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua
index 18c9be5e3..e7f6a5d0d 100644
--- a/xmake/core/sandbox/modules/import/lib/detect/find_program.lua
+++ b/xmake/core/sandbox/modules/import/lib/detect/find_program.lua
@@ -117,16 +117,52 @@ function sandbox_lib_detect_find_program._find_from_pathes(name, pathes, opt)
end
end
+-- find program from the xmake packages
+function sandbox_lib_detect_find_program._find_from_packages(name, opt)
+
+ -- get the manifest file of package, .e.g ~/.xmake/packages/g/git/1.1.12/ed41d5327fad3fc06fe376b4a94f62ef/manifest.txt
+ local manifest_file = path.join(package.installdir(), name:sub(1, 1), name, opt.version, opt.buildhash, "manifest.txt")
+ if not os.isfile(manifest_file) then
+ return
+ end
+
+ -- get install directory of this package
+ local installdir = path.directory(manifest_file)
+
+ -- init pathes
+ local pathes = {}
+ table.insert(pathes, path.join(installdir, "bin"))
+
+ -- load manifest info
+ local manifest = io.load(manifest_file)
+ if manifest and manifest.envs then
+ local pathenvs = manifest.envs.PATH
+ if pathenvs then
+ for _, pathenv in ipairs(pathenvs) do
+ table.insert(pathes, path.join(installdir, pathenv))
+ end
+ end
+ end
+
+ -- find it
+ return sandbox_lib_detect_find_program._find_from_pathes(name, pathes, opt)
+end
+
-- find program
function sandbox_lib_detect_find_program._find(name, pathes, opt)
- -- attempt to check it from the given directories
+ -- attempt to find it from the given directories
local program_path = sandbox_lib_detect_find_program._find_from_pathes(name, pathes, opt)
if program_path then
return program_path
end
- -- attempt to check it from regists
+ -- attempt to find it from the xmake packages
+ if opt.version and opt.buildhash then
+ return sandbox_lib_detect_find_program._find_from_packages(name, opt)
+ end
+
+ -- attempt to find it from regists
if os.host() == "windows" then
local program_name = name:lower()
if not program_name:endswith(".exe") then
@@ -143,7 +179,7 @@ function sandbox_lib_detect_find_program._find(name, pathes, opt)
end
end
else
- -- attempt to check it use `which program` command
+ -- attempt to find it use `which program` command
local ok, program_path = os.iorunv("which", {name})
if ok and program_path then
-- check it
@@ -156,7 +192,7 @@ function sandbox_lib_detect_find_program._find(name, pathes, opt)
end
end
- -- attempt to check it from the some default system directories
+ -- attempt to find it from the some default system directories
local syspathes = {}
if os.host() ~= "windows" then
table.insert(syspathes, "/usr/local/bin")
@@ -169,7 +205,7 @@ function sandbox_lib_detect_find_program._find(name, pathes, opt)
end
end
- -- attempt to check it directly in current environment
+ -- attempt to find it directly in current environment
--
-- @note must be detected at the end, because full path is more accurate
--