diff options
| author | ruki <[email protected]> | 2019-03-17 12:18:03 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-03-17 12:18:03 +0800 |
| commit | fb572ca825d47b0dd3612f824aefbd7eed7ba36a (patch) | |
| tree | 34817de06cd4eec5b01596c8e81d3911bc0d6272 | |
| parent | 27187f0004a3e93b76431cfb78bcd0e2250263a1 (diff) | |
enter and leave package envs
| -rw-r--r-- | xmake/actions/require/impl/action/install.lua | 9 | ||||
| -rw-r--r-- | xmake/actions/require/impl/environment.lua | 82 | ||||
| -rw-r--r-- | xmake/core/package/package.lua | 70 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/lib/detect/find_program.lua | 46 |
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 -- |
