diff options
| author | ruki <[email protected]> | 2019-03-22 23:52:08 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-03-22 17:12:49 +0800 |
| commit | 6771a6707d884f53a192f8a5a1ed42db299f79a5 (patch) | |
| tree | 3dee7df8fee33fe7dded6537b613681e9d0a7f7d | |
| parent | 9ed3fd873294466fa927d9dfd38cb43cce1d6dd8 (diff) | |
improve install packages
| -rw-r--r-- | xmake/actions/require/impl/action/install.lua | 129 | ||||
| -rw-r--r-- | xmake/actions/require/impl/package.lua | 121 |
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 |
