summaryrefslogtreecommitdiff
path: root/xmake/modules/utils
diff options
context:
space:
mode:
authorÂngelo Andrade Cirino <[email protected]>2022-01-10 10:23:17 -0300
committerÂngelo Andrade Cirino <[email protected]>2022-01-10 10:23:17 -0300
commited0c0c5e0249aa966ea7061b30710abdd0b09d87 (patch)
tree2a51c869a3aea1a093ed569e749bdf0465634a6c /xmake/modules/utils
parent885d00da8caf74aeed758d030b9a1b50d9078e1f (diff)
parent2431dd7e6142ff98b55741cfd4de4d2e69f4f8b5 (diff)
Merged from upstream/master
Diffstat (limited to 'xmake/modules/utils')
-rw-r--r--xmake/modules/utils/archive/extension.lua3
-rw-r--r--xmake/modules/utils/archive/extract.lua77
-rw-r--r--xmake/modules/utils/archive/merge_staticlib.lua73
-rw-r--r--xmake/modules/utils/progress.lua139
4 files changed, 241 insertions, 51 deletions
diff --git a/xmake/modules/utils/archive/extension.lua b/xmake/modules/utils/archive/extension.lua
index 3a8554efd..fe33a395f 100644
--- a/xmake/modules/utils/archive/extension.lua
+++ b/xmake/modules/utils/archive/extension.lua
@@ -23,7 +23,6 @@ import("core.base.hashset")
-- get the archive extension
function main(archivefile)
-
local extension = ""
local filename = path.filename(archivefile)
local extensionset = hashset.from({".zip", ".7z", ".gz", ".xz", ".tgz", ".bz2", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2"})
@@ -33,5 +32,5 @@ function main(archivefile)
if p and extensionset:has(filename:sub(p)) then i = p end
extension = filename:sub(i)
end
- return extension
+ return extensionset:has(extension) and extension or ""
end
diff --git a/xmake/modules/utils/archive/extract.lua b/xmake/modules/utils/archive/extract.lua
index 4e54bc4dc..d4a41e542 100644
--- a/xmake/modules/utils/archive/extract.lua
+++ b/xmake/modules/utils/archive/extract.lua
@@ -43,16 +43,23 @@ function _extract_using_tar(archivefile, outputdir, extension, opt)
return false
end
- -- on msys2/cygwin? we need translate input path to cygwin-like path
- if is_subhost("msys", "cygwin") and program:gsub("\\", "/"):find("/usr/bin") then
- archivefile = path.cygwin_path(archivefile)
- end
-
-- init argv
local argv = {}
- if is_subhost("windows") then
+ if is_host("windows") then
-- force "x:\\xx" as local file
- table.insert(argv, "--force-local")
+ local force_local = _g.force_local
+ if force_local == nil then
+ force_local = try {function ()
+ local result = os.iorunv(program, {"--help"})
+ if result and result:find("--force-local", 1, true) then
+ return true
+ end
+ end}
+ _g.force_local = force_local or false
+ end
+ if force_local then
+ table.insert(argv, "--force-local")
+ end
end
table.insert(argv, option.get("verbose") and "-xvf" or "-xf")
table.insert(argv, archivefile)
@@ -78,14 +85,10 @@ function _extract_using_tar(archivefile, outputdir, extension, opt)
-- extract it
if is_host("windows") then
- local oldir = os.cd(outputdir)
- os.vrunv(program, argv)
- os.cd(oldir)
+ os.vrunv(program, argv, {curdir = outputdir})
else
os.vrunv(program, argv)
end
-
- -- ok
return true
end
@@ -98,6 +101,12 @@ function _extract_using_7z(archivefile, outputdir, extension, opt)
return false
end
+ -- p7zip cannot extract other archive format on msys/cygwin
+ -- https://github.com/xmake-io/xmake/issues/1575#issuecomment-898205462
+ if is_subhost("msys", "cygwin") and extension ~= ".7z" and program:startswith("sh ") then
+ return false
+ end
+
-- extract to *.tar file first
local outputdir_old = nil
if extension:startswith(".tar.") or extension == ".tgz" then
@@ -140,7 +149,7 @@ function _extract_using_7z(archivefile, outputdir, extension, opt)
-- remove unused pax_global_header file after extracting .tar file
if extension == ".tar" then
os.tryrm(path.join(outputdir, "pax_global_header"))
- os.tryrm(path.join(outputdir, "PaxHeaders.*"))
+ os.tryrm(path.join(outputdir, "PaxHeaders*"))
os.tryrm(path.join(outputdir, "@PaxHeader"))
end
@@ -151,8 +160,6 @@ function _extract_using_7z(archivefile, outputdir, extension, opt)
return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt)
end
end
-
- -- ok
return true
end
@@ -192,14 +199,8 @@ function _extract_using_gzip(archivefile, outputdir, extension, opt)
os.cp(archivefile, tmpfile)
end
- -- enter outputdir
- local oldir = os.cd(outputdir)
-
-- extract it
- os.vrunv(program, argv)
-
- -- leave outputdir
- os.cd(oldir)
+ os.vrunv(program, argv, {curdir = outputdir})
-- continue to extract *.tar file
if outputdir_old then
@@ -208,8 +209,6 @@ function _extract_using_gzip(archivefile, outputdir, extension, opt)
return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt)
end
end
-
- -- ok
return true
end
@@ -249,14 +248,8 @@ function _extract_using_xz(archivefile, outputdir, extension, opt)
os.cp(archivefile, tmpfile)
end
- -- enter outputdir
- local oldir = os.cd(outputdir)
-
-- extract it
- os.vrunv(program, argv)
-
- -- leave outputdir
- os.cd(oldir)
+ os.vrunv(program, argv, {curdir = outputdir})
-- continue to extract *.tar file
if outputdir_old then
@@ -265,8 +258,6 @@ function _extract_using_xz(archivefile, outputdir, extension, opt)
return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt)
end
end
-
- -- ok
return true
end
@@ -320,8 +311,6 @@ function _extract_using_unzip(archivefile, outputdir, extension, opt)
return _extract(tarfile, outputdir_old, ".tar", {_extract_using_tar, _extract_using_7z}, opt)
end
end
-
- -- ok
return true
end
@@ -366,14 +355,8 @@ function _extract_using_bzip2(archivefile, outputdir, extension, opt)
os.cp(archivefile, tmpfile)
end
- -- enter outputdir
- local oldir = os.cd(outputdir)
-
-- extract it
- os.vrunv(program, argv)
-
- -- leave outputdir
- os.cd(oldir)
+ os.vrunv(program, argv, {curdir = outputdir})
-- continue to extract *.tar file
if outputdir_old then
@@ -382,22 +365,16 @@ function _extract_using_bzip2(archivefile, outputdir, extension, opt)
return _extract(tarfile, outputdir_old, ".tar", {_extract_using_7z, _extract_using_tar}, opt)
end
end
-
- -- ok
return true
end
-- extract archive file using extractors
function _extract(archivefile, outputdir, extension, extractors, opt)
-
- -- extract it
for _, extract in ipairs(extractors) do
if extract(archivefile, outputdir, extension, opt) then
return true
end
end
-
- -- failed
return false
end
@@ -417,7 +394,7 @@ function main(archivefile, outputdir, opt)
-- init extractors
local extractors
- if is_host("windows") then
+ if is_subhost("windows") then
-- we use 7z first, becase xmake package has builtin 7z program on windows
-- tar/windows can not extract .bz2 ...
extractors =
@@ -432,6 +409,7 @@ function main(archivefile, outputdir, opt)
, [".tar.gz"] = {_extract_using_7z, _extract_using_gzip}
, [".tar.xz"] = {_extract_using_7z, _extract_using_xz}
, [".tar.bz2"] = {_extract_using_7z, _extract_using_bzip2}
+ , [".tar.lz"] = {_extract_using_7z}
}
else
extractors =
@@ -446,6 +424,7 @@ function main(archivefile, outputdir, opt)
, [".tar.gz"] = {_extract_using_tar, _extract_using_7z, _extract_using_gzip}
, [".tar.xz"] = {_extract_using_tar, _extract_using_7z, _extract_using_xz}
, [".tar.bz2"] = {_extract_using_tar, _extract_using_7z, _extract_using_bzip2}
+ , [".tar.lz"] = {_extract_using_tar, _extract_using_7z}
}
end
diff --git a/xmake/modules/utils/archive/merge_staticlib.lua b/xmake/modules/utils/archive/merge_staticlib.lua
new file mode 100644
index 000000000..dc0130219
--- /dev/null
+++ b/xmake/modules/utils/archive/merge_staticlib.lua
@@ -0,0 +1,73 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file merge_staticlib.lua
+--
+
+-- imports
+import("core.base.option")
+import("private.tools.vstool")
+
+-- merge *.a archive libraries for ar
+function _merge_for_ar(target, program, outputfile, libraryfiles, opt)
+ opt = opt or {}
+ if target:is_plat("macosx", "iphoneos", "watchos", "appletvos") then
+ os.vrunv("libtool", table.join("-static", "-o", outputfile, libraryfiles))
+ else
+ local tmpfile = os.tmpfile()
+ local mrifile = io.open(tmpfile, "w")
+ mrifile:print("create %s", outputfile)
+ for _, libraryfile in ipairs(libraryfiles) do
+ mrifile:print("addlib %s", libraryfile)
+ end
+ mrifile:print("save")
+ mrifile:print("end")
+ mrifile:close()
+ os.vrunv(program, {"-M"}, {stdin = tmpfile})
+ os.rm(tmpfile)
+ end
+end
+
+-- merge *.a archive libraries for msvc/lib.exe
+function _merge_for_msvclib(target, program, outputfile, libraryfiles, opt)
+ opt = opt or {}
+ vstool.runv(program, table.join("-nologo", "-out:" .. outputfile, libraryfiles), {envs = opt.runenvs})
+end
+
+-- merge *.a archive libraries
+function main(target, outputfile, libraryfiles)
+ local program, toolname = target:tool("ar")
+ if program and toolname then
+ if toolname:find("ar") then
+ _merge_for_ar(target, program, outputfile, libraryfiles)
+ elseif toolname == "link" and target:is_plat("windows") then
+ local msvc
+ for _, toolchain_inst in ipairs(target:toolchains()) do
+ if toolchain_inst:name() == "msvc" then
+ msvc = toolchain_inst
+ break
+ end
+ end
+ _merge_for_msvclib(target, (program:gsub("link%.exe", "lib.exe")), outputfile, libraryfiles, {runenvs = msvc and msvc:runenvs()})
+ else
+ raise("cannot merge (%s): unknown ar tool %s!", table.concat(libraryfiles, ", "), toolname)
+ end
+ else
+ raise("cannot merge (%s): ar not found!", table.concat(libraryfiles, ", "))
+ end
+end
+
diff --git a/xmake/modules/utils/progress.lua b/xmake/modules/utils/progress.lua
new file mode 100644
index 000000000..074046a69
--- /dev/null
+++ b/xmake/modules/utils/progress.lua
@@ -0,0 +1,139 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-present, TBOOX Open Source Group.
+--
+-- @author OpportunityLiu
+-- @file progress.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.object")
+import("core.base.colors")
+import("core.base.tty")
+import("core.theme.theme")
+
+-- define module
+local process = process or object { _init = { "_RUNNING", "_INDEX", "_STREAM", "_OPT" } }
+
+-- stop the progress indicator, clear written frames
+function process:stop()
+ if self._RUNNING ~= 0 then
+ self:clear()
+ self._RUNNING = 0
+ self._INDEX = 0
+ end
+end
+
+function process:_clear()
+ if self._RUNNING == 1 then
+ tty.erase_line_to_end()
+ self._RUNNING = 2
+ return true
+ end
+end
+
+-- clear previous frame of the progress indicator
+function process:clear()
+ if self:_clear() then
+ self._STREAM:flush()
+ end
+end
+
+-- write next frame of the progress indicator
+function process:write()
+ local chars = self._OPT.chars[self._INDEX % #self._OPT.chars + 1]
+ tty.cursor_and_attrs_save()
+ self._STREAM:write(chars)
+ self._STREAM:flush()
+ tty.cursor_and_attrs_restore()
+ self._INDEX = self._INDEX + 1
+ self._RUNNING = 1
+end
+
+-- check if the progress indicator is running
+function process:running()
+ return self._RUNNING and true or false
+end
+
+-- showing progress line without scroll?
+function showing_without_scroll()
+ return _g.showing_without_scroll
+end
+
+-- show the message with process
+function show(progress, format, ...)
+ progress = math.floor(progress)
+ local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
+ if option.get("verbose") then
+ cprint(progress_prefix .. "${dim}" .. format, progress, ...)
+ else
+ local is_scroll = _g.is_scroll
+ if is_scroll == nil then
+ is_scroll = theme.get("text.build.progress_style") == "scroll"
+ _g.is_scroll = is_scroll
+ end
+ if is_scroll then
+ cprint(progress_prefix .. format, progress, ...)
+ else
+ tty.erase_line_to_start().cr()
+ local msg = vformat(progress_prefix .. format, progress, ...)
+ local msg_plain = colors.translate(msg, {plain = true})
+ local maxwidth = os.getwinsize().width
+ if #msg_plain <= maxwidth then
+ cprintf(msg)
+ else
+ -- windows width is too small? strip the partial message in middle
+ local partlen = math.floor(maxwidth / 2) - 3
+ local sep = msg_plain:sub(partlen + 1, #msg_plain - partlen - 1)
+ local split = msg:split(sep, {plain = true, strict = true})
+ cprintf(table.concat(split, "..."))
+ end
+ if math.floor(progress) == 100 then
+ print("")
+ _g.showing_without_scroll = false
+ else
+ _g.showing_without_scroll = true
+ end
+ io.flush()
+ end
+ end
+end
+
+-- get the message text with process
+function text(progress, format, ...)
+ progress = math.floor(progress)
+ local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
+ if option.get("verbose") then
+ return string.format(progress_prefix .. "${dim}" .. format, progress, ...)
+ else
+ return string.format(progress_prefix .. format, progress, ...)
+ end
+end
+
+-- build a progress indicator
+-- @params stream - stream to write to, will use io.stdout if not provided
+-- @params opt - options
+-- - chars - an array of chars for progress indicator
+function new(stream, opt)
+
+ -- set default values
+ stream = stream or io.stdout
+ opt = opt or {}
+ if opt.chars == nil or #opt.chars == 0 then
+ opt.chars = theme.get("text.spinner.chars")
+ end
+ return process {_OPT = opt, _STREAM = stream, _RUNNING = 0, _INDEX = 0}
+end