summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-03-22 23:52:08 +0800
committerruki <[email protected]>2019-03-22 17:12:49 +0800
commit6771a6707d884f53a192f8a5a1ed42db299f79a5 (patch)
tree3dee7df8fee33fe7dded6537b613681e9d0a7f7d
parent9ed3fd873294466fa927d9dfd38cb43cce1d6dd8 (diff)
improve install packages
-rw-r--r--xmake/actions/require/impl/action/install.lua129
-rw-r--r--xmake/actions/require/impl/package.lua121
2 files changed, 156 insertions, 94 deletions
diff --git a/xmake/actions/require/impl/action/install.lua b/xmake/actions/require/impl/action/install.lua
index 2a8a838ae..81a456b0d 100644
--- a/xmake/actions/require/impl/action/install.lua
+++ b/xmake/actions/require/impl/action/install.lua
@@ -29,6 +29,20 @@ import("lib.detect.find_file")
import("test")
import(".utils.filter")
+-- empty chars
+function _emptychars()
+
+ -- get left width
+ local width = os.getwinsize()["width"] or 64
+
+ -- make empty chars
+ local emptychars = ""
+ for i = 1, width do
+ emptychars = emptychars .. " "
+ end
+ return emptychars
+end
+
-- patch pkgconfig if not exists
function _patch_pkgconfig(package)
@@ -115,12 +129,6 @@ function main(package)
tipname = tipname .. "-" .. package:version_str()
end
- -- trace
- cprintf("${yellow} => ${clear}installing %s .. ", tipname)
- if option.get("verbose") or option.get("diagnosis") then
- print("")
- end
-
-- install it
try
{
@@ -134,81 +142,71 @@ function main(package)
, package:script("install_after")
}
- -- create the install task
- local installtask = function ()
-
- -- install the third-party package directly, e.g. brew::pcre2/libpcre2-8, conan::OpenSSL/1.0.2n@conan/stable
- local installed_now = false
- if package:is3rd() then
- local script = package:script("install")
- if script ~= nil then
- filter.call(script, package)
- end
- else
-
- -- build and install package to the install directory
- if option.get("force") or not package:manifest_load() then
+ -- install the third-party package directly, e.g. brew::pcre2/libpcre2-8, conan::OpenSSL/1.0.2n@conan/stable
+ local installed_now = false
+ if package:is3rd() then
+ local script = package:script("install")
+ if script ~= nil then
+ filter.call(script, package)
+ end
+ else
- -- clean install directory first
- os.tryrm(package:installdir())
+ -- build and install package to the install directory
+ if option.get("force") or not package:manifest_load() then
- -- enter the environments of all package dependencies
- for _, dep in ipairs(package:orderdeps()) do
- dep:envs_enter()
- end
+ -- clean install directory first
+ os.tryrm(package:installdir())
- -- do install
- for i = 1, 3 do
- local script = scripts[i]
- if script ~= nil then
- filter.call(script, package)
- end
- end
+ -- enter the environments of all package dependencies
+ for _, dep in ipairs(package:orderdeps()) do
+ dep:envs_enter()
+ end
- -- leave the environments of all package dependencies
- for _, dep in irpairs(package:orderdeps()) do
- dep:envs_leave()
+ -- do install
+ for i = 1, 3 do
+ local script = scripts[i]
+ if script ~= nil then
+ filter.call(script, package)
end
-
- -- save the package info to the manifest file
- package:manifest_save()
- installed_now = true
end
- end
- -- enter the package environments
- package:envs_enter()
+ -- leave the environments of all package dependencies
+ for _, dep in irpairs(package:orderdeps()) do
+ dep:envs_leave()
+ end
- -- fetch package and force to flush the cache
- local fetchinfo = package:fetch({force = true})
- if option.get("verbose") or option.get("diagnosis") then
- print(fetchinfo)
+ -- save the package info to the manifest file
+ package:manifest_save()
+ installed_now = true
end
- assert(fetchinfo, "fetch %s failed!", tipname)
+ end
+
+ -- enter the package environments
+ package:envs_enter()
- -- this package is installed now
- if installed_now then
+ -- fetch package and force to flush the cache
+ local fetchinfo = package:fetch({force = true})
+ if option.get("verbose") or option.get("diagnosis") then
+ print(fetchinfo)
+ end
+ assert(fetchinfo, "fetch %s failed!", tipname)
- -- patch pkg-config files for package
- _patch_pkgconfig(package)
+ -- this package is installed now
+ if installed_now then
- -- test it
- test(package)
- end
+ -- patch pkg-config files for package
+ _patch_pkgconfig(package)
- -- leave the package environments
- package:envs_leave()
+ -- test it
+ test(package)
end
- -- install package
- if option.get("verbose") or option.get("diagnosis") then
- installtask()
- else
- process.asyncrun(installtask)
- end
+ -- leave the package environments
+ package:envs_leave()
-- trace
- cprint("${color.success}${text.success}")
+ printf("\r" .. _emptychars())
+ cprint("\r${yellow} => ${clear}install %s-%s .. ${color.success}${text.success}", package:name(), package:version_str())
end,
catch
@@ -221,7 +219,8 @@ function main(package)
end
-- trace
- cprint("${color.failure}${text.failure}")
+ printf("\r" .. _emptychars())
+ cprint("\r${yellow} => ${clear}install %s-%s .. ${color.failure}${text.failure}", package:name(), package:version_str())
-- leave the package environments
package:envs_leave()
diff --git a/xmake/actions/require/impl/package.lua b/xmake/actions/require/impl/package.lua
index 6e277c07b..0595ed8f1 100644
--- a/xmake/actions/require/impl/package.lua
+++ b/xmake/actions/require/impl/package.lua
@@ -439,19 +439,88 @@ function _get_confirm(packages)
return confirm
end
--- download packages
-function _download_packages(packages)
+-- install packages
+function _install_packages(packages_install, packages_download)
local waitindex = 0
local waitchars = {'\\', '|', '/', '-'}
+ local packages_installing = {}
+ local packages_downloading = {}
+ local packages_pending = table.copy(packages_install)
+ local packages_in_group = {}
process.runjobs(function (index)
- local package = packages[index]
+ -- fetch a new package
+ local package = nil
+ while package == nil and #packages_pending > 0 do
+ for idx, pkg in ipairs(packages_pending) do
+
+ -- all dependences has been installed? we install it now
+ local ready = true
+ for _, dep in ipairs(pkg:orderdeps()) do
+ if not dep:exists() then
+ ready = false
+ end
+ end
+ local group = pkg:group()
+ if ready and group then
+ -- this group has been installed? skip it
+ local group_status = packages_in_group[group]
+ if group_status == 1 then
+ table.remove(packages_pending, idx)
+ break
+ -- this group is installing? wait it
+ elseif group_status == 0 then
+ ready = false
+ end
+ end
+
+ -- get a package with the ready status
+ if ready then
+ package = pkg
+ table.remove(packages_pending, idx)
+ break
+ end
+ end
+ if package == nil and #packages_pending > 0 then
+ local curdir = os.curdir()
+ coroutine.yield()
+ os.cd(curdir)
+ end
+ end
if package then
- action.download(package)
+
+ -- only install the first package in same group
+ local group = package:group()
+ if not group or not packages_in_group[group] then
+
+ -- mark this group as 'installing'
+ if group then
+ packages_in_group[group] = 0
+ end
+
+ -- download this package first
+ if packages_download[tostring(package)] then
+ packages_downloading[index] = package
+ action.download(package)
+ packages_downloading[index] = nil
+ end
+
+ -- install this package
+ packages_installing[index] = package
+ action.install(package)
+ packages_installing[index] = nil
+
+ -- mark this group as 'installed' or 'failed'
+ if group then
+ packages_in_group[group] = package:exists() and 1 or -1
+ end
+ end
end
+ packages_installing[index] = nil
+ packages_downloading[index] = nil
- end, #packages, (option.get("verbose") or option.get("diagnosis")) and 1 or 4, 300, function (indices)
+ end, #packages_install, (option.get("verbose") or option.get("diagnosis")) and 1 or 4, 300, function (indices)
-- do not print progress info if be verbose
if option.get("verbose") then
@@ -461,37 +530,34 @@ function _download_packages(packages)
-- update waitchar index
waitindex = ((waitindex + 1) % #waitchars)
- -- make downloading packages list
+ -- make installing and downloading packages list
+ local installing = {}
local downloading = {}
for _, index in ipairs(indices) do
- local package = packages[index]
+ local package = packages_installing[index]
+ if package then
+ table.insert(installing, package:name())
+ end
+ local package = packages_downloading[index]
if package then
table.insert(downloading, package:name())
end
end
-- trace
- cprintf("\r${yellow} => ${clear}downloading %s .. %s", table.concat(downloading, ", "), waitchars[waitindex + 1])
+ cprintf("\r${yellow} => ${clear}installing %s .. %s", table.concat(installing, ", "), waitchars[waitindex + 1])
+ cprintf("\r${yellow} => ${clear}")
+ if #downloading > 0 then
+ cprintf("downloading ${yellow}%s${clear}", table.concat(downloading, ", "))
+ end
+ if #installing > 0 then
+ cprintf("%sinstalling ${yellow}%s${clear}", #downloading > 0 and ", " or "", table.concat(installing, ", "))
+ end
+ cprintf(" .. %s", waitchars[waitindex + 1])
io.flush()
end)
end
--- install packages
-function _install_packages(packages)
- local installed_in_group = {}
- for _, package in ipairs(packages) do
-
- -- only install the first package in same group
- local group = package:group()
- if not group or not installed_in_group[group] then
- action.install(package)
- if group then
- installed_in_group[group] = true
- end
- end
- end
-end
-
-- the cache directory
function cachedir()
return path.join(global.directory(), "cache", "packages")
@@ -578,7 +644,7 @@ function install_packages(requires, opt)
if (option.get("force") or not package:exists()) and (#package:urls() > 0 or package:script("install")) then
if package:supported() then
if #package:urls() > 0 then
- table.insert(packages_download, package)
+ packages_download[tostring(package)] = package
end
table.insert(packages_install, package)
elseif not package:optional() then
@@ -605,11 +671,8 @@ function install_packages(requires, opt)
-- sort package urls
_sort_packages_urls(packages_download)
- -- download remote packages
- _download_packages(packages_download)
-
-- install all required packages from repositories
- _install_packages(packages_install)
+ _install_packages(packages_install, packages_download)
-- ok
return packages