summaryrefslogtreecommitdiff
path: root/xmake/modules
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
parent885d00da8caf74aeed758d030b9a1b50d9078e1f (diff)
parent2431dd7e6142ff98b55741cfd4de4d2e69f4f8b5 (diff)
Merged from upstream/master
Diffstat (limited to 'xmake/modules')
-rw-r--r--xmake/modules/cli/amalgamate.lua108
-rw-r--r--xmake/modules/core/project/depend.lua15
-rw-r--r--xmake/modules/core/tools/ar.lua18
-rw-r--r--xmake/modules/core/tools/armar.lua26
-rw-r--r--xmake/modules/core/tools/armasm.lua179
-rw-r--r--xmake/modules/core/tools/armcc.lua183
-rw-r--r--xmake/modules/core/tools/armclang.lua32
-rw-r--r--xmake/modules/core/tools/armlink.lua61
-rw-r--r--xmake/modules/core/tools/circle.lua34
-rw-r--r--xmake/modules/core/tools/cl.lua85
-rw-r--r--xmake/modules/core/tools/clang.lua13
-rw-r--r--xmake/modules/core/tools/clang_cl.lua10
-rw-r--r--xmake/modules/core/tools/dmd.lua8
-rw-r--r--xmake/modules/core/tools/fpc.lua110
-rw-r--r--xmake/modules/core/tools/gcc.lua56
-rw-r--r--xmake/modules/core/tools/go.lua38
-rw-r--r--xmake/modules/core/tools/ml.lua43
-rw-r--r--xmake/modules/core/tools/nim.lua161
-rw-r--r--xmake/modules/core/tools/nvcc.lua32
-rw-r--r--xmake/modules/core/tools/rc.lua2
-rw-r--r--xmake/modules/core/tools/rustc.lua82
-rw-r--r--xmake/modules/core/tools/sdcc.lua33
-rw-r--r--xmake/modules/core/tools/zig.lua9
-rw-r--r--xmake/modules/detect/sdks/find_iccenv.lua21
-rw-r--r--xmake/modules/detect/sdks/find_ifortenv.lua28
-rw-r--r--xmake/modules/detect/sdks/find_mdk.lua123
-rw-r--r--xmake/modules/detect/sdks/find_mingw.lua3
-rw-r--r--xmake/modules/detect/sdks/find_ndk.lua20
-rw-r--r--xmake/modules/detect/sdks/find_qt.lua30
-rw-r--r--xmake/modules/detect/sdks/find_vstudio.lua113
-rw-r--r--xmake/modules/detect/tools/circle/has_flags.lua23
-rw-r--r--xmake/modules/detect/tools/cl/cfeatures.lua5
-rw-r--r--xmake/modules/detect/tools/cl/cxxfeatures.lua10
-rw-r--r--xmake/modules/detect/tools/cl/has_flags.lua8
-rw-r--r--xmake/modules/detect/tools/clang/cfeatures.lua8
-rw-r--r--xmake/modules/detect/tools/clang/cxxfeatures.lua12
-rw-r--r--xmake/modules/detect/tools/clang_cl/has_flags.lua2
-rw-r--r--xmake/modules/detect/tools/dmd/has_flags.lua2
-rw-r--r--xmake/modules/detect/tools/find_7z.lua5
-rw-r--r--xmake/modules/detect/tools/find_armar.lua65
-rw-r--r--xmake/modules/detect/tools/find_armasm.lua65
-rw-r--r--xmake/modules/detect/tools/find_armcc.lua60
-rw-r--r--xmake/modules/detect/tools/find_armclang.lua59
-rw-r--r--xmake/modules/detect/tools/find_armlink.lua65
-rw-r--r--xmake/modules/detect/tools/find_cargo.lua52
-rw-r--r--xmake/modules/detect/tools/find_circle.lua52
-rw-r--r--xmake/modules/detect/tools/find_cxxbridge.lua52
-rw-r--r--xmake/modules/detect/tools/find_fpc.lua52
-rw-r--r--xmake/modules/detect/tools/find_glslangValidator.lua52
-rw-r--r--xmake/modules/detect/tools/find_glslc.lua61
-rw-r--r--xmake/modules/detect/tools/find_ifort.lua1
-rw-r--r--xmake/modules/detect/tools/find_llvm_as.lua57
-rw-r--r--xmake/modules/detect/tools/find_make.lua53
-rw-r--r--xmake/modules/detect/tools/find_metal.lua50
-rw-r--r--xmake/modules/detect/tools/find_metallib.lua50
-rw-r--r--xmake/modules/detect/tools/find_nim.lua52
-rw-r--r--xmake/modules/detect/tools/find_nimble.lua52
-rw-r--r--xmake/modules/detect/tools/find_pkg_config.lua2
-rw-r--r--xmake/modules/detect/tools/find_pkgconf.lua52
-rw-r--r--xmake/modules/detect/tools/find_swig.lua53
-rw-r--r--xmake/modules/detect/tools/fpc/has_flags.lua98
-rw-r--r--xmake/modules/detect/tools/gcc/cfeatures.lua7
-rw-r--r--xmake/modules/detect/tools/gcc/cxxfeatures.lua65
-rw-r--r--xmake/modules/detect/tools/gcc/has_flags.lua39
-rw-r--r--xmake/modules/detect/tools/go/has_flags.lua2
-rw-r--r--xmake/modules/detect/tools/ml/has_flags.lua11
-rw-r--r--xmake/modules/detect/tools/nim/has_flags.lua98
-rw-r--r--xmake/modules/detect/tools/rc/has_flags.lua68
-rw-r--r--xmake/modules/detect/tools/rustc/has_flags.lua30
-rw-r--r--xmake/modules/detect/tools/sdcc/has_flags.lua2
-rw-r--r--xmake/modules/detect/tools/swiftc/has_flags.lua2
-rw-r--r--xmake/modules/detect/tools/zig/has_flags.lua2
-rw-r--r--xmake/modules/devel/git/apply.lua13
-rw-r--r--xmake/modules/devel/git/checkout.lua13
-rw-r--r--xmake/modules/devel/git/clean.lua13
-rw-r--r--xmake/modules/devel/git/lastcommit.lua66
-rw-r--r--xmake/modules/devel/git/pull.lua15
-rw-r--r--xmake/modules/devel/git/reset.lua13
-rw-r--r--xmake/modules/devel/git/submodule/update.lua21
-rw-r--r--xmake/modules/lib/detect/check_cxsnippets.lua59
-rw-r--r--xmake/modules/lib/detect/features.lua5
-rw-r--r--xmake/modules/lib/detect/find_package.lua29
-rw-r--r--xmake/modules/lib/detect/pkgconfig.lua20
-rw-r--r--xmake/modules/net/ping.lua2
-rw-r--r--xmake/modules/package/manager/apt/find_package.lua72
-rw-r--r--xmake/modules/package/manager/brew/find_package.lua10
-rw-r--r--xmake/modules/package/manager/cargo/configurations.lua28
-rw-r--r--xmake/modules/package/manager/cargo/find_package.lua58
-rw-r--r--xmake/modules/package/manager/cargo/install_package.lua95
-rw-r--r--xmake/modules/package/manager/clib/configurations.lua30
-rw-r--r--xmake/modules/package/manager/clib/install_package.lua21
-rw-r--r--xmake/modules/package/manager/cmake/configurations.lua31
-rw-r--r--xmake/modules/package/manager/cmake/find_package.lua282
-rw-r--r--xmake/modules/package/manager/conan/configurations.lua33
-rw-r--r--xmake/modules/package/manager/conan/find_package.lua2
-rw-r--r--xmake/modules/package/manager/conan/install_package.lua44
-rw-r--r--xmake/modules/package/manager/conda/find_package.lua4
-rw-r--r--xmake/modules/package/manager/dub/find_package.lua4
-rw-r--r--xmake/modules/package/manager/dub/install_package.lua2
-rw-r--r--xmake/modules/package/manager/find_package.lua4
-rw-r--r--xmake/modules/package/manager/install_package.lua4
-rw-r--r--xmake/modules/package/manager/nimble/find_package.lua67
-rw-r--r--xmake/modules/package/manager/nimble/install_package.lua58
-rw-r--r--xmake/modules/package/manager/pacman/find_package.lua124
-rw-r--r--xmake/modules/package/manager/pkgconfig/find_package.lua1
-rw-r--r--xmake/modules/package/manager/system/find_package.lua97
-rw-r--r--xmake/modules/package/manager/vcpkg/configurations.lua48
-rw-r--r--xmake/modules/package/manager/vcpkg/find_package.lua130
-rw-r--r--xmake/modules/package/manager/vcpkg/install_package.lua151
-rw-r--r--xmake/modules/package/manager/xmake/find_package.lua54
-rw-r--r--xmake/modules/package/manager/xmake/search_package.lua5
-rw-r--r--xmake/modules/package/tools/autoconf.lua136
-rw-r--r--xmake/modules/package/tools/cmake.lua61
-rw-r--r--xmake/modules/package/tools/make.lua61
-rw-r--r--xmake/modules/package/tools/meson.lua107
-rw-r--r--xmake/modules/package/tools/ninja.lua11
-rw-r--r--xmake/modules/package/tools/scons.lua2
-rw-r--r--xmake/modules/package/tools/xmake.lua19
-rw-r--r--xmake/modules/private/action/build/object.lua8
-rw-r--r--xmake/modules/private/action/require/impl/actions/download.lua35
-rw-r--r--xmake/modules/private/action/require/impl/actions/download_resources.lua6
-rw-r--r--xmake/modules/private/action/require/impl/actions/install.lua58
-rw-r--r--xmake/modules/private/action/require/impl/actions/patch_sources.lua3
-rw-r--r--xmake/modules/private/action/require/impl/install_packages.lua38
-rw-r--r--xmake/modules/private/action/require/impl/lock_packages.lua72
-rw-r--r--xmake/modules/private/action/require/impl/package.lua178
-rw-r--r--xmake/modules/private/action/require/impl/packagenv.lua2
-rw-r--r--xmake/modules/private/action/require/impl/register_packages.lua13
-rw-r--r--xmake/modules/private/action/require/impl/remove_packages.lua2
-rw-r--r--xmake/modules/private/action/require/impl/repository.lua142
-rw-r--r--xmake/modules/private/action/require/impl/search_packages.lua2
-rw-r--r--xmake/modules/private/action/require/impl/utils/requirekey.lua60
-rw-r--r--xmake/modules/private/action/require/install.lua2
-rw-r--r--xmake/modules/private/action/trybuild/autotools.lua3
-rw-r--r--xmake/modules/private/action/trybuild/cmake.lua3
-rw-r--r--xmake/modules/private/action/trybuild/meson.lua3
-rw-r--r--xmake/modules/private/async/jobpool.lua15
-rw-r--r--xmake/modules/private/async/runjobs.lua4
-rw-r--r--xmake/modules/private/tools/gcc/parse_deps.lua18
-rw-r--r--xmake/modules/private/utils/batchcmds.lua22
-rw-r--r--xmake/modules/private/utils/bin2c.lua11
-rw-r--r--xmake/modules/private/xrepo/action/env.lua177
-rw-r--r--xmake/modules/private/xrepo/action/export.lua2
-rw-r--r--xmake/modules/private/xrepo/action/fetch.lua2
-rw-r--r--xmake/modules/private/xrepo/action/import.lua2
-rw-r--r--xmake/modules/private/xrepo/action/info.lua2
-rw-r--r--xmake/modules/private/xrepo/action/install.lua4
-rw-r--r--xmake/modules/private/xrepo/action/remove.lua2
-rw-r--r--xmake/modules/target/action/install/cmake_importfiles.lua101
-rw-r--r--xmake/modules/target/action/install/main.lua11
-rw-r--r--xmake/modules/target/action/install/pkgconfig_importfiles.lua25
-rw-r--r--xmake/modules/target/action/install/unix.lua95
-rw-r--r--xmake/modules/target/action/install/windows.lua28
-rw-r--r--xmake/modules/target/action/uninstall/unix.lua72
-rw-r--r--xmake/modules/target/action/uninstall/windows.lua11
-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.lua (renamed from xmake/modules/private/utils/progress.lua)2
159 files changed, 5795 insertions, 951 deletions
diff --git a/xmake/modules/cli/amalgamate.lua b/xmake/modules/cli/amalgamate.lua
new file mode 100644
index 000000000..a9835eda6
--- /dev/null
+++ b/xmake/modules/cli/amalgamate.lua
@@ -0,0 +1,108 @@
+--!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 amalgamate.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.config")
+import("core.project.task")
+import("core.project.project")
+
+-- the options
+local options =
+{
+ {'u', "uniqueid", "kv", nil, "Set the unique id." },
+ {'o', "outputdir", "kv", nil, "Set the output directory."},
+ {nil, "target", "v", nil, "The target name." }
+}
+
+-- generate code
+function _generate_amalgamate_code(target, opt)
+
+ -- only for library/binary
+ if not target:is_library() and not target:is_binary() then
+ return
+ end
+
+ -- generate source code
+ local outputdir = opt.outputdir
+ local uniqueid = opt.uniqueid
+ for _, sourcebatch in pairs(target:sourcebatches()) do
+ local sourcekind = sourcebatch.sourcekind
+ if sourcekind == "cc" or sourcekind == "cxx" then
+ local outputpath = path.join(outputdir, target:name() .. (sourcekind == "cxx" and ".cpp" or ".c"))
+ local outputfile = io.open(outputpath, "w")
+ for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
+ if uniqueid then
+ outputfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1])
+ end
+ outputfile:write(io.readfile(sourcefile))
+ if uniqueid then
+ outputfile:print("#undef %s", uniqueid)
+ end
+ end
+ outputfile:close()
+ cprint("${bright}%s generated!", outputpath)
+ end
+ end
+
+ -- generate header file
+ local srcheaders = target:headerfiles(includedir)
+ if srcheaders and #srcheaders > 0 then
+ local outputpath = path.join(outputdir, target:name() .. ".h")
+ local outputfile = io.open(outputpath, "w")
+ for _, srcheader in ipairs(srcheaders) do
+ if uniqueid then
+ outputfile:print("#define %s %s", uniqueid, "unity_" .. hash.uuid():split("-", {plain = true})[1])
+ end
+ outputfile:write(io.readfile(srcheader))
+ if uniqueid then
+ outputfile:print("#undef %s", uniqueid)
+ end
+ end
+ outputfile:close()
+ cprint("${bright}%s generated!", outputpath)
+ end
+end
+
+-- generate amalgamate code
+--
+-- https://github.com/xmake-io/xmake/issues/1438
+--
+function main(...)
+
+ -- parse arguments
+ local argv = table.pack(...)
+ local args = option.parse(argv, options, "Generate amalgamate code.",
+ "",
+ "Usage: xmake l cli.amalgamate [options]")
+
+ -- config first
+ task.run("config")
+
+ -- generate amalgamate code
+ args.outputdir = args.outputdir or config.buildir()
+ if args.target then
+ _generate_amalgamate_code(args.target, args)
+ else
+ for _, target in ipairs(project.ordertargets()) do
+ _generate_amalgamate_code(target, args)
+ end
+ end
+end
diff --git a/xmake/modules/core/project/depend.lua b/xmake/modules/core/project/depend.lua
index cb25db359..89a517c07 100644
--- a/xmake/modules/core/project/depend.lua
+++ b/xmake/modules/core/project/depend.lua
@@ -78,8 +78,8 @@ end
function is_changed(dependinfo, opt)
-- empty depend info? always be changed
- local files = dependinfo.files or {}
- local values = dependinfo.values or {}
+ local files = table.wrap(dependinfo.files)
+ local values = table.wrap(dependinfo.values)
if #files == 0 and #values == 0 then
return true
end
@@ -102,7 +102,7 @@ function is_changed(dependinfo, opt)
-- check the dependent values are changed?
local depvalues = values
- local optvalues = opt.values or {}
+ local optvalues = table.wrap(opt.values)
if #depvalues ~= #optvalues then
return true
end
@@ -124,8 +124,11 @@ function is_changed(dependinfo, opt)
end
-- check the dependent files list are changed?
- local optfiles = opt.files
- if optfiles then
+ if opt.files then
+ local optfiles = table.wrap(opt.files)
+ if #files ~= #optfiles then
+ return true
+ end
for idx, file in ipairs(files) do
if file ~= optfiles[idx] then
return true
@@ -178,7 +181,7 @@ function on_changed(callback, opt)
-- need build this object?
-- @note we use mtime(dependfile) instead of mtime(objectfile) to ensure the object file is is fully compiled.
-- @see https://github.com/xmake-io/xmake/issues/748
- if not is_changed(dependinfo, {lastmtime = opt.lastmtime or os.mtime(dependfile), values = opt.values}) then
+ if not is_changed(dependinfo, {lastmtime = opt.lastmtime or os.mtime(dependfile), values = opt.values, files = opt.files}) then
return
end
diff --git a/xmake/modules/core/tools/ar.lua b/xmake/modules/core/tools/ar.lua
index dc858a19e..0496238b4 100644
--- a/xmake/modules/core/tools/ar.lua
+++ b/xmake/modules/core/tools/ar.lua
@@ -20,7 +20,7 @@
-- imports
import("core.tool.compiler")
-import("private.utils.progress")
+import("utils.progress")
-- init it
function init(self)
@@ -30,42 +30,26 @@ end
-- make the strip flag
function strip(self, level)
-
- -- the maps
local maps =
{
debug = "-S"
, all = "-s"
}
-
- -- make it
return maps[level]
end
-- make the link arguments list
function linkargv(self, objectfiles, targetkind, targetfile, flags, opt)
-
- -- check
- assert(targetkind == "static")
-
- -- init arguments
opt = opt or {}
local argv = table.join(flags, targetfile, objectfiles)
if is_host("windows") and not opt.rawargs then
argv = winos.cmdargv(argv, {escape = true})
end
-
- -- make it
return self:program(), argv
end
-- link the library file
function link(self, objectfiles, targetkind, targetfile, flags)
-
- -- check
- assert(targetkind == "static", "the target kind: %s is not support for ar", targetkind)
-
- -- ensure the target directory
os.mkdir(path.directory(targetfile))
-- @note remove the previous archived file first to force recreating a new file
diff --git a/xmake/modules/core/tools/armar.lua b/xmake/modules/core/tools/armar.lua
new file mode 100644
index 000000000..66740c11a
--- /dev/null
+++ b/xmake/modules/core/tools/armar.lua
@@ -0,0 +1,26 @@
+--!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 armar.lua
+--
+
+inherit("ar")
+
+function init(self)
+ _super.init(self)
+end
+
diff --git a/xmake/modules/core/tools/armasm.lua b/xmake/modules/core/tools/armasm.lua
new file mode 100644
index 000000000..3ae578c55
--- /dev/null
+++ b/xmake/modules/core/tools/armasm.lua
@@ -0,0 +1,179 @@
+--!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 armasm.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.global")
+import("core.language.language")
+import("utils.progress")
+
+-- init it
+function init(self)
+end
+
+-- make the symbol flag
+function nf_symbol(self, level)
+ -- only for source kind
+ local kind = self:kind()
+ if language.sourcekinds()[kind] then
+ local maps = _g.symbol_maps
+ if not maps then
+ maps =
+ {
+ debug = "-g"
+ }
+ _g.symbol_maps = maps
+ end
+ return maps[level .. '_' .. kind] or maps[level]
+ end
+end
+
+-- make the optimize flag
+function nf_optimize(self, level)
+ local maps =
+ {
+ none = "-O0"
+ , fast = "-O1"
+ , faster = "-O2"
+ , fastest = "-O3"
+ , smallest = "-Os"
+ , aggressive = "-Ofast"
+ }
+ return maps[level]
+end
+
+-- make the language flag
+function nf_language(self, stdname)
+
+ -- the stdc maps
+ if _g.cmaps == nil then
+ _g.cmaps =
+ {
+ ansi = "-c89"
+ , c89 = "-c89"
+ , gnu89 = "-c89"
+ , c99 = "-c99"
+ , gnu99 = "-c99"
+ , c11 = "-c11"
+ , gnu11 = "-c11"
+ , clatest = {"-c11", "-c99", "-c89"}
+ , gnulatest = {"-c11", "-c99", "-c89"}
+ }
+ end
+ local maps = _g.cmaps
+ local result = maps[stdname]
+ if type(result) == "table" then
+ for _, v in ipairs(result) do
+ if self:has_flags(v, "cxflags") then
+ result = v
+ maps[stdname] = result
+ return result
+ end
+ end
+ else
+ return result
+ end
+end
+
+-- make runtime flag
+function nf_runtime(self, runtime)
+ if runtime == "microlib" then
+ return {"--pd", "__MICROLIB SETA 1"}
+ end
+end
+
+-- make the define flag
+function nf_define(self, macro)
+ return {"--pd", macro .. " SETA 1"}
+end
+
+-- make the includedir flag
+function nf_includedir(self, dir)
+ return {"-I" .. dir}
+end
+
+-- make the sysincludedir flag
+function nf_sysincludedir(self, dir)
+ return nf_includedir(self, dir)
+end
+
+-- make the compile arguments list
+function compargv(self, sourcefile, objectfile, flags)
+ return self:program(), table.join(flags, "-o", objectfile, sourcefile)
+end
+
+-- compile the source file
+function compile(self, sourcefile, objectfile, dependinfo, flags)
+
+ -- ensure the object directory
+ os.mkdir(path.directory(objectfile))
+
+ -- compile it
+ try
+ {
+ function ()
+ local outdata, errdata = os.iorunv(compargv(self, sourcefile, objectfile, flags))
+ return (outdata or "") .. (errdata or "")
+ end,
+ catch
+ {
+ function (errors)
+
+ -- try removing the old object file for forcing to rebuild this source file
+ os.tryrm(objectfile)
+
+ -- find the start line of error
+ local lines = tostring(errors):split("\n")
+ local start = 0
+ for index, line in ipairs(lines) do
+ if line:find("error:", 1, true) or line:find("错误:", 1, true) then
+ start = index
+ break
+ end
+ end
+
+ -- get 16 lines of errors
+ if start > 0 or not option.get("verbose") then
+ if start == 0 then start = 1 end
+ errors = table.concat(table.slice(lines, start, start + ((#lines - start > 16) and 16 or (#lines - start))), "\n")
+ end
+
+ -- raise compiling errors
+ raise(errors)
+ end
+ },
+ finally
+ {
+ function (ok, warnings)
+
+ -- print some warnings
+ if warnings and #warnings > 0 and (option.get("verbose") or option.get("warning") or global.get("build_warning")) then
+ if progress.showing_without_scroll() then
+ print("")
+ end
+ cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n'))
+ end
+ end
+ }
+ }
+end
+
+
+
diff --git a/xmake/modules/core/tools/armcc.lua b/xmake/modules/core/tools/armcc.lua
new file mode 100644
index 000000000..403e143f0
--- /dev/null
+++ b/xmake/modules/core/tools/armcc.lua
@@ -0,0 +1,183 @@
+--!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 armcc.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.global")
+import("core.language.language")
+import("utils.progress")
+
+-- init it
+function init(self)
+end
+
+-- make the symbol flag
+function nf_symbol(self, level)
+ -- only for source kind
+ local kind = self:kind()
+ if language.sourcekinds()[kind] then
+ local maps = _g.symbol_maps
+ if not maps then
+ maps =
+ {
+ debug = "-g"
+ }
+ _g.symbol_maps = maps
+ end
+ return maps[level .. '_' .. kind] or maps[level]
+ end
+end
+
+-- make runtime flag
+function nf_runtime(self, runtime)
+ if runtime == "microlib" then
+ return "-D__MICROLIB"
+ end
+end
+
+-- make the optimize flag
+function nf_optimize(self, level)
+ local maps =
+ {
+ none = "-O0"
+ , fast = "-O1"
+ , faster = "-O2"
+ , fastest = "-O3"
+ , smallest = "-Os"
+ , aggressive = "-Ofast"
+ }
+ return maps[level]
+end
+
+-- make the language flag
+function nf_language(self, stdname)
+
+ -- the stdc maps
+ if _g.cmaps == nil then
+ _g.cmaps =
+ {
+ ansi = "-c89"
+ , c89 = "-c89"
+ , gnu89 = "-c89"
+ , c99 = "-c99"
+ , gnu99 = "-c99"
+ , c11 = "-c11"
+ , gnu11 = "-c11"
+ , clatest = {"-c11", "-c99", "-c89"}
+ , gnulatest = {"-c11", "-c99", "-c89"}
+ }
+ end
+ local maps = _g.cmaps
+ local result = maps[stdname]
+ if type(result) == "table" then
+ for _, v in ipairs(result) do
+ if self:has_flags(v, "cxflags") then
+ result = v
+ maps[stdname] = result
+ return result
+ end
+ end
+ else
+ return result
+ end
+end
+
+-- make the define flag
+function nf_define(self, macro)
+ return "-D" .. macro
+end
+
+-- make the undefine flag
+function nf_undefine(self, macro)
+ return "-U" .. macro
+end
+
+-- make the includedir flag
+function nf_includedir(self, dir)
+ return {"-I" .. dir}
+end
+
+-- make the sysincludedir flag
+function nf_sysincludedir(self, dir)
+ return nf_includedir(self, dir)
+end
+
+-- make the compile arguments list
+function compargv(self, sourcefile, objectfile, flags)
+ return self:program(), table.join("-c", flags, "-o", objectfile, sourcefile)
+end
+
+-- compile the source file
+function compile(self, sourcefile, objectfile, dependinfo, flags)
+
+ -- ensure the object directory
+ os.mkdir(path.directory(objectfile))
+
+ -- compile it
+ try
+ {
+ function ()
+ local outdata, errdata = os.iorunv(compargv(self, sourcefile, objectfile, flags))
+ return (outdata or "") .. (errdata or "")
+ end,
+ catch
+ {
+ function (errors)
+
+ -- try removing the old object file for forcing to rebuild this source file
+ os.tryrm(objectfile)
+
+ -- find the start line of error
+ local lines = tostring(errors):split("\n")
+ local start = 0
+ for index, line in ipairs(lines) do
+ if line:find("error:", 1, true) or line:find("错误:", 1, true) then
+ start = index
+ break
+ end
+ end
+
+ -- get 16 lines of errors
+ if start > 0 or not option.get("verbose") then
+ if start == 0 then start = 1 end
+ errors = table.concat(table.slice(lines, start, start + ((#lines - start > 16) and 16 or (#lines - start))), "\n")
+ end
+
+ -- raise compiling errors
+ raise(errors)
+ end
+ },
+ finally
+ {
+ function (ok, warnings)
+
+ -- print some warnings
+ if warnings and #warnings > 0 and (option.get("verbose") or option.get("warning") or global.get("build_warning")) then
+ if progress.showing_without_scroll() then
+ print("")
+ end
+ cprint("${color.warning}%s", table.concat(table.slice(warnings:split('\n'), 1, 8), '\n'))
+ end
+ end
+ }
+ }
+end
+
+
diff --git a/xmake/modules/core/tools/armclang.lua b/xmake/modules/core/tools/armclang.lua
new file mode 100644
index 000000000..dcec82015
--- /dev/null
+++ b/xmake/modules/core/tools/armclang.lua
@@ -0,0 +1,32 @@
+--!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 armclang.lua
+--
+
+inherit("gcc")
+
+function init(self)
+ _super.init(self)
+end
+
+-- make runtime flag
+function nf_runtime(self, runtime)
+ if runtime == "microlib" then
+ return "-D__MICROLIB"
+ end
+end
diff --git a/xmake/modules/core/tools/armlink.lua b/xmake/modules/core/tools/armlink.lua
new file mode 100644
index 000000000..e25a81967
--- /dev/null
+++ b/xmake/modules/core/tools/armlink.lua
@@ -0,0 +1,61 @@
+--!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 armlink.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.global")
+import("utils.progress")
+
+function init(self)
+end
+
+-- make the link flag
+function nf_link(self, lib)
+ return "lib" .. lib .. ".a"
+end
+
+-- make the syslink flag
+function nf_syslink(self, lib)
+ return nf_link(self, lib)
+end
+
+-- make the linkdir flag
+function nf_linkdir(self, dir)
+ return {"--userlibpath", dir}
+end
+
+-- make runtime flag
+function nf_runtime(self, runtime)
+ if runtime == "microlib" then
+ return "--library_type=microlib"
+ end
+end
+
+-- make the link arguments list
+function linkargv(self, objectfiles, targetkind, targetfile, flags)
+ return self:program(), table.join("-o", targetfile, objectfiles, flags)
+end
+
+-- link the target file
+function link(self, objectfiles, targetkind, targetfile, flags)
+ os.mkdir(path.directory(targetfile))
+ os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags))
+end
+
diff --git a/xmake/modules/core/tools/circle.lua b/xmake/modules/core/tools/circle.lua
new file mode 100644
index 000000000..fcf567549
--- /dev/null
+++ b/xmake/modules/core/tools/circle.lua
@@ -0,0 +1,34 @@
+--!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 circle.lua
+--
+
+inherit("gcc")
+
+function init(self)
+ _super.init(self)
+end
+
+function nf_strip(self, level)
+ local maps =
+ {
+ debug = "-Wl,-S"
+ , all = "-Wl,-s"
+ }
+ return maps[level]
+end
diff --git a/xmake/modules/core/tools/cl.lua b/xmake/modules/core/tools/cl.lua
index d95d58e5d..b76061cd7 100644
--- a/xmake/modules/core/tools/cl.lua
+++ b/xmake/modules/core/tools/cl.lua
@@ -26,7 +26,7 @@ import("core.project.project")
import("core.language.language")
import("private.tools.vstool")
import("private.tools.cl.parse_include")
-import("private.utils.progress")
+import("utils.progress")
-- init it
function init(self)
@@ -34,12 +34,6 @@ function init(self)
-- init cxflags
self:set("cxflags", "-nologo")
- -- we need show full file path to goto error position if xmake is called in vstudio
- -- https://github.com/xmake-io/xmake/issues/1049
- if os.getenv("XMAKE_IN_VSTUDIO") then
- self:add("cxflags", "-FC")
- end
-
-- init flags map
self:set("mapflags",
{
@@ -62,6 +56,8 @@ function init(self)
, ["-W2"] = "-W2"
, ["-W3"] = "-W3"
, ["-Werror"] = "-WX"
+ , ["-Wswitch"] = "-we4062"
+ , ["-Wswitch-enum"] = "-we4061"
, ["%-Wno%-error=.*"] = ""
, ["%-fno%-.*"] = ""
@@ -116,7 +112,7 @@ function nf_symbols(self, levels, target)
end
-- check and add symbol output file
- local pdbflags = "-Fd" .. path.join(symboldir, "compile." .. path.filename(symbolfile))
+ local pdbflags = "-Fd" .. (target:is_static() and symbolfile or path.join(symboldir, "compile." .. path.filename(symbolfile)))
if self:has_flags({"-FS", "-Fd" .. os.nuldev() .. ".pdb"}, "cxflags", { flagskey = "-FS -Fd" }) then
pdbflags = {"-FS", pdbflags}
end
@@ -197,12 +193,14 @@ function nf_language(self, stdname)
_g.cmaps =
{
-- stdc
- c99 = "-TP" -- compile as c++ files because older msvc only support c89
- , gnu99 = "-TP"
- , c11 = {"-std:c11", "-TP"}
- , gnu11 = {"-std:c11", "-TP"}
- , c17 = {"-std:c17", "-TP"}
- , gnu17 = {"-std:c17", "-TP"}
+ c99 = "-TP" -- compile as c++ files because older msvc only support c89
+ , gnu99 = "-TP"
+ , c11 = {"-std:c11", "-TP"}
+ , gnu11 = {"-std:c11", "-TP"}
+ , c17 = {"-std:c17", "-TP"}
+ , gnu17 = {"-std:c17", "-TP"}
+ , clatest = {"-std:c17", "-std:c11"}
+ , gnulatest = {"-std:c17", "-std:c11"}
}
end
@@ -222,6 +220,8 @@ function nf_language(self, stdname)
, gnuxx20 = {"-std:c++20", "-std:c++latest"}
, cxx2a = {"-std:c++20", "-std:c++latest"}
, gnuxx2a = {"-std:c++20", "-std:c++latest"}
+ , cxxlatest = "-std:c++latest"
+ , gnuxxlatest = "-std:c++latest"
}
local cxxmaps2 = {}
for k, v in pairs(_g.cxxmaps) do
@@ -237,13 +237,17 @@ function nf_language(self, stdname)
end
-- map it
- local flags = maps[stdname]
- if flags then
- for _, flag in ipairs(table.wrap(flags)) do
- if self:has_flags(flag, "cxflags") then
- return flag
+ local result = maps[stdname]
+ if type(result) == "table" then
+ for _, v in ipairs(result) do
+ if self:has_flags(v, "cxflags") then
+ result = v
+ maps[stdname] = result
+ return result
end
end
+ else
+ return result
end
end
@@ -266,13 +270,17 @@ end
function nf_sysincludedir(self, dir)
local has_external_includedir = _g._HAS_EXTERNAL_INCLUDEDIR
if has_external_includedir == nil then
- if self:has_flags({"-experimental:external", "-external:W0", "-external:I" .. os.args(path.translate(dir))}, "cxflags", {flagskey = "cl_external_includedir"}) then
- has_external_includedir = true
+ if self:has_flags({"-external:W0", "-external:I" .. os.args(path.translate(dir))}, "cxflags", {flagskey = "cl_external_includedir"}) then
+ has_external_includedir = 2 -- full support
+ elseif self:has_flags({"-experimental:external", "-external:W0", "-external:I" .. os.args(path.translate(dir))}, "cxflags", {flagskey = "cl_external_includedir_experimental"}) then
+ has_external_includedir = 1 -- experimental support
end
- has_external_includedir = has_external_includedir or false
+ has_external_includedir = has_external_includedir or 0
_g._HAS_EXTERNAL_INCLUDEDIR = has_external_includedir
end
- if has_external_includedir then
+ if has_external_includedir >= 2 then
+ return {"-external:W0", "-external:I" .. path.translate(dir)}
+ elseif has_external_includedir >= 1 then
return {"-experimental:external", "-external:W0", "-external:I" .. path.translate(dir)}
else
return nf_includedir(self, dir)
@@ -371,6 +379,15 @@ function _has_source_dependencies(self)
return has_source_dependencies
end
+function _is_in_vstudio()
+ local is_in_vstudio = _g._IS_IN_VSTUDIO
+ if is_in_vstudio == nil then
+ is_in_vstudio = os.getenv("XMAKE_IN_VSTUDIO") or false
+ _g._IS_IN_VSTUDIO = is_in_vstudio
+ end
+ return is_in_vstudio
+end
+
-- make the compile arguments list
function compargv(self, sourcefile, objectfile, flags, opt)
@@ -403,6 +420,7 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt)
-- generate includes file
local compflags = flags
+
if dependinfo then
if _has_source_dependencies(self) then
depfile = os.tmpfile()
@@ -412,6 +430,16 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt)
end
end
+ -- we need show full file path to goto error position if xmake is called in vstudio
+ -- https://github.com/xmake-io/xmake/issues/1049
+ if _is_in_vstudio() then
+ if compflags == flags then
+ compflags = table.join(flags, "-FC")
+ else
+ table.join2(compflags, "-FC")
+ end
+ end
+
-- use vstool to compile and enable vs_unicode_output @see https://github.com/xmake-io/xmake/issues/528
local program, argv = compargv(self, sourcefile, objectfile, compflags, opt)
return vstool.iorunv(program, argv, {envs = self:runenvs()})
@@ -444,7 +472,10 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt)
end
end
end
- os.raise(results)
+ if not option.get("verbose") then
+ results = results .. "\n ${yellow}> in ${bright}" .. sourcefile
+ end
+ raise(results)
end
},
finally
@@ -466,7 +497,10 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt)
end
end
if #lines > 0 then
- local warnings = table.concat(table.slice(lines, 1, (#lines > 8 and 8 or #lines)), "\r\n")
+ if not option.get("diagnosis") then
+ lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines))
+ end
+ local warnings = table.concat(lines, "\r\n")
if progress.showing_without_scroll() then
print("")
end
@@ -488,4 +522,3 @@ function compile(self, sourcefile, objectfile, dependinfo, flags, opt)
end
end
end
-
diff --git a/xmake/modules/core/tools/clang.lua b/xmake/modules/core/tools/clang.lua
index a0d39f3b4..e5734a953 100644
--- a/xmake/modules/core/tools/clang.lua
+++ b/xmake/modules/core/tools/clang.lua
@@ -124,3 +124,16 @@ function nf_warning(self, level)
}
return maps[level]
end
+
+-- make the symbol flag
+function nf_symbol(self, level)
+ local kind = self:kind()
+ if kind == "ld" or kind == "sh" then
+ -- clang/windows need add `-g` to linker to generate pdb symbol file
+ if self:plat() == "windows" and level == "debug" then
+ return "-g"
+ end
+ else
+ return _super.nf_symbol(self, level)
+ end
+end
diff --git a/xmake/modules/core/tools/clang_cl.lua b/xmake/modules/core/tools/clang_cl.lua
index 4e0046fe8..9c4236343 100644
--- a/xmake/modules/core/tools/clang_cl.lua
+++ b/xmake/modules/core/tools/clang_cl.lua
@@ -117,6 +117,10 @@ function nf_language(self, stdname)
, gnu99 = "-Xclang -std=gnu99"
, c11 = "-Xclang -std=c11"
, gnu11 = "-Xclang -std=gnu11"
+ , c17 = "-Xclang -std=c17"
+ , gnu17 = "-Xclang -std=gnu17"
+ , clatest = "-Xclang -std=c17"
+ , gnulatest = "-Xclang -std=gnu17"
}
end
@@ -134,10 +138,12 @@ function nf_language(self, stdname)
, gnuxx17 = "-Xclang -std=gnu++17"
, cxx1z = "-Xclang -std=c++1z"
, gnuxx1z = "-Xclang -std=gnu++1z"
- , cxx20 = "-Xclang -std=c++2a"
- , gnuxx20 = "-Xclang -std=gnu++2a"
+ , cxx20 = "-Xclang -std=c++20"
+ , gnuxx20 = "-Xclang -std=gnu++20"
, cxx2a = "-Xclang -std=c++2a"
, gnuxx2a = "-Xclang -std=gnu++2a"
+ , cxxlatest = "-Xclang -std=c++latest"
+ , gnuxxlatest = "-Xclang -std=gnu++latest"
}
local cxxmaps2 = {}
for k, v in pairs(_g.cxxmaps) do
diff --git a/xmake/modules/core/tools/dmd.lua b/xmake/modules/core/tools/dmd.lua
index 2a9d860e1..3f29da28f 100644
--- a/xmake/modules/core/tools/dmd.lua
+++ b/xmake/modules/core/tools/dmd.lua
@@ -146,11 +146,7 @@ end
-- link the target file
function link(self, objectfiles, targetkind, targetfile, flags)
-
- -- ensure the target directory
os.mkdir(path.directory(targetfile))
-
- -- link it
os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags))
end
@@ -161,11 +157,7 @@ end
-- compile the source file
function compile(self, sourcefile, objectfile, dependinfo, flags)
-
- -- ensure the object directory
os.mkdir(path.directory(objectfile))
-
- -- compile it
os.runv(compargv(self, sourcefile, objectfile, flags))
end
diff --git a/xmake/modules/core/tools/fpc.lua b/xmake/modules/core/tools/fpc.lua
new file mode 100644
index 000000000..98b746c8a
--- /dev/null
+++ b/xmake/modules/core/tools/fpc.lua
@@ -0,0 +1,110 @@
+--!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 fpc.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.config")
+import("core.project.project")
+
+-- init it
+function init(self)
+ if not is_plat("windows", "mingw") then
+ self:add("shared.pcflags", "-Cg")
+ end
+end
+
+-- make the optimize flag
+function nf_optimize(self, level)
+ local maps =
+ {
+ none = "-O-"
+ , fast = "-O1"
+ , fastest = "-O3"
+ , smallest = "-O2"
+ , aggressive = "-O4"
+ }
+ return maps[level]
+end
+
+-- make the strip flag
+function nf_strip(self, level)
+ if level == "all" then
+ return "-Xs"
+ end
+end
+
+-- make the symbol flag
+function nf_symbol(self, level)
+ if level == "debug" and self:kind() == "pc" then
+ if self:plat() == "windows" then
+ return {"-gw3", "-WN"}
+ else
+ return "-gw3"
+ end
+ end
+end
+
+-- make the link flag
+function nf_link(self, lib)
+ return "-k-l" .. lib
+end
+
+-- make the syslink flag
+function nf_syslink(self, lib)
+ return nf_link(self, lib)
+end
+
+-- make the linkdir flag
+function nf_linkdir(self, dir)
+ return {"-k-L" .. dir}
+end
+
+-- make the rpathdir flag
+function nf_rpathdir(self, dir)
+ dir = path.translate(dir)
+ if self:has_flags("-k-rpath=" .. dir, "ldflags") then
+ return {"-k-rpath=" .. (dir:gsub("@[%w_]+", function (name)
+ local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"}
+ return maps[name]
+ end))}
+ end
+end
+
+-- make the framework flag
+function nf_framework(self, framework)
+ return {"-k-framework", framework}
+end
+
+-- make the frameworkdir flag
+function nf_frameworkdir(self, frameworkdir)
+ return {"-k-F", path.translate(frameworkdir)}
+end
+
+-- make the build arguments list
+function buildargv(self, sourcefiles, targetkind, targetfile, flags)
+ return self:program(), table.join(flags, "-o" .. targetfile, sourcefiles)
+end
+
+-- build the target file
+function build(self, sourcefiles, targetkind, targetfile, flags)
+ os.mkdir(path.directory(targetfile))
+ os.runv(buildargv(self, sourcefiles, targetkind, targetfile, flags))
+end
+
diff --git a/xmake/modules/core/tools/gcc.lua b/xmake/modules/core/tools/gcc.lua
index 89b732ec9..40d3b8a4e 100644
--- a/xmake/modules/core/tools/gcc.lua
+++ b/xmake/modules/core/tools/gcc.lua
@@ -27,7 +27,7 @@ import("core.project.config")
import("core.project.project")
import("core.language.language")
import("private.tools.ccache")
-import("private.utils.progress")
+import("utils.progress")
-- init it
function init(self)
@@ -42,7 +42,11 @@ function init(self)
self:set("shflags", "-shared")
-- add -fPIC for shared
- if not is_plat("windows", "mingw") then
+ --
+ -- we need check it for clang/gcc with window target
+ -- @see https://github.com/xmake-io/xmake/issues/1392
+ --
+ if not is_plat("windows", "mingw") and self:has_flags("-fPIC", "cxflags") then
self:add("shflags", "-fPIC")
self:add("shared.cxflags", "-fPIC")
end
@@ -72,13 +76,13 @@ function init(self)
end
-- make the strip flag
-function nf_strip(self, level)
+function nf_strip(self, level, target)
local maps =
{
debug = "-Wl,-S"
, all = "-s"
}
- if is_plat("macosx") or is_plat("iphoneos") then
+ if target:is_plat("macosx") or target:is_plat("iphoneos") then
maps.all = "-Wl,-x"
end
return maps[level]
@@ -113,8 +117,8 @@ function nf_warning(self, level)
, less = "-Wall"
, more = "-Wall"
, all = "-Wall"
- , allextra = "-Wall -Wextra"
- , everything = "-Wall -Wextra -Weffc++"
+ , allextra = {"-Wall", "-Wextra"}
+ , everything = self:kind() == "cxx" and {"-Wall", "-Wextra", "-Weffc++"} or {"-Wall", "-Wextra"}
, error = "-Werror"
}
return maps[level]
@@ -180,6 +184,8 @@ function nf_language(self, stdname)
, gnu11 = "-std=gnu11"
, c17 = "-std=c17"
, gnu17 = "-std=gnu17"
+ , clatest = {"-std=c17", "-std=c11", "-std=c99", "-std=c89", "-ansi"}
+ , gnulatest = {"-std=gnu17", "-std=gnu11", "-std=gnu99", "-std=gnu89", "-ansi"}
}
end
@@ -197,10 +203,12 @@ function nf_language(self, stdname)
, gnuxx17 = "-std=gnu++17"
, cxx1z = "-std=c++1z"
, gnuxx1z = "-std=gnu++1z"
- , cxx20 = "-std=c++2a"
- , gnuxx20 = "-std=gnu++2a"
+ , cxx20 = {"-std=c++20", "-std=c++2a"}
+ , gnuxx20 = {"-std=gnu++20", "-std=c++2a"}
, cxx2a = "-std=c++2a"
, gnuxx2a = "-std=gnu++2a"
+ , cxxlatest = {"-std=c++20", "-std=c++2a", "-std=c++17", "-std=c++14", "-std=c++11", "-std=c++1z", "-std=c++98"}
+ , gnuxxlatest = {"-std=gnu++20", "-std=gnu++2a", "-std=gnu++17", "-std=gnu++14", "-std=gnu++11", "-std=c++1z", "-std=gnu++98"}
}
local cxxmaps2 = {}
for k, v in pairs(_g.cxxmaps) do
@@ -216,9 +224,18 @@ function nf_language(self, stdname)
elseif self:kind() == "sc" then
maps = {}
end
-
- -- make it
- return maps[stdname]
+ local result = maps[stdname]
+ if type(result) == "table" then
+ for _, v in ipairs(result) do
+ if self:has_flags(v, "cxflags") then
+ result = v
+ maps[stdname] = result
+ return result
+ end
+ end
+ else
+ return result
+ end
end
-- make the define flag
@@ -276,7 +293,7 @@ end
-- make the frameworkdir flag
function nf_frameworkdir(self, frameworkdir)
- return {"-F", path.translate(frameworkdir)}
+ return {"-F" .. path.translate(frameworkdir)}
end
-- make the c precompiled header flag
@@ -334,7 +351,7 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags, opt)
-- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc
if targetkind == "shared" and is_plat("mingw") then
- table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib"))
+ table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a"))
end
-- init arguments
@@ -408,7 +425,6 @@ end
-- make the compile arguments list
function compargv(self, sourcefile, objectfile, flags)
-
-- precompiled header?
local extension = path.extension(sourcefile)
if (extension:startswith(".h") or extension == ".inl") then
@@ -478,7 +494,12 @@ function compile(self, sourcefile, objectfile, dependinfo, flags)
end
-- raise compiling errors
- raise(#lines > 0 and table.concat(lines, "\n") or "")
+ local results = #lines > 0 and table.concat(lines, "\n") or ""
+ if not option.get("verbose") then
+ results = results .. "\n ${yellow}> in ${bright}" .. sourcefile
+ end
+ raise(results)
+
end
},
finally
@@ -488,7 +509,10 @@ function compile(self, sourcefile, objectfile, dependinfo, flags)
if ok and errdata and #errdata > 0 and (option.get("diagnosis") or option.get("warning") or global.get("build_warning")) then
local lines = errdata:split('\n', {plain = true})
if #lines > 0 then
- local warnings = table.concat(table.slice(lines, 1, (#lines > 8 and 8 or #lines)), "\n")
+ if not option.get("diagnosis") then
+ lines = table.slice(lines, 1, (#lines > 16 and 16 or #lines))
+ end
+ local warnings = table.concat(lines, "\n")
if progress.showing_without_scroll() then
print("")
end
diff --git a/xmake/modules/core/tools/go.lua b/xmake/modules/core/tools/go.lua
index fbd046cf0..2b2b76623 100644
--- a/xmake/modules/core/tools/go.lua
+++ b/xmake/modules/core/tools/go.lua
@@ -25,56 +25,34 @@ import("core.project.project")
-- init it
function init(self)
-
- -- init arflags
self:set("gcarflags", "grc")
-
- -- init the file formats
- self:set("formats", { static = "$(name).a" })
end
-- make the optimize flag
function nf_optimize(self, level)
-
- -- the maps
- local maps =
- {
+ local maps = {
none = "-N"
}
-
- -- make it
return maps[level]
end
-- make the symbol flag
function nf_symbol(self, level, target, mapkind)
-
- -- only for compiler
if mapkind ~= "object" then
return
end
-
- -- the maps
- local maps =
- {
+ local maps = {
debug = "-E"
}
-
- -- make it
return maps[level]
end
-- make the strip flag
function nf_strip(self, level)
-
- -- the maps
- local maps =
- {
+ local maps = {
debug = "-s"
, all = "-s"
}
-
- -- make it
return maps[level]
end
@@ -95,8 +73,6 @@ end
-- make the link arguments list
function linkargv(self, objectfiles, targetkind, targetfile, flags)
-
- -- make it
if targetkind == "static" then
return self:program(), table.join("tool", "pack", flags, targetfile, objectfiles)
else
@@ -106,11 +82,7 @@ end
-- link the target file
function link(self, objectfiles, targetkind, targetfile, flags)
-
- -- ensure the target directory
os.mkdir(path.directory(targetfile))
-
- -- link it
local program, argv = linkargv(self, objectfiles, targetkind, targetfile, flags)
os.runv(program, argv, {envs = self:runenvs()})
end
@@ -122,11 +94,7 @@ end
-- compile the source file
function compile(self, sourcefiles, objectfile, dependinfo, flags)
-
- -- ensure the object directory
os.mkdir(path.directory(objectfile))
-
- -- compile it
local program, argv = compargv(self, sourcefiles, objectfile, flags)
os.runv(program, argv, {envs = self:runenvs()})
end
diff --git a/xmake/modules/core/tools/ml.lua b/xmake/modules/core/tools/ml.lua
index 83da11fb6..59749974c 100644
--- a/xmake/modules/core/tools/ml.lua
+++ b/xmake/modules/core/tools/ml.lua
@@ -20,6 +20,7 @@
-- imports
import("private.tools.vstool")
+import("core.base.hashset")
-- init it
--
@@ -28,11 +29,7 @@ import("private.tools.vstool")
function init(self)
-- init asflags
- if self:program():find("64") then
- self:set("asflags", "-nologo")
- else
- self:set("asflags", "-nologo", "-Gd")
- end
+ self:set("asflags", "-nologo")
-- init flags map
self:set("mapflags",
@@ -57,10 +54,25 @@ function init(self)
})
end
+-- make the symbol flags
+function nf_symbols(self, levels, target)
+ local flags = nil
+ local values = hashset.from(levels)
+ if values:has("debug") then
+ flags = {}
+ if values:has("edit") then
+ table.insert(flags, "-ZI")
+ elseif values:has("embed") then
+ table.insert(flags, "-Z7")
+ else
+ table.insert(flags, "-Zi")
+ end
+ end
+ return flags
+end
+
-- make the warning flag
function nf_warning(self, level)
-
- -- the maps
local maps =
{
none = "-w"
@@ -70,8 +82,6 @@ function nf_warning(self, level)
, everything = "-W3"
, error = "-WX"
}
-
- -- make it
return maps[level]
end
@@ -97,6 +107,21 @@ end
-- make the compile arguments list
function compargv(self, sourcefile, objectfile, flags)
+ -- we need to set the default -Gd option for the x86 architecture,
+ -- if the other calling convention flags are not set
+ --
+ -- we can't directly remove -Gd. This is not only for backward compatibility,
+ -- but also to simplify mixed compilation with c programs.
+ --
+ -- although this may affect some performance,
+ -- it only takes effect under x86 asm, so there will be no major performance issues.
+ --
+ -- @see https://github.com/xmake-io/xmake/issues/1779
+ --
+ if not self:program():find("64", 1, true) and
+ not table.contains(flags, "-Gc", "/Gc", "-GZ", "/GZ") then
+ table.insert(flags, "-Gd")
+ end
return self:program(), table.join("-c", flags, "-Fo" .. objectfile, sourcefile)
end
diff --git a/xmake/modules/core/tools/nim.lua b/xmake/modules/core/tools/nim.lua
new file mode 100644
index 000000000..0eece46cf
--- /dev/null
+++ b/xmake/modules/core/tools/nim.lua
@@ -0,0 +1,161 @@
+--!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 nim.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.config")
+import("core.project.project")
+
+-- init it
+--
+-- @see https://nim-lang.org/docs/nimc.html
+function init(self)
+
+ -- init arflags
+ self:set("ncarflags", "--app:staticlib", "--noMain")
+
+ -- init shflags
+ self:set("ncshflags", "--app:lib", "--noMain")
+end
+
+-- make the warning flag
+function nf_warning(self, level)
+ local maps =
+ {
+ none = "--warning:X:off"
+ , less = "--warning:X:on"
+ , more = "--warning:X:on"
+ , all = "--warning:X:on"
+ , allextra = "--warning:X:on"
+ , everything = "--warning:X:on"
+ , error = "--warningAsError:X:on"
+ }
+ return maps[level]
+end
+
+-- make the define flag
+function nf_define(self, macro)
+ return "--define:" .. macro
+end
+
+-- make the undefine flag
+function nf_undefine(self, macro)
+ return "--undef:" .. macro
+end
+
+-- make the optimize flag
+function nf_optimize(self, level)
+ local maps =
+ {
+ none = "--opt:none"
+ , fast = "-d:release"
+ , faster = "-d:release"
+ , fastest = "-d:release"
+ , smallest = {"-d:release", "--opt:size"}
+ , aggressive = "-d:danger"
+ }
+ return maps[level]
+end
+
+-- make the symbol flag
+function nf_symbol(self, level)
+ local maps =
+ {
+ debug = "--debugger:native"
+ }
+ return maps[level]
+end
+
+-- make the strip flag
+function nf_strip(self, level, target)
+ if target:is_plat("linux", "macosx", "bsd") then
+ if level == "debug" or level == "all" then
+ return "--passL:-s"
+ end
+ end
+end
+
+-- make the includedir flag
+function nf_includedir(self, dir)
+ return {"--passC:-I" .. path.translate(dir)}
+end
+
+-- make the link flag
+function nf_link(self, lib, target)
+ if target:is_plat("windows") then
+ return "--passL:" .. lib .. ".lib"
+ else
+ return "--passL:-l" .. lib
+ end
+end
+
+-- make the linkdir flag
+function nf_linkdir(self, dir, target)
+ if target:is_plat("windows") then
+ return {"--passL:-libpath:" .. path.translate(dir)}
+ else
+ return {"--passL:-L" .. path.translate(dir)}
+ end
+end
+
+-- make the build arguments list
+function buildargv(self, sourcefiles, targetkind, targetfile, flags)
+ local flags_extra = {}
+ if targetkind == "static" then
+ -- fix multiple definition of `NimMain', it is only workaround solution
+ -- we need to wait for this problem to be resolved
+ --
+ -- @see https://github.com/nim-lang/Nim/issues/15955
+ local uniquekey = hash.uuid(targetfile):split("-", {plain = true})[1]
+ table.insert(flags_extra, "--passC:-DNimMain=NimMain_" .. uniquekey)
+ table.insert(flags_extra, "--passC:-DNimMainInner=NimMainInner_" .. uniquekey)
+ table.insert(flags_extra, "--passC:-DNimMainModule=NimMainModule_" .. uniquekey)
+ table.insert(flags_extra, "--passC:-DPreMain=PreMain_" .. uniquekey)
+ table.insert(flags_extra, "--passC:-DPreMainInner=PreMainInner_" .. uniquekey)
+ end
+ if targetkind ~= "static" and is_plat("windows") then
+ -- fix link flags for windows
+ -- @see https://github.com/nim-lang/Nim/issues/19033
+ local flags_new = {}
+ local flags_link = {}
+ for _, flag in ipairs(flags) do
+ if flag:find("passL:", 1, true) then
+ table.insert(flags_link, flag)
+ else
+ table.insert(flags_new, flag)
+ end
+ end
+ if #flags_link > 0 then
+ table.insert(flags_new, "--passL:-link")
+ table.join2(flags_new, flags_link)
+ end
+ flags = flags_new
+ end
+ return self:program(), table.join("c", flags, flags_extra, "-o:" .. targetfile, sourcefiles)
+end
+
+-- build the target file
+function build(self, sourcefiles, targetkind, targetfile, flags)
+ os.mkdir(path.directory(targetfile))
+ local program, argv = buildargv(self, sourcefiles, targetkind, targetfile, flags)
+ os.runv(program, argv, {envs = self:runenvs()})
+end
+
+
diff --git a/xmake/modules/core/tools/nvcc.lua b/xmake/modules/core/tools/nvcc.lua
index 784b606c5..2aad54096 100644
--- a/xmake/modules/core/tools/nvcc.lua
+++ b/xmake/modules/core/tools/nvcc.lua
@@ -26,7 +26,7 @@ import("core.project.project")
import("core.platform.platform")
import("core.language.language")
import("private.tools.ccache")
-import("private.utils.progress")
+import("utils.progress")
-- init it
function init(self)
@@ -59,7 +59,7 @@ function nf_symbol(self, level, target)
-- debug? generate *.pdb file
local flags = nil
if level == "debug" then
- flags = "-g -lineinfo"
+ flags = {"-g", "-lineinfo"}
if is_plat("windows") then
local host_flags = nil
local symbolfile = nil
@@ -82,11 +82,10 @@ function nf_symbol(self, level, target)
else
host_flags = "-Zi"
end
- flags = flags .. ' -Xcompiler "' .. host_flags .. '"'
+ table.insert(flags, "-Xcompiler")
+ table.insert(flags, host_flags)
end
end
-
- -- none
return flags
end
@@ -178,6 +177,8 @@ function nf_language(self, stdname)
cxx03 = "--std c++03"
, cxx11 = "--std c++11"
, cxx14 = "--std c++14"
+ , cxx17 = "--std c++17"
+ , cxxlatest = {"--std c++17", "--std c++14", "--std c++11", "--std c++03"}
}
local cxxmaps2 = {}
for k, v in pairs(_g.cxxmaps) do
@@ -185,7 +186,18 @@ function nf_language(self, stdname)
end
table.join2(_g.cxxmaps, cxxmaps2)
end
- return _g.cxxmaps[stdname]
+ local maps = _g.cxxmaps
+ local result = maps[stdname]
+ if type(result) == "table" then
+ for _, v in ipairs(result) do
+ if self:has_flags(v, "cxflags") then
+ result = v
+ maps[stdname] = result
+ break
+ end
+ end
+ end
+ return result
end
-- make the define flag
@@ -200,7 +212,7 @@ end
-- make the includedir flag
function nf_includedir(self, dir)
- return {"-I", dir}
+ return {"-I" .. path.translate(dir)}
end
-- make the sysincludedir flag
@@ -220,7 +232,7 @@ end
-- make the linkdir flag
function nf_linkdir(self, dir)
- return {"-L", dir}
+ return {"-L" .. path.translate(dir)}
end
-- make the rpathdir flag
@@ -258,9 +270,9 @@ function linkargv(self, objectfiles, targetkind, targetfile, flags)
end
-- add `-Wl,--out-implib,outputdir/libxxx.a` for xxx.dll on mingw/gcc
- if targetkind == "shared" and config.plat() == "mingw" then
+ if targetkind == "shared" and is_plat("mingw") then
table.insert(flags_extra, "-Xlinker")
- table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib"))
+ table.insert(flags_extra, "-Wl,--out-implib," .. path.join(path.directory(targetfile), path.basename(targetfile) .. ".dll.a"))
end
-- make link args
diff --git a/xmake/modules/core/tools/rc.lua b/xmake/modules/core/tools/rc.lua
index 208161b67..6796c0fe0 100644
--- a/xmake/modules/core/tools/rc.lua
+++ b/xmake/modules/core/tools/rc.lua
@@ -25,7 +25,7 @@ import("private.tools.vstool")
-- init it
function init(self)
- if winos.version():gt("winxp") then
+ if self:has_flags("-nologo", "mrcflags") then
-- fix vs2008 on xp, e.g. fatal error RC1106: invalid option: -ologo
self:set("mrcflags", "-nologo")
end
diff --git a/xmake/modules/core/tools/rustc.lua b/xmake/modules/core/tools/rustc.lua
index ade2daea4..ab41620cd 100644
--- a/xmake/modules/core/tools/rustc.lua
+++ b/xmake/modules/core/tools/rustc.lua
@@ -25,24 +25,10 @@ import("core.project.project")
-- init it
function init(self)
-
- -- init arflags
- self:set("rcarflags", "--crate-type=lib")
-
- -- init shflags
- self:set("rcshflags", "--crate-type=dylib")
-
- -- init ldflags
- self:set("rcldflags", "--crate-type=bin")
-
- -- init the file formats
- self:set("formats", { static = "lib$(name).rlib" })
end
-- make the optimize flag
function nf_optimize(self, level)
-
- -- the maps
local maps =
{
none = "-C opt-level=0"
@@ -52,21 +38,15 @@ function nf_optimize(self, level)
, smallest = "-C opt-level=s"
, aggressive = "-C opt-level=z"
}
-
- -- make it
return maps[level]
end
-- make the symbol flag
function nf_symbol(self, level)
-
- -- the maps
local maps =
{
debug = "-C debuginfo=2"
}
-
- -- make it
return maps[level]
end
@@ -75,18 +55,66 @@ function nf_linkdir(self, dir)
return {"-L" .. dir}
end
+-- make the link flag
+function nf_link(self, lib)
+ return "-l" .. lib
+end
+
+-- make the syslink flag
+function nf_syslink(self, lib)
+ return nf_link(self, lib)
+end
+
+-- make the frameworkdir flag, crate module dependency directories
+function nf_frameworkdir(self, frameworkdir)
+ return {"-L", "dependency=" .. frameworkdir}
+end
+
+-- make the framework flag, crate module
+function nf_framework(self, framework)
+ local basename = path.basename(framework)
+ local cratename = basename:match("lib(.-)%-.-") or basename:match("lib(.-)")
+ if cratename then
+ return {"--extern", cratename .. "=" .. framework}
+ end
+end
+
+-- make the rpathdir flag
+function nf_rpathdir(self, dir)
+ dir = path.translate(dir)
+ if self:has_flags({"-C", "link-arg=-Wl,-rpath=$ORIGIN"}, "ldflags") then
+ return {"-C", "link-arg=-Wl,-rpath=" .. (dir:gsub("@[%w_]+", function (name)
+ local maps = {["@loader_path"] = "$ORIGIN", ["@executable_path"] = "$ORIGIN"}
+ return maps[name]
+ end))}
+ elseif self:has_flags({"-C", "link-arg=-Xlinker", "-C", "link-arg=-rpath", "-C", "link-arg=-Xlinker", "-C", "link-arg=@loader_path"}, "ldflags") then
+ return {"-C", "link-arg=-Xlinker",
+ "-C", "link-arg=-rpath",
+ "-C", "link-arg=-Xlinker",
+ "-C", "link-arg=" .. (dir:gsub("%$ORIGIN", "@loader_path"))}
+ end
+end
+
-- make the build arguments list
function buildargv(self, sourcefiles, targetkind, targetfile, flags)
- return self:program(), table.join(flags, "-o", targetfile, sourcefiles)
+ -- add rpath for dylib (macho), e.g. -install_name @rpath/file.dylib
+ local flags_extra = {}
+ if targetkind == "shared" and is_plat("macosx", "iphoneos", "watchos") then
+ table.insert(flags_extra, "-C")
+ table.insert(flags_extra, "link-arg=-Xlinker")
+ table.insert(flags_extra, "-C")
+ table.insert(flags_extra, "link-arg=-install_name")
+ table.insert(flags_extra, "-C")
+ table.insert(flags_extra, "link-arg=-Xlinker")
+ table.insert(flags_extra, "-C")
+ table.insert(flags_extra, "link-arg=@rpath/" .. path.filename(targetfile))
+ end
+ return self:program(), table.join(flags, flags_extra, "-o", targetfile, sourcefiles)
end
-- build the target file
function build(self, sourcefiles, targetkind, targetfile, flags)
-
- -- ensure the target directory
os.mkdir(path.directory(targetfile))
-
- -- build it
os.runv(buildargv(self, sourcefiles, targetkind, targetfile, flags))
end
@@ -97,11 +125,7 @@ end
-- compile the source file
function compile(self, sourcefiles, objectfile, dependinfo, flags)
-
- -- ensure the object directory
os.mkdir(path.directory(objectfile))
-
- -- compile it
os.runv(compargv(self, sourcefiles, objectfile, flags))
end
diff --git a/xmake/modules/core/tools/sdcc.lua b/xmake/modules/core/tools/sdcc.lua
index 00e081384..4605f12f8 100644
--- a/xmake/modules/core/tools/sdcc.lua
+++ b/xmake/modules/core/tools/sdcc.lua
@@ -21,7 +21,7 @@
-- imports
import("core.base.option")
import("core.base.global")
-import("private.utils.progress")
+import("utils.progress")
-- init it
function init(self)
@@ -68,23 +68,17 @@ end
-- make the warning flag
function nf_warning(self, level)
-
- -- the maps
local maps =
{
none = "--less-pedantic"
, less = "--less-pedantic"
, error = "-Werror"
}
-
- -- make it
return maps[level]
end
-- make the optimize flag
function nf_optimize(self, level)
-
- -- the maps
local maps =
{
none = ""
@@ -94,19 +88,14 @@ function nf_optimize(self, level)
, smallest = "--opt-code-size"
, aggressive = "--opt-code-speed"
}
-
- -- make it
return maps[level]
end
-- make the language flag
function nf_language(self, stdname)
-
- -- the stdc maps
if _g.cmaps == nil then
_g.cmaps =
{
- -- stdc
ansi = "--std-c89"
, c89 = "--std-c89"
, gnu89 = "--std-sdcc89"
@@ -116,9 +105,23 @@ function nf_language(self, stdname)
, gnu11 = "--std-sdcc11"
, c20 = "--std-c2x"
, gnu20 = "--std-sdcc2x"
+ , clatest = {"--std-c2x", "--std-c11", "--std-c99", "--std-c89"}
+ , gnulatest = {"--std-sdcc2x", "--std-sdcc11", "--std-sdcc99", "--std-sdcc89"}
}
end
- return _g.cmaps[stdname]
+ local maps = _g.cmaps
+ local result = maps[stdname]
+ if type(result) == "table" then
+ for _, v in ipairs(result) do
+ if self:has_flags(v, "cxflags") then
+ result = v
+ maps[stdname] = result
+ return result
+ end
+ end
+ else
+ return result
+ end
end
-- make the define flag
@@ -163,11 +166,7 @@ end
-- link the target file
function link(self, objectfiles, targetkind, targetfile, flags)
-
- -- ensure the target directory
os.mkdir(path.directory(targetfile))
-
- -- link it
os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags))
end
diff --git a/xmake/modules/core/tools/zig.lua b/xmake/modules/core/tools/zig.lua
index 2270e2a3e..f0d6c5d98 100644
--- a/xmake/modules/core/tools/zig.lua
+++ b/xmake/modules/core/tools/zig.lua
@@ -55,7 +55,6 @@ function nf_optimize(self, level)
{
none = "-O Debug"
, fast = "-O ReleaseSafe"
- , aggressive = "-O ReleaseFast"
, fastest = "-O ReleaseFast"
, smallest = "-O ReleaseSmall"
, aggressive = "-O ReleaseFast"
@@ -117,11 +116,7 @@ end
-- link the target file
function link(self, objectfiles, targetkind, targetfile, flags)
-
- -- ensure the target directory
os.mkdir(path.directory(targetfile))
-
- -- link it
os.runv(linkargv(self, objectfiles, targetkind, targetfile, flags))
end
@@ -132,11 +127,7 @@ end
-- compile the source file
function compile(self, sourcefile, objectfile, dependinfo, flags)
-
- -- ensure the object directory
os.mkdir(path.directory(objectfile))
-
- -- compile it
os.runv(compargv(self, sourcefile, objectfile, flags))
end
diff --git a/xmake/modules/detect/sdks/find_iccenv.lua b/xmake/modules/detect/sdks/find_iccenv.lua
index 0e432a99c..84b40fade 100644
--- a/xmake/modules/detect/sdks/find_iccenv.lua
+++ b/xmake/modules/detect/sdks/find_iccenv.lua
@@ -102,6 +102,11 @@ function _find_intel_on_windows(opt)
-- find iclvars_bat.bat
local paths = {"$(env ICPP_COMPILER20)"}
local iclvars_bat = find_file("bin/iclvars.bat", paths)
+ -- look for setvars.bat which is new in 2021
+ if not iclvars_bat then
+ paths = {"$(env ICPP_COMPILER21)"}
+ iclvars_bat = find_file("../../../setvars.bat", paths)
+ end
if iclvars_bat then
-- load iclvars_bat
@@ -123,6 +128,22 @@ function _find_intel_on_linux(opt)
local sdkdir = path.directory(path.directory(icc))
return {sdkdir = sdkdir, bindir = path.directory(icc), path.join(sdkdir, "include"), libdir = path.join(sdkdir, "lib")}
end
+
+ -- find it from oneapi sdk directory
+ local oneapi_rootdirs = {"~/intel/oneapi/compiler", "/opt/intel/oneapi/compiler"}
+ local arch = os.arch() == "x86_64" and "intel64" or "ia32"
+ paths = {}
+ for _, rootdir in ipairs(oneapi_rootdirs) do
+ table.insert(paths, path.join(rootdir, "*", is_host("macosx") and "mac" or "linux", "bin", arch))
+ end
+ if #paths > 0 then
+ local icc = find_file("icc", paths)
+ if icc then
+ local bindir = path.directory(icc)
+ local sdkdir = path.directory(path.directory(bindir))
+ return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "compiler", "lib", arch)}
+ end
+ end
end
-- find intel c/c++ environment
diff --git a/xmake/modules/detect/sdks/find_ifortenv.lua b/xmake/modules/detect/sdks/find_ifortenv.lua
index f3aafad06..d851b3f6a 100644
--- a/xmake/modules/detect/sdks/find_ifortenv.lua
+++ b/xmake/modules/detect/sdks/find_ifortenv.lua
@@ -102,6 +102,12 @@ function _find_intel_on_windows(opt)
-- find ifortvars_bat.bat
local paths = {"$(env IFORT_COMPILER20)"}
local ifortvars_bat = find_file("bin/ifortvars.bat", paths)
+ -- look for setvars.bat which is new in 2021
+ if not ifortvars_bat then
+ paths = {"$(env IFORT_COMPILER21)"}
+ ifortvars_bat = find_file("../../../setvars.bat", paths)
+ end
+
if ifortvars_bat then
-- load ifortvars_bat
@@ -116,12 +122,28 @@ end
-- find intel fortran envirnoment on linux
function _find_intel_on_linux(opt)
- -- attempt to find the sdk directory
local paths = {"/opt/intel/bin", "/usr/local/bin", "/usr/bin"}
local ifort = find_file("ifort", paths)
if ifort then
- local sdkdir = path.directory(path.directory(ifort))
- return {sdkdir = sdkdir, bindir = path.directory(ifort), path.join(sdkdir, "include"), libdir = path.join(sdkdir, "lib")}
+ local bindir = path.directory(ifort)
+ local sdkdir = path.directory(bindir)
+ return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "lib")}
+ end
+
+ -- find it from oneapi sdk directory
+ local oneapi_rootdirs = {"~/intel/oneapi/compiler", "/opt/intel/oneapi/compiler"}
+ local arch = os.arch() == "x86_64" and "intel64" or "ia32"
+ paths = {}
+ for _, rootdir in ipairs(oneapi_rootdirs) do
+ table.insert(paths, path.join(rootdir, "*", is_host("macosx") and "mac" or "linux", "bin", arch))
+ end
+ if #paths > 0 then
+ local ifort = find_file("ifort", paths)
+ if ifort then
+ local bindir = path.directory(ifort)
+ local sdkdir = path.directory(path.directory(bindir))
+ return {sdkdir = sdkdir, bindir = bindir, libdir = path.join(sdkdir, "compiler", "lib", arch)}
+ end
end
end
diff --git a/xmake/modules/detect/sdks/find_mdk.lua b/xmake/modules/detect/sdks/find_mdk.lua
new file mode 100644
index 000000000..a2af360f1
--- /dev/null
+++ b/xmake/modules/detect/sdks/find_mdk.lua
@@ -0,0 +1,123 @@
+--!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 find_mdk.lua
+--
+
+-- imports
+import("lib.detect.find_path")
+import("core.base.option")
+import("core.base.semver")
+import("core.project.config")
+import("core.cache.detectcache")
+
+-- find MDK directory
+function _find_sdkdir(sdkdir)
+ local paths = {
+ "$(reg HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Keil\\Products\\MDK;Path)"
+ }
+ if sdkdir then
+ table.insert(paths, 1, sdkdir)
+ end
+ local result = find_path("armcc", paths) or find_path("armclang", paths)
+ if not result then
+ -- find it from some logical drives paths
+ paths = {}
+ for _, logical_drive in ipairs(winos.logical_drives()) do
+ table.insert(paths, path.join(logical_drive, "Keil_v5", "ARM"))
+ end
+ result = find_path("armcc", paths) or find_path("armclang", paths)
+ end
+ return result
+end
+
+-- find MDK toolchains
+function _find_mdk(sdkdir)
+
+ -- find mdk directory
+ sdkdir = _find_sdkdir(sdkdir)
+ if not sdkdir or not os.isdir(sdkdir) then
+ return nil
+ end
+ local result = {sdkdir = sdkdir}
+
+ -- get sdk version
+ local sdkver = winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Keil\\Products\\MDK;Version")
+ if sdkver then
+ sdkver = semver.match(sdkver, 1, "V%d+%.%d+")
+ if sdkver then
+ result.sdkver = sdkver:rawstr()
+ end
+ end
+
+ -- armcc sdk directory
+ local sdkdir_armcc = path.join(sdkdir, "armcc")
+ if os.isdir(sdkdir_armcc) and os.isfile(path.join(sdkdir_armcc, "bin", "armcc.exe")) then
+ result.sdkdir_armcc = sdkdir_armcc
+ end
+
+ -- armclang sdk directory
+ local sdkdir_armclang = path.join(sdkdir, "armclang")
+ if os.isdir(sdkdir_armclang) and os.isfile(path.join(sdkdir_armclang, "bin", "armclang.exe")) then
+ result.sdkdir_armclang = sdkdir_armclang
+ end
+ return result
+end
+
+-- find MDK toolchains
+--
+-- @param sdkdir the MDK directory
+-- @param opt the argument options, e.g. {verbose = true, force = false}
+--
+-- @return the MDK toolchains. e.g. {sdkver = ..., sdkdir, sdkdir_armcc, sdkdir_armclang}
+--
+-- @code
+--
+-- local toolchains = find_mdk("~/mdk")
+--
+-- @endcode
+--
+function main(sdkdir, opt)
+
+ -- init arguments
+ opt = opt or {}
+
+ -- attempt to load cache first
+ local key = "detect.sdks.find_mdk"
+ local cacheinfo = detectcache:get(key) or {}
+ if not opt.force and cacheinfo.mdk and cacheinfo.mdk.sdkdir and os.isdir(cacheinfo.mdk.sdkdir) then
+ return cacheinfo.mdk
+ end
+
+ -- find mdk
+ local mdk = _find_mdk(sdkdir or config.get("sdk"))
+ if mdk then
+ if opt.verbose or option.get("verbose") then
+ cprint("checking for MDK directory ... ${color.success}%s", mdk.sdkdir)
+ end
+ else
+ if opt.verbose or option.get("verbose") then
+ cprint("checking for MDK directory ... ${color.nothing}${text.nothing}")
+ end
+ end
+
+ -- save to cache
+ cacheinfo.mdk = mdk or false
+ detectcache:set(key, cacheinfo)
+ detectcache:save()
+ return mdk
+end
diff --git a/xmake/modules/detect/sdks/find_mingw.lua b/xmake/modules/detect/sdks/find_mingw.lua
index 7be315a9c..e5276834b 100644
--- a/xmake/modules/detect/sdks/find_mingw.lua
+++ b/xmake/modules/detect/sdks/find_mingw.lua
@@ -94,6 +94,9 @@ function _find_mingw(sdkdir, bindir, cross)
-- find cross toolchain
local toolchain = find_cross_toolchain(sdkdir or bindir, {bindir = bindir, cross = cross})
+ if not toolchain then -- fallback, e.g. gcc.exe without cross
+ toolchain = find_cross_toolchain(sdkdir or bindir, {bindir = bindir})
+ end
if toolchain then
return {sdkdir = toolchain.sdkdir, bindir = toolchain.bindir, cross = toolchain.cross}
end
diff --git a/xmake/modules/detect/sdks/find_ndk.lua b/xmake/modules/detect/sdks/find_ndk.lua
index bc07f6081..ac412bce0 100644
--- a/xmake/modules/detect/sdks/find_ndk.lua
+++ b/xmake/modules/detect/sdks/find_ndk.lua
@@ -50,10 +50,16 @@ function _find_ndkdir(sdkdir)
if not sdkdir then
sdkdir = os.getenv("ANDROID_NDK_HOME") or os.getenv("ANDROID_NDK_ROOT")
if not sdkdir and config.get("android_sdk") then
- sdkdir = path.join(config.get("android_sdk"), "ndk-bundle")
+ local ndkbundle = path.join(config.get("android_sdk"), "ndk-bundle")
+ if os.isdir(ndkbundle) then
+ sdkdir = ndkbundle
+ end
end
if not sdkdir and is_host("macosx") then
- sdkdir = "~/Library/Android/sdk/ndk-bundle"
+ sdkdir = find_directory("NDK", "/Applications/AndroidNDK*.app/Contents")
+ if not sdkdir then
+ sdkdir = "~/Library/Android/sdk/ndk-bundle"
+ end
end
end
@@ -188,8 +194,12 @@ function _find_ndk(sdkdir, arch, ndk_sdkver, ndk_toolchains_ver)
local gcc_toolchain_subdir = gcc_toolchain_subdirs[arch] or "arm-linux-androideabi-*"
-- find the binary directory
- local bindir = find_directory("bin", path.join(sdkdir, "toolchains", "llvm", "prebuilt", "*")) -- larger than ndk r16
- if not bindir then
+ local llvm_toolchain
+ local prebuilt = (is_host("macosx") and "darwin" or os.host()) .. "-x86_64"
+ local bindir = find_directory("bin", path.join(sdkdir, "toolchains", "llvm", "prebuilt", prebuilt)) -- larger than ndk r16
+ if bindir then
+ llvm_toolchain = path.directory(bindir)
+ else
bindir = find_directory("bin", path.join(sdkdir, "toolchains", gcc_toolchain_subdir, "prebuilt", "*"))
end
if not bindir then
@@ -231,6 +241,7 @@ function _find_ndk(sdkdir, arch, ndk_sdkver, ndk_toolchains_ver)
bindir = bindir,
cross = cross,
sdkver = sdkver,
+ llvm_toolchain = llvm_toolchain, -- >= ndk r22
gcc_toolchain = gcc_toolchain,
toolchains_ver = toolchains_ver,
sysroot = sysroot}
@@ -280,7 +291,6 @@ function main(sdkdir, opt)
if opt.verbose or option.get("verbose") then
cprint("checking for NDK directory ... ${color.success}%s", ndk.sdkdir)
cprint("checking for SDK version of NDK ... ${color.success}%s", ndk.sdkver)
- cprint("checking for toolchains version of NDK ... ${color.success}%s", ndk.toolchains_ver)
end
else
diff --git a/xmake/modules/detect/sdks/find_qt.lua b/xmake/modules/detect/sdks/find_qt.lua
index 9dbc7b386..202b52d88 100644
--- a/xmake/modules/detect/sdks/find_qt.lua
+++ b/xmake/modules/detect/sdks/find_qt.lua
@@ -35,7 +35,10 @@ function _find_sdkdir(sdkdir, sdkver)
table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "gcc_64" or "gcc_32", "bin"))
table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "clang_64" or "clang_32", "bin"))
elseif is_plat("macosx") then
+ table.insert(subdirs, path.join(sdkver or "*", "macos", "bin")) -- for Qt 6.2
table.insert(subdirs, path.join(sdkver or "*", is_arch("x86_64") and "clang_64" or "clang_32", "bin"))
+ elseif is_plat("iphoneos") then
+ table.insert(subdirs, path.join(sdkver or "*", "ios", "bin"))
elseif is_plat("windows") then
local vs = config.get("vs")
if vs then
@@ -120,11 +123,7 @@ end
-- find qmake
function _find_qmake(sdkdir, sdkver)
-
- -- find qt directory
sdkdir = _find_sdkdir(sdkdir, sdkver)
-
- -- get the bin directory
local qmake = find_tool("qmake", {paths = sdkdir and path.join(sdkdir, "bin")})
if qmake then
return qmake.program
@@ -174,8 +173,27 @@ function _find_qt(sdkdir, sdkver)
local libdir = qtenvs.QT_INSTALL_LIBS
local pluginsdir = qtenvs.QT_INSTALL_PLUGINS
local includedir = qtenvs.QT_INSTALL_HEADERS
- local mkspecsdir = path.join(qtenvs.QT_INSTALL_ARCHDATA, "mkspecs")
- return {sdkdir = sdkdir, bindir = bindir, libexecdir = libexecdir, libdir = libdir, includedir = includedir, qmldir = qmldir, pluginsdir = pluginsdir, mkspecsdir = mkspecsdir, sdkver = sdkver}
+ local mkspecsdir = qtenvs.QMAKE_MKSPECS or path.join(qtenvs.QT_INSTALL_ARCHDATA, "mkspecs")
+ -- for 6.2
+ local bindir_host
+ if libexecdir and is_plat("android", "iphoneos") then
+ local rootdir = path.directory(path.directory(bindir))
+ if is_host("macosx") then
+ bindir_host = path.join(rootdir, "macos", "bin")
+ else
+ -- TODO
+ end
+ end
+ local libexecdir_host
+ if libexecdir and is_plat("android", "iphoneos") then
+ local rootdir = path.directory(path.directory(libexecdir))
+ if is_host("macosx") then
+ libexecdir_host = path.join(rootdir, "macos", "libexec")
+ else
+ -- TODO
+ end
+ end
+ return {sdkdir = sdkdir, bindir = bindir, bindir_host = bindir_host, libexecdir = libexecdir, libexecdir_host = libexecdir_host, libdir = libdir, includedir = includedir, qmldir = qmldir, pluginsdir = pluginsdir, mkspecsdir = mkspecsdir, sdkver = sdkver}
end
-- find qt sdk toolchains
diff --git a/xmake/modules/detect/sdks/find_vstudio.lua b/xmake/modules/detect/sdks/find_vstudio.lua
index 2934d23c8..0b3fb1361 100644
--- a/xmake/modules/detect/sdks/find_vstudio.lua
+++ b/xmake/modules/detect/sdks/find_vstudio.lua
@@ -19,6 +19,7 @@
--
-- imports
+import("core.project.config")
import("lib.detect.find_file")
import("lib.detect.find_tool")
@@ -34,9 +35,66 @@ local vcvars = {"path",
"WindowsLibPath",
"WindowsSDKVersion",
"WindowsSdkBinPath",
+ "WindowsSdkVerBinPath",
+ "ExtensionSdkDir",
"UniversalCRTSdkDir",
"UCRTVersion",
- "VCToolsVersion"}
+ "VCToolsVersion",
+ "VCIDEInstallDir",
+ "VCToolsInstallDir",
+ "VCToolsRedistDir",
+ "VisualStudioVersion",
+ "VSCMD_VER",
+ "VSCMD_ARG_app_plat",
+ "VSCMD_ARG_HOST_ARCH",
+ "VSCMD_ARG_TGT_ARCH"}
+
+-- init vsvers
+local vsvers =
+{
+ ["17.0"] = "2022"
+, ["16.0"] = "2019"
+, ["15.0"] = "2017"
+, ["14.0"] = "2015"
+, ["12.0"] = "2013"
+, ["11.0"] = "2012"
+, ["10.0"] = "2010"
+, ["9.0"] = "2008"
+, ["8.0"] = "2005"
+, ["7.1"] = "2003"
+, ["7.0"] = "7.0"
+, ["6.0"] = "6.0"
+, ["5.0"] = "5.0"
+, ["4.2"] = "4.2"
+}
+
+-- init vsenvs
+local vsenvs =
+{
+ ["17.0"] = "VS170COMNTOOLS"
+, ["16.0"] = "VS160COMNTOOLS"
+, ["15.0"] = "VS150COMNTOOLS"
+, ["14.0"] = "VS140COMNTOOLS"
+, ["12.0"] = "VS120COMNTOOLS"
+, ["11.0"] = "VS110COMNTOOLS"
+, ["10.0"] = "VS100COMNTOOLS"
+, ["9.0"] = "VS90COMNTOOLS"
+, ["8.0"] = "VS80COMNTOOLS"
+, ["7.1"] = "VS71COMNTOOLS"
+, ["7.0"] = "VS70COMNTOOLS"
+, ["6.0"] = "VS60COMNTOOLS"
+, ["5.0"] = "VS50COMNTOOLS"
+, ["4.2"] = "VS42COMNTOOLS"
+}
+
+-- get all known Visual Studio environment variables
+function get_vcvars()
+ local realvcvars = vcvars
+ for _, v in pairs(vsenvs) do
+ table.insert(realvcvars, v)
+ end
+ return realvcvars
+end
-- load vcvarsall environment variables
function _load_vcvarsall(vcvarsall, vsver, arch, opt)
@@ -59,7 +117,7 @@ function _load_vcvarsall(vcvarsall, vsver, arch, opt)
else
file:print("call \"%s\" %s %s > nul", vcvarsall, arch, opt.sdkver and opt.sdkver or "")
end
- for idx, var in ipairs(vcvars) do
+ for idx, var in ipairs(get_vcvars()) do
file:print("echo " .. var .. " = %%" .. var .. "%%")
end
file:close()
@@ -148,41 +206,6 @@ function main(opt)
return
end
- -- init vsvers
- local vsvers =
- {
- ["17.0"] = "2022"
- , ["16.0"] = "2019"
- , ["15.0"] = "2017"
- , ["14.0"] = "2015"
- , ["12.0"] = "2013"
- , ["11.0"] = "2012"
- , ["10.0"] = "2010"
- , ["9.0"] = "2008"
- , ["8.0"] = "2005"
- , ["7.1"] = "2003"
- , ["7.0"] = "7.0"
- , ["6.0"] = "6.0"
- , ["5.0"] = "5.0"
- , ["4.2"] = "4.2"
- }
-
- -- init vsenvs
- local vsenvs =
- {
- ["14.0"] = "VS140COMNTOOLS"
- , ["12.0"] = "VS120COMNTOOLS"
- , ["11.0"] = "VS110COMNTOOLS"
- , ["10.0"] = "VS100COMNTOOLS"
- , ["9.0"] = "VS90COMNTOOLS"
- , ["8.0"] = "VS80COMNTOOLS"
- , ["7.1"] = "VS71COMNTOOLS"
- , ["7.0"] = "VS70COMNTOOLS"
- , ["6.0"] = "VS60COMNTOOLS"
- , ["5.0"] = "VS50COMNTOOLS"
- , ["4.2"] = "VS42COMNTOOLS"
- }
-
-- init options
opt = opt or {}
@@ -255,7 +278,8 @@ function main(opt)
local vswhere_VCAuxiliaryBuildDir = nil
if (tonumber(version) >= 15) and vswhere then
local vswhere_vrange = format("%s,%s)", version, (version + 1))
- local result = os.iorunv(vswhere.program, {"-prerelease", "-property", "installationpath", "-version", vswhere_vrange})
+ -- build tools: https://github.com/microsoft/vswhere/issues/22 @@ https://aka.ms/vs/workloads
+ local result = os.iorunv(vswhere.program, {"-products", "*", "-prerelease", "-property", "installationpath", "-version", vswhere_vrange})
if result then
vswhere_VCAuxiliaryBuildDir = path.join(result:trim(), "VC", "Auxiliary", "Build")
end
@@ -282,7 +306,18 @@ function main(opt)
if not vcvarsall then
-- find vs from some logical drives paths
paths = {}
- for _, logical_drive in ipairs(winos.logical_drives()) do
+ local logical_drives = winos.logical_drives()
+ -- we attempt to find vs from wdk directory
+ -- wdk: E:\Program Files\Windows Kits\10
+ -- vcvarsall: E:\Program Files\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build
+ local wdk = config.get("wdk")
+ if wdk and os.isdir(wdk) then
+ local p = wdk:find("Program Files")
+ if p then
+ table.insert(logical_drives, wdk:sub(1, p - 1))
+ end
+ end
+ for _, logical_drive in ipairs(logical_drives) do
if os.isdir(path.join(logical_drive, "Program Files (x86)")) then
table.insert(paths, path.join(logical_drive, "Program Files (x86)", "Microsoft Visual Studio", vsvers[version], "*", "VC", "Auxiliary", "Build"))
table.insert(paths, path.join(logical_drive, "Program Files (x86)", "Microsoft Visual Studio " .. version, "VC"))
diff --git a/xmake/modules/detect/tools/circle/has_flags.lua b/xmake/modules/detect/tools/circle/has_flags.lua
new file mode 100644
index 000000000..6464e10b6
--- /dev/null
+++ b/xmake/modules/detect/tools/circle/has_flags.lua
@@ -0,0 +1,23 @@
+--!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 has_flags.lua
+--
+
+-- imports
+inherit("detect.tools.gcc.has_flags")
+
diff --git a/xmake/modules/detect/tools/cl/cfeatures.lua b/xmake/modules/detect/tools/cl/cfeatures.lua
index 88c65559f..9b043f7e1 100644
--- a/xmake/modules/detect/tools/cl/cfeatures.lua
+++ b/xmake/modules/detect/tools/cl/cfeatures.lua
@@ -31,6 +31,11 @@ function main()
local msvc_minver = "_MSC_VER >= 1200"
local msvc_2005 = "_MSC_VER >= 1400"
local msvc_2010 = "_MSC_VER >= 1600"
+ local msvc_2019 = "_MSC_VER >= 1920"
+
+ -- set language standard supports
+ _set("c_std_89", msvc_2005)
+ _set("c_std_99", msvc_2019)
-- set features
_set("c_static_assert", msvc_2010)
diff --git a/xmake/modules/detect/tools/cl/cxxfeatures.lua b/xmake/modules/detect/tools/cl/cxxfeatures.lua
index 661af6640..c8b683e6f 100644
--- a/xmake/modules/detect/tools/cl/cxxfeatures.lua
+++ b/xmake/modules/detect/tools/cl/cxxfeatures.lua
@@ -32,6 +32,7 @@ end
-- http://www.visualstudio.com/en-us/news/vs2015-preview-vs.aspx
-- http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx
-- http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx
+-- https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-160
--
-- porting from Modules/Compiler/MSVC-CXX-FeatureTests.cmake
--
@@ -49,6 +50,15 @@ function main()
local msvc_2013 = "_MSC_VER >= 1800"
local msvc_2015 = "_MSC_VER >= 1900"
local msvc_2017 = "_MSC_VER >= 1910"
+ local msvc_2019 = "_MSC_VER >= 1920"
+ local msvc_2022 = "_MSC_VER >= 1930"
+
+ -- set language standard supports
+ _set("cxx_std_98", msvc_2005)
+ _set("cxx_std_11", msvc_2015)
+ _set("cxx_std_14", msvc_2017)
+ _set("cxx_std_17", msvc_2019)
+ _set("cxx_std_20", msvc_2022)
-- VS version 15 (not 2015) introduces support for aggregate initializers.
_set("cxx_aggregate_default_initializers", "_MSC_FULL_VER >= 190024406")
diff --git a/xmake/modules/detect/tools/cl/has_flags.lua b/xmake/modules/detect/tools/cl/has_flags.lua
index a1cb9ace7..1c7f65325 100644
--- a/xmake/modules/detect/tools/cl/has_flags.lua
+++ b/xmake/modules/detect/tools/cl/has_flags.lua
@@ -20,6 +20,7 @@
-- imports
import("core.cache.detectcache")
+import("core.language.language")
-- attempt to check it from the argument list
function _check_from_arglist(flags, opt)
@@ -55,12 +56,17 @@ function _check_from_arglist(flags, opt)
return allflags[flags[1]:gsub("/", "-")]
end
+-- get extension
+function _get_extension(opt)
+ return opt.flagkind == "cxxflags" and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
+end
+
-- try running to check flags
function _check_try_running(flags, opt)
-- make an stub source file
local tmpdir = path.join(os.tmpdir(), "detect")
- local sourcefile = path.join(tmpdir, "cl_has_flags.c")
+ local sourcefile = path.join(tmpdir, "cl_has_flags" .. _get_extension(opt))
if not os.isfile(sourcefile) then
io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}")
end
diff --git a/xmake/modules/detect/tools/clang/cfeatures.lua b/xmake/modules/detect/tools/clang/cfeatures.lua
index 8cdfadfd0..e9a1687a6 100644
--- a/xmake/modules/detect/tools/clang/cfeatures.lua
+++ b/xmake/modules/detect/tools/clang/cfeatures.lua
@@ -33,11 +33,19 @@ function main()
_g.features = cfeatures()
-- init conditions
+ -- clang -std=c11 -dM -E - < /dev/null | grep __STDC_VERSION__
local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 304"
+ local c17 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L"
local c11 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L"
local c99 = clang_minver .. " && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L"
local c90 = clang_minver
+ -- set language standard supports
+ _set("c_std_89", c90)
+ _set("c_std_99", c99)
+ _set("c_std_11", c11)
+ _set("c_std_17", c17)
+
-- set features
_set("c_static_assert", c11)
_set("c_restrict", c99)
diff --git a/xmake/modules/detect/tools/clang/cxxfeatures.lua b/xmake/modules/detect/tools/clang/cxxfeatures.lua
index bbf3da8b8..1fd57c8d6 100644
--- a/xmake/modules/detect/tools/clang/cxxfeatures.lua
+++ b/xmake/modules/detect/tools/clang/cxxfeatures.lua
@@ -28,6 +28,8 @@ end
-- get features
--
+-- @see http://clang.llvm.org/cxx_status.html
+--
-- porting from Modules/Compiler/Clang-CXX-FeatureTests.cmake
--
function main()
@@ -36,12 +38,22 @@ function main()
_g.features = cxxfeatures()
-- init conditions
+ -- clang -x c++ -std=c++20 -dM -E - < /dev/null | grep __cplusplus
local clang_minver = "((__clang_major__ * 100) + __clang_minor__) >= 301"
+ local clang80_cxx20 = "((__clang_major__ * 100) + __clang_minor__) >= 800 && __cplusplus >= 202002L"
+ local clang50_cxx17 = "((__clang_major__ * 100) + __clang_minor__) >= 500 && __cplusplus >= 201703L"
local clang34_cxx14 = "((__clang_major__ * 100) + __clang_minor__) >= 304 && __cplusplus > 201103L"
local clang31_cxx11 = clang_minver .. " && __cplusplus >= 201103L"
local clang29_cxx11 = clang_minver .. " && __cplusplus >= 201103L"
local clang_cxx98 = clang_minver .. " && __cplusplus >= 199711L"
+ -- set language standard supports
+ _set("cxx_std_98", clang_cxx98)
+ _set("cxx_std_11", clang29_cxx11)
+ _set("cxx_std_14", clang34_cxx14)
+ _set("cxx_std_17", clang50_cxx17)
+ _set("cxx_std_20", clang80_cxx20)
+
-- set features for __has_feature()
local features_of_has_feature =
{
diff --git a/xmake/modules/detect/tools/clang_cl/has_flags.lua b/xmake/modules/detect/tools/clang_cl/has_flags.lua
index 27728697f..4917fb665 100644
--- a/xmake/modules/detect/tools/clang_cl/has_flags.lua
+++ b/xmake/modules/detect/tools/clang_cl/has_flags.lua
@@ -61,7 +61,7 @@ function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- try running to check flags
diff --git a/xmake/modules/detect/tools/dmd/has_flags.lua b/xmake/modules/detect/tools/dmd/has_flags.lua
index 459db9228..235e99d4c 100644
--- a/xmake/modules/detect/tools/dmd/has_flags.lua
+++ b/xmake/modules/detect/tools/dmd/has_flags.lua
@@ -40,7 +40,7 @@ function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- attempt to check it from the argument list
diff --git a/xmake/modules/detect/tools/find_7z.lua b/xmake/modules/detect/tools/find_7z.lua
index b441c2200..ce1a04f4a 100644
--- a/xmake/modules/detect/tools/find_7z.lua
+++ b/xmake/modules/detect/tools/find_7z.lua
@@ -55,6 +55,11 @@ function main(opt)
program = find_program("7za", opt)
end
+ -- find it from msys/mingw, it is only a shell script
+ if not program and is_subhost("msys") then
+ program = find_program("sh 7z", opt)
+ end
+
-- find program version
local version = nil
if program and opt and opt.version then
diff --git a/xmake/modules/detect/tools/find_armar.lua b/xmake/modules/detect/tools/find_armar.lua
new file mode 100644
index 000000000..725d6a988
--- /dev/null
+++ b/xmake/modules/detect/tools/find_armar.lua
@@ -0,0 +1,65 @@
+--!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 find_armar.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+import("detect.sdks.find_mdk")
+
+-- find armar
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local armar = find_armar()
+-- local armar, version = find_armar({program = "armar", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = "-h"
+
+ -- find program
+ local program = find_program(opt.program or "armar.exe", opt)
+ if not program then
+ local mdk = find_mdk()
+ if mdk then
+ if mdk.sdkdir_armcc then
+ program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armar.exe"), opt)
+ end
+ if not program and mdk.sdkdir_armclang then
+ program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armar.exe"), opt)
+ end
+ end
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_armasm.lua b/xmake/modules/detect/tools/find_armasm.lua
new file mode 100644
index 000000000..280333195
--- /dev/null
+++ b/xmake/modules/detect/tools/find_armasm.lua
@@ -0,0 +1,65 @@
+--!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 find_armasm.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+import("detect.sdks.find_mdk")
+
+-- find armasm
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local armasm = find_armasm()
+-- local armasm, version = find_armasm({program = "armasm", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = "-h"
+
+ -- find program
+ local program = find_program(opt.program or "armasm.exe", opt)
+ if not program then
+ local mdk = find_mdk()
+ if mdk then
+ if mdk.sdkdir_armcc then
+ program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armasm.exe"), opt)
+ end
+ if not program and mdk.sdkdir_armclang then
+ program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armasm.exe"), opt)
+ end
+ end
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_armcc.lua b/xmake/modules/detect/tools/find_armcc.lua
new file mode 100644
index 000000000..584e9b3a9
--- /dev/null
+++ b/xmake/modules/detect/tools/find_armcc.lua
@@ -0,0 +1,60 @@
+--!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 find_armcc.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+import("detect.sdks.find_mdk")
+
+-- find armcc
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local armcc = find_armcc()
+-- local armcc, version = find_armcc({program = "armcc", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = "-h"
+
+ -- find program
+ local program = find_program(opt.program or "armcc.exe", opt)
+ if not program then
+ local mdk = find_mdk()
+ if mdk and mdk.sdkdir_armcc then
+ program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armcc.exe"), opt)
+ end
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_armclang.lua b/xmake/modules/detect/tools/find_armclang.lua
new file mode 100644
index 000000000..ed6b0bbfe
--- /dev/null
+++ b/xmake/modules/detect/tools/find_armclang.lua
@@ -0,0 +1,59 @@
+--!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 find_armclang.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+import("detect.sdks.find_mdk")
+
+-- find armclang
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local armclang = find_armclang()
+-- local armclang, version = find_armclang({program = "armclang", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "armclang.exe", opt)
+ if not program then
+ local mdk = find_mdk()
+ if mdk and mdk.sdkdir_armclang then
+ program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armclang.exe"), opt)
+ end
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_armlink.lua b/xmake/modules/detect/tools/find_armlink.lua
new file mode 100644
index 000000000..3ab383c86
--- /dev/null
+++ b/xmake/modules/detect/tools/find_armlink.lua
@@ -0,0 +1,65 @@
+--!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 find_armlink.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+import("detect.sdks.find_mdk")
+
+-- find armlink
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local armlink = find_armlink()
+-- local armlink, version = find_armlink({program = "armlink", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = "-h"
+
+ -- find program
+ local program = find_program(opt.program or "armlink.exe", opt)
+ if not program then
+ local mdk = find_mdk()
+ if mdk then
+ if mdk.sdkdir_armcc then
+ program = find_program(path.join(mdk.sdkdir_armcc, "bin", "armlink.exe"), opt)
+ end
+ if not program and mdk.sdkdir_armclang then
+ program = find_program(path.join(mdk.sdkdir_armclang, "bin", "armlink.exe"), opt)
+ end
+ end
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_cargo.lua b/xmake/modules/detect/tools/find_cargo.lua
new file mode 100644
index 000000000..a67b29821
--- /dev/null
+++ b/xmake/modules/detect/tools/find_cargo.lua
@@ -0,0 +1,52 @@
+--!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 find_cargo.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find nim
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local nim = find_cargo()
+-- local nim, version = find_cargo({program = "cargo", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "cargo", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_circle.lua b/xmake/modules/detect/tools/find_circle.lua
new file mode 100644
index 000000000..ba2f805c2
--- /dev/null
+++ b/xmake/modules/detect/tools/find_circle.lua
@@ -0,0 +1,52 @@
+--!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 find_circle.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find circle
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local circle = find_circle()
+-- local circle, version = find_circle({program = "circle", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "circle", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_cxxbridge.lua b/xmake/modules/detect/tools/find_cxxbridge.lua
new file mode 100644
index 000000000..400573fa7
--- /dev/null
+++ b/xmake/modules/detect/tools/find_cxxbridge.lua
@@ -0,0 +1,52 @@
+--!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 find_cxxbridge.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find nim
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local nim = find_cxxbridge()
+-- local nim, version = find_cxxbridge({program = "cxxbridge", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "cxxbridge", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_fpc.lua b/xmake/modules/detect/tools/find_fpc.lua
new file mode 100644
index 000000000..8414acba8
--- /dev/null
+++ b/xmake/modules/detect/tools/find_fpc.lua
@@ -0,0 +1,52 @@
+--!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 find_fpc.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find fpc
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local fpc = find_fpc()
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = opt.check or "-h"
+
+ -- find program
+ local program = find_program(opt.program or "fpc", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_glslangValidator.lua b/xmake/modules/detect/tools/find_glslangValidator.lua
new file mode 100644
index 000000000..93bc94670
--- /dev/null
+++ b/xmake/modules/detect/tools/find_glslangValidator.lua
@@ -0,0 +1,52 @@
+--!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 find_glslangValidator.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find glslangValidator
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local glslangValidator = find_glslangValidator()
+-- local glslangValidator, version = find_glslangValidator({program = "glslangValidator", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "glslangValidator", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_glslc.lua b/xmake/modules/detect/tools/find_glslc.lua
new file mode 100644
index 000000000..ada89e672
--- /dev/null
+++ b/xmake/modules/detect/tools/find_glslc.lua
@@ -0,0 +1,61 @@
+--!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 find_glslc.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+import("core.tool.toolchain")
+
+-- find glslc
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local glslc = find_glslc()
+-- local glslc, version = find_glslc({program = "glslc", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "glslc", opt)
+ if not program and is_plat("android") then
+ local ndk = toolchain.load("ndk"):config("ndk")
+ if ndk then
+ local prebuilt = (is_host("macosx") and "darwin" or os.host()) .. "-x86_64"
+ opt.paths = path.join(ndk, "shader-tools", prebuilt)
+ program = find_program(opt.program or "glslc", opt)
+ end
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_ifort.lua b/xmake/modules/detect/tools/find_ifort.lua
index ecdb94dfd..31f158996 100644
--- a/xmake/modules/detect/tools/find_ifort.lua
+++ b/xmake/modules/detect/tools/find_ifort.lua
@@ -36,7 +36,6 @@ import("lib.detect.find_programver")
-- @endcode
--
function main(opt)
-
opt = opt or {}
if is_host("windows") then
-- find program
diff --git a/xmake/modules/detect/tools/find_llvm_as.lua b/xmake/modules/detect/tools/find_llvm_as.lua
new file mode 100644
index 000000000..213f63abf
--- /dev/null
+++ b/xmake/modules/detect/tools/find_llvm_as.lua
@@ -0,0 +1,57 @@
+--!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 xq114
+-- @file find_llvm_as.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find llvm-ar
+--
+-- @param opt the argument options, e.g. {version = true, program = "c:\xxx\llvm-as.exe"}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local llvm_as = find_llvm_as()
+-- local llvm_as, version = find_llvm_as({version = true})
+-- local llvm_as, version = find_llvm_as({version = true, program = "c:\xxx\llvm-as.exe"})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = opt.check or "-version"
+ opt.command = opt.command or "-version"
+
+ -- find program
+ local program = find_program(opt.program or "llvm-as", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+
+ -- ok?
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_make.lua b/xmake/modules/detect/tools/find_make.lua
new file mode 100644
index 000000000..eb2957d63
--- /dev/null
+++ b/xmake/modules/detect/tools/find_make.lua
@@ -0,0 +1,53 @@
+--!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 find_make.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find make
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local make = find_make()
+--
+-- @endcode
+--
+function main(opt)
+
+ -- find program
+ opt = opt or {}
+ local program = find_program(opt.program or (is_host("bsd") and "gmake" or "make"), opt)
+ if not program and not opt.program and is_subhost("msys", "cygwin") then
+ program = find_program("mingw32-make.exe", opt)
+ end
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
+
diff --git a/xmake/modules/detect/tools/find_metal.lua b/xmake/modules/detect/tools/find_metal.lua
new file mode 100644
index 000000000..71a01728b
--- /dev/null
+++ b/xmake/modules/detect/tools/find_metal.lua
@@ -0,0 +1,50 @@
+--!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 find_metal.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find metal
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local metal = find_metal()
+-- local metal, version = find_metal({program = "xcrun -sdk macosx metal", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- find program
+ opt = opt or {}
+ local program = find_program(opt.program or "xcrun -sdk macosx metal", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_metallib.lua b/xmake/modules/detect/tools/find_metallib.lua
new file mode 100644
index 000000000..6989729f9
--- /dev/null
+++ b/xmake/modules/detect/tools/find_metallib.lua
@@ -0,0 +1,50 @@
+--!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 find_metallib.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find metallib
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local metallib = find_metallib()
+-- local metallib, version = find_metallib({program = "xcrun -sdk macosx metallib", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- find program
+ opt = opt or {}
+ local program = find_program(opt.program or "xcrun -sdk macosx metallib", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_nim.lua b/xmake/modules/detect/tools/find_nim.lua
new file mode 100644
index 000000000..ae524ddbc
--- /dev/null
+++ b/xmake/modules/detect/tools/find_nim.lua
@@ -0,0 +1,52 @@
+--!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 find_nim.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find nim
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local nim = find_nim()
+-- local nim, version = find_nim({program = "nim", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "nim", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_nimble.lua b/xmake/modules/detect/tools/find_nimble.lua
new file mode 100644
index 000000000..7d4364b64
--- /dev/null
+++ b/xmake/modules/detect/tools/find_nimble.lua
@@ -0,0 +1,52 @@
+--!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 find_nimble.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find nim
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local nim = find_nimble()
+-- local nim, version = find_nimble({program = "nimble", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "nimble", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_pkg_config.lua b/xmake/modules/detect/tools/find_pkg_config.lua
index 00698d2cc..0dc83454a 100644
--- a/xmake/modules/detect/tools/find_pkg_config.lua
+++ b/xmake/modules/detect/tools/find_pkg_config.lua
@@ -48,7 +48,5 @@ function main(opt)
if program and opt and opt.version then
version = find_programver(program, opt)
end
-
- -- ok?
return program, version
end
diff --git a/xmake/modules/detect/tools/find_pkgconf.lua b/xmake/modules/detect/tools/find_pkgconf.lua
new file mode 100644
index 000000000..563989268
--- /dev/null
+++ b/xmake/modules/detect/tools/find_pkgconf.lua
@@ -0,0 +1,52 @@
+--!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 find_pkgconf.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find pkgconf
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local pkgconf = find_pkgconf()
+-- local pkgconf, version = find_pkgconf({version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- find program
+ local program = find_program(opt.program or "pkgconf", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/find_swig.lua b/xmake/modules/detect/tools/find_swig.lua
new file mode 100644
index 000000000..25220030e
--- /dev/null
+++ b/xmake/modules/detect/tools/find_swig.lua
@@ -0,0 +1,53 @@
+--!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 find_swig.lua
+--
+
+-- imports
+import("lib.detect.find_program")
+import("lib.detect.find_programver")
+
+-- find swig
+--
+-- @param opt the argument options, e.g. {version = true}
+--
+-- @return program, version
+--
+-- @code
+--
+-- local swig = find_swig()
+-- local swig, version = find_swig({program = "swig", version = true})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- init options
+ opt = opt or {}
+ opt.check = opt.check or "-version"
+
+ -- find program
+ local program = find_program(opt.program or "swig", opt)
+
+ -- find program version
+ local version = nil
+ if program and opt and opt.version then
+ version = find_programver(program, opt)
+ end
+ return program, version
+end
diff --git a/xmake/modules/detect/tools/fpc/has_flags.lua b/xmake/modules/detect/tools/fpc/has_flags.lua
new file mode 100644
index 000000000..109e1014b
--- /dev/null
+++ b/xmake/modules/detect/tools/fpc/has_flags.lua
@@ -0,0 +1,98 @@
+--!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 has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "detect.tools.fpc.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-h"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "fpc_has_flags.pas")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "program Hello;\nbegin\nend.")
+ end
+
+ -- check it
+ local binaryfile = os.tmpfile()
+ local ok, errors = _try_running(opt.program, table.join(flags, "-o" .. binaryfile, sourcefile))
+ os.tryrm(binaryfile)
+ return ok, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/detect/tools/gcc/cfeatures.lua b/xmake/modules/detect/tools/gcc/cfeatures.lua
index 664892720..b9ebaa036 100644
--- a/xmake/modules/detect/tools/gcc/cfeatures.lua
+++ b/xmake/modules/detect/tools/gcc/cfeatures.lua
@@ -29,10 +29,17 @@ function main()
-- init conditions
local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304"
+ local gcc10_c17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 1000 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201710L"
local gcc46_c11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L"
local gcc34_c99 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L"
local gcc_c90 = gcc_minver
+ -- set language standard supports
+ _set("c_std_89", gcc46_c90)
+ _set("c_std_99", gcc34_c99)
+ _set("c_std_11", gcc46_c11)
+ _set("c_std_17", gcc46_c17)
+
-- set features
_set("c_static_assert", gcc46_c11) -- GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it to 201000L
_set("c_restrict", gcc34_c99)
diff --git a/xmake/modules/detect/tools/gcc/cxxfeatures.lua b/xmake/modules/detect/tools/gcc/cxxfeatures.lua
index 4edb33a27..9d628522c 100644
--- a/xmake/modules/detect/tools/gcc/cxxfeatures.lua
+++ b/xmake/modules/detect/tools/gcc/cxxfeatures.lua
@@ -28,13 +28,17 @@ end
--
-- http://gcc.gnu.org/projects/cxx0x.html
-- http://gcc.gnu.org/projects/cxx1y.html
+-- https://gcc.gnu.org/projects/cxx-status.html
--
-- porting from Modules/Compiler/GNU-CXX-FeatureTests.cmake
--
function main()
-- init conditions
+ -- gcc -x c++ -std=c++20 -dM -E - < /dev/null | grep __cplusplus
local gcc_minver = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404"
+ local gcc90_cxx20 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 900 && __cplusplus >= 202002L"
+ local gcc70_cxx17 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 700 && __cplusplus >= 201703L"
local gcc50_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 500 && __cplusplus >= 201402L"
local gcc49_cxx14 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 409 && __cplusplus > 201103L"
local gcc481_cxx11 = "((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L"
@@ -46,6 +50,13 @@ function main()
local gcc44_cxx11 = "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && " .. gcc_cxx0x_defined
local gcc43_cxx11 = gcc_minver .. " && " .. gcc_cxx0x_defined
+ -- set language standard supports
+ _set("cxx_std_98", gcc_minver)
+ _set("cxx_std_11", gcc43_cxx11)
+ _set("cxx_std_14", gcc49_cxx14)
+ _set("cxx_std_17", gcc70_cxx17)
+ _set("cxx_std_20", gcc90_cxx20)
+
-- set features
_set("cxx_variable_templates", gcc50_cxx14)
_set("cxx_relaxed_constexpr", gcc50_cxx14)
@@ -151,6 +162,60 @@ function main()
_set("cxx_variadic_macros", gcc_minver .. " && " .. gcc_cxx0x_defined)
_set("cxx_template_template_parameters", gcc_minver .. " && __cplusplus")
+ -- c++17 language features with predefined macros
+ -- https://en.cppreference.com/w/cpp/feature_test
+ local features_cxx17 = {
+ "__cpp_aggregate_bases",
+ "__cpp_aligned_new",
+ "__cpp_capture_star_this",
+ "__cpp_constexpr",
+ "__cpp_deduction_guides",
+ "__cpp_enumerator_attributes",
+ "__cpp_fold_expressions",
+ "__cpp_guaranteed_copy_elision",
+ "__cpp_hex_float",
+ "__cpp_if_constexpr",
+ "__cpp_inheriting_constructors",
+ "__cpp_inline_variables",
+ "__cpp_namespace_attributes",
+ "__cpp_noexcept_function_type",
+ "__cpp_nontype_template_args",
+ "__cpp_nontype_template_parameter_auto",
+ "__cpp_range_based_for",
+ "__cpp_static_assert",
+ "__cpp_structured_bindings",
+ "__cpp_template_template_args",
+ "__cpp_variadic_using"}
+ for _, feature in ipairs(features_cxx17) do
+ _set((feature:gsub("__cpp", "cxx")), "__cplusplus && defined(" .. feature .. ")")
+ end
+
+ -- c++20 language features with predefined macros
+ -- https://en.cppreference.com/w/cpp/feature_test
+ local features_cxx20 = {
+ "__cpp_aggregate_paren_init",
+ "__cpp_char8_t",
+ "__cpp_concepts",
+ "__cpp_conditional_explicit",
+ "__cpp_consteval",
+ "__cpp_constexpr",
+ "__cpp_constexpr_dynamic_alloc",
+ "__cpp_constexpr_in_decltype",
+ "__cpp_constinit",
+ "__cpp_deduction_guides",
+ "__cpp_designated_initializers",
+ "__cpp_generic_lambdas",
+ "__cpp_impl_coroutine",
+ "__cpp_impl_destroying_delete",
+ "__cpp_impl_three_way_comparison",
+ "__cpp_init_captures",
+ "__cpp_modules",
+ "__cpp_nontype_template_args",
+ "__cpp_using_enum"}
+ for _, feature in ipairs(features_cxx20) do
+ _set((feature:gsub("__cpp", "cxx")), "__cplusplus && defined(" .. feature .. ")")
+ end
+
-- get features
return _g.features
end
diff --git a/xmake/modules/detect/tools/gcc/has_flags.lua b/xmake/modules/detect/tools/gcc/has_flags.lua
index 391ff2bfb..f7cf1d29e 100644
--- a/xmake/modules/detect/tools/gcc/has_flags.lua
+++ b/xmake/modules/detect/tools/gcc/has_flags.lua
@@ -44,47 +44,40 @@ end
-- attempt to check it from the argument list
function _check_from_arglist(flags, opt, islinker)
-
- -- only for compiler
- if islinker or #flags > 1 then
- return
- end
-
- -- make cache key
- local key = "detect.tools.gcc.has_flags"
-
- -- make flags key
+ local key = "detect.tools.gcc." .. (islinker and "has_ldflags" or "has_cflags")
local flagskey = opt.program .. "_" .. (opt.programver or "")
-
- -- get all flags from argument list
local allflags = detectcache:get2(key, flagskey)
if not allflags then
-
- -- get argument list
allflags = {}
- local arglist = os.iorunv(opt.program, {"--help"}, {envs = opt.envs})
+ local arglist = try {function () return os.iorunv(opt.program, {islinker and "-Wl,--help" or "--help"}, {envs = opt.envs}) end}
if arglist then
for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
allflags[arg] = true
end
end
-
- -- save cache
detectcache:set2(key, flagskey, allflags)
detectcache:save()
end
- return allflags[flags[1]]
+ local flag = flags[1]
+ if islinker and flag then
+ if flag:startswith("-Wl,") then
+ flag = flag:match("-Wl,(.-),") or flag:sub(5)
+ end
+ end
+ return allflags[flag]
+end
+
+-- get extension
+function _get_extension(opt)
+ -- @note we need detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
+ return (opt.program:endswith("++") or opt.flagkind == "cxxflags") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
end
-- try running to check flags
function _check_try_running(flags, opt, islinker)
- -- get extension
- -- @note we need detect extension for ndk/clang++.exe: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
- local extension = opt.program:endswith("++") and ".cpp" or (table.wrap(language.sourcekinds()[opt.toolkind or "cc"])[1] or ".c")
-
-- make an stub source file
- local sourcefile = path.join(os.tmpdir(), "detect", "gcc_has_flags" .. extension)
+ local sourcefile = path.join(os.tmpdir(), "detect", "gcc_has_flags" .. _get_extension(opt))
if not os.isfile(sourcefile) then
io.writefile(sourcefile, "int main(int argc, char** argv)\n{return 0;}")
end
diff --git a/xmake/modules/detect/tools/go/has_flags.lua b/xmake/modules/detect/tools/go/has_flags.lua
index 267d4de8a..e1acf3769 100644
--- a/xmake/modules/detect/tools/go/has_flags.lua
+++ b/xmake/modules/detect/tools/go/has_flags.lua
@@ -35,7 +35,7 @@ function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- attempt to check it from the argument list
diff --git a/xmake/modules/detect/tools/ml/has_flags.lua b/xmake/modules/detect/tools/ml/has_flags.lua
index 53576fa22..0dbda2134 100644
--- a/xmake/modules/detect/tools/ml/has_flags.lua
+++ b/xmake/modules/detect/tools/ml/has_flags.lua
@@ -61,12 +61,21 @@ function _check_try_running(flags, opt)
-- make an stub source file
local sourcefile = path.join(os.tmpdir(), "detect", "ml_has_flags.asm")
if not os.isfile(sourcefile) then
- io.writefile(sourcefile, ".code\nend")
+ io.writefile(sourcefile, [[
+ifndef X64
+.686p
+.model flat, C
+endif
+.code
+end]])
end
-- check it
local errors = nil
return try { function ()
+ if opt.program:find("ml64", 1, true) then
+ table.insert(flags, "-DX64")
+ end
local _, errs = os.iorunv(opt.program, table.join("-c", "-nologo", flags, "-Fo" .. os.nuldev(), sourcefile), {envs = opt.envs})
if errs and #errs:trim() > 0 then
return false, errs
diff --git a/xmake/modules/detect/tools/nim/has_flags.lua b/xmake/modules/detect/tools/nim/has_flags.lua
new file mode 100644
index 000000000..5538257fb
--- /dev/null
+++ b/xmake/modules/detect/tools/nim/has_flags.lua
@@ -0,0 +1,98 @@
+--!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 has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+
+-- try running
+function _try_running(...)
+
+ local argv = {...}
+ local errors = nil
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+end
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "detect.tools.nim.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"--help"})
+ if arglist then
+ for arg in arglist:gmatch("%s+(%-[%-%a%d]+)%s+") do
+ allflags[arg] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]]
+end
+
+-- try running to check flags
+function _check_try_running(flags, opt)
+
+ -- make an stub source file
+ local sourcefile = path.join(os.tmpdir(), "detect", "nim_has_flags.nim")
+ if not os.isfile(sourcefile) then
+ io.writefile(sourcefile, "echo \"hello\"")
+ end
+
+ -- check it
+ local cachedir = os.tmpfile() .. ".dir"
+ local ok, errors = _try_running(opt.program, table.join("c", "-c", flags, "--nimcache:" .. cachedir, sourcefile))
+ os.tryrm(cachedir)
+ return ok, errors
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", toolkind = "[cc|cxx|ld|ar|sh|gc|rc|dc|mm|mxx]"}
+--
+-- @return true or false
+--
+function main(flags, opt)
+
+ -- attempt to check it from the argument list
+ if _check_from_arglist(flags, opt) then
+ return true
+ end
+
+ -- try running to check it
+ return _check_try_running(flags, opt)
+end
+
diff --git a/xmake/modules/detect/tools/rc/has_flags.lua b/xmake/modules/detect/tools/rc/has_flags.lua
new file mode 100644
index 000000000..ac023c466
--- /dev/null
+++ b/xmake/modules/detect/tools/rc/has_flags.lua
@@ -0,0 +1,68 @@
+--!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 has_flags.lua
+--
+
+-- imports
+import("core.cache.detectcache")
+import("core.language.language")
+
+-- attempt to check it from the argument list
+function _check_from_arglist(flags, opt)
+
+ -- only one flag?
+ if #flags > 1 then
+ return
+ end
+
+ -- make cache key
+ local key = "detect.tools.rc.has_flags"
+
+ -- make allflags key
+ local flagskey = opt.program .. "_" .. (opt.programver or "")
+
+ -- get all allflags from argument list
+ local allflags = detectcache:get2(key, flagskey)
+ if not allflags then
+
+ -- get argument list
+ allflags = {}
+ local arglist = os.iorunv(opt.program, {"-?"}, {envs = opt.envs})
+ if arglist then
+ for arg in arglist:gmatch("(/[%-%a%d]+)%s+") do
+ allflags[arg:gsub("/", "-")] = true
+ end
+ end
+
+ -- save cache
+ detectcache:set2(key, flagskey, allflags)
+ detectcache:save()
+ end
+ return allflags[flags[1]:gsub("/", "-")]
+end
+
+-- has_flags(flags)?
+--
+-- @param opt the argument options, e.g. {toolname = "", program = "", programver = ""}
+--
+-- @return true or false
+--
+function main(flags, opt)
+ return _check_from_arglist(flags, opt)
+end
+
diff --git a/xmake/modules/detect/tools/rustc/has_flags.lua b/xmake/modules/detect/tools/rustc/has_flags.lua
index e7c55a180..e1696e454 100644
--- a/xmake/modules/detect/tools/rustc/has_flags.lua
+++ b/xmake/modules/detect/tools/rustc/has_flags.lua
@@ -21,12 +21,22 @@
-- imports
import("core.cache.detectcache")
+-- is linker?
+function _islinker(flags, opt)
+ local flags_str = table.concat(flags, " ")
+ if flags_str:startswith("-C linkarg=") then
+ return true
+ end
+ local toolkind = opt.toolkind or ""
+ return toolkind == "ld" or toolkind == "sh" or toolkind:endswith("ld") or toolkind:endswith("sh")
+end
+
-- try running
function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- attempt to check it from the argument list
@@ -64,7 +74,7 @@ function _check_from_arglist(flags, opt)
end
-- try running to check flags
-function _check_try_running(flags, opt)
+function _check_try_running(flags, opt, islinker)
-- make an stub source file
local sourcefile = path.join(os.tmpdir(), "detect", "rustc_has_flags.rs")
@@ -72,14 +82,15 @@ function _check_try_running(flags, opt)
io.writefile(sourcefile, "fn main() {\n}")
end
- -- check it
+ -- check flags for linker
+ if islinker then
+ return _try_running(opt.program, table.join("--crate-type=bin", flags, "-o", os.tmpfile(), sourcefile), opt)
+ end
+
+ -- check flags for compiler
local objectfile = os.tmpfile() .. ".o"
local ok, errors = _try_running(opt.program, table.join("--emit", "obj", flags, "-o", objectfile, sourcefile))
-
- -- remove files
os.tryrm(objectfile)
-
- -- ok?
return ok, errors
end
@@ -91,12 +102,15 @@ end
--
function main(flags, opt)
+ -- is linker?
+ local islinker = _islinker(flags, opt)
+
-- attempt to check it from the argument list
if _check_from_arglist(flags, opt) then
return true
end
-- try running to check it
- return _check_try_running(flags, opt)
+ return _check_try_running(flags, opt, islinker)
end
diff --git a/xmake/modules/detect/tools/sdcc/has_flags.lua b/xmake/modules/detect/tools/sdcc/has_flags.lua
index 1198b6f44..c7c440a8a 100644
--- a/xmake/modules/detect/tools/sdcc/has_flags.lua
+++ b/xmake/modules/detect/tools/sdcc/has_flags.lua
@@ -41,7 +41,7 @@ function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- attempt to check it from the argument list
diff --git a/xmake/modules/detect/tools/swiftc/has_flags.lua b/xmake/modules/detect/tools/swiftc/has_flags.lua
index 541b897a9..fc4ff6540 100644
--- a/xmake/modules/detect/tools/swiftc/has_flags.lua
+++ b/xmake/modules/detect/tools/swiftc/has_flags.lua
@@ -26,7 +26,7 @@ function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- attempt to check it from the argument list
diff --git a/xmake/modules/detect/tools/zig/has_flags.lua b/xmake/modules/detect/tools/zig/has_flags.lua
index b12f3defb..1dea91cfe 100644
--- a/xmake/modules/detect/tools/zig/has_flags.lua
+++ b/xmake/modules/detect/tools/zig/has_flags.lua
@@ -34,7 +34,7 @@ function _try_running(...)
local argv = {...}
local errors = nil
- return try { function () os.runv(unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
+ return try { function () os.runv(table.unpack(argv)); return true end, catch { function (errs) errors = (errs or ""):trim() end }}, errors
end
-- attempt to check it from the argument list
diff --git a/xmake/modules/devel/git/apply.lua b/xmake/modules/devel/git/apply.lua
index 97923da02..ccfd5bf80 100644
--- a/xmake/modules/devel/git/apply.lua
+++ b/xmake/modules/devel/git/apply.lua
@@ -44,17 +44,6 @@ function main(patchfile, opt)
opt = opt or {}
local argv = {"apply", "--reject", "--ignore-whitespace", patchfile}
- -- enter repository directory
- local oldir = nil
- if opt.repodir then
- oldir = os.cd(opt.repodir)
- end
-
-- apply it
- os.vrunv(git.program, argv)
-
- -- leave repository directory
- if oldir then
- os.cd(oldir)
- end
+ os.vrunv(git.program, argv, {curdir = opt.repodir})
end
diff --git a/xmake/modules/devel/git/checkout.lua b/xmake/modules/devel/git/checkout.lua
index 7a32aa3b1..c78d8f439 100644
--- a/xmake/modules/devel/git/checkout.lua
+++ b/xmake/modules/devel/git/checkout.lua
@@ -47,17 +47,6 @@ function main(commit, opt)
-- init argv
local argv = {"checkout", commit}
- -- enter repository directory
- local oldir = nil
- if opt.repodir then
- oldir = os.cd(opt.repodir)
- end
-
-- checkout it
- os.vrunv(git.program, argv)
-
- -- leave repository directory
- if oldir then
- os.cd(oldir)
- end
+ os.vrunv(git.program, argv, {curdir = opt.repodir})
end
diff --git a/xmake/modules/devel/git/clean.lua b/xmake/modules/devel/git/clean.lua
index ae21c3d88..52fa81a0b 100644
--- a/xmake/modules/devel/git/clean.lua
+++ b/xmake/modules/devel/git/clean.lua
@@ -61,17 +61,6 @@ function main(opt)
table.insert(argv, "-x")
end
- -- enter repository directory
- local oldir = nil
- if opt.repodir then
- oldir = os.cd(opt.repodir)
- end
-
-- clean it
- os.vrunv(git.program, argv)
-
- -- leave repository directory
- if oldir then
- os.cd(oldir)
- end
+ os.vrunv(git.program, argv, {curdir = opt.repodir})
end
diff --git a/xmake/modules/devel/git/lastcommit.lua b/xmake/modules/devel/git/lastcommit.lua
new file mode 100644
index 000000000..1ad6de1f4
--- /dev/null
+++ b/xmake/modules/devel/git/lastcommit.lua
@@ -0,0 +1,66 @@
+--!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 lastcommit.lua
+--
+
+-- imports
+import("core.base.option")
+import("lib.detect.find_tool")
+import("net.proxy")
+
+-- get last commit in git repository
+--
+-- @param opt the options, e.g. {repodir = ..}
+--
+-- @return the last commit
+--
+-- @code
+--
+-- import("devel.git")
+--
+-- local lastcommit = git.lastcommit({repodir = ..})
+--
+-- @endcode
+--
+function main(opt)
+
+ -- find git
+ local git = assert(find_tool("git"), "git not found!")
+
+ -- init arguments
+ local argv = {"rev-parse", "HEAD"}
+
+ -- trace
+ if option.get("verbose") then
+ print("%s %s", git.program, os.args(argv))
+ end
+
+ -- use proxy?
+ local envs
+ local proxy_conf = proxy.config(url)
+ if proxy_conf then
+ envs = {ALL_PROXY = proxy_conf}
+ end
+
+ -- get last commit
+ local lastcommit = os.iorunv(git.program, argv, {envs = envs, curdir = opt.repodir})
+ if lastcommit then
+ lastcommit = lastcommit:trim()
+ end
+ return lastcommit
+end
diff --git a/xmake/modules/devel/git/pull.lua b/xmake/modules/devel/git/pull.lua
index 9970f8dbc..412e6e757 100644
--- a/xmake/modules/devel/git/pull.lua
+++ b/xmake/modules/devel/git/pull.lua
@@ -58,18 +58,12 @@ function main(opt)
table.insert(argv, "--tags")
end
- -- enter repository directory
- local oldir = nil
- if opt.repodir then
- oldir = os.cd(opt.repodir)
- end
-
-- use proxy?
local envs
local proxy_conf = proxy.config()
if proxy_conf then
-- get proxy configuration from the current remote url
- local remoteinfo = try { function() return os.iorunv(git.program, {"remote", "-v"}) end }
+ local remoteinfo = try { function() return os.iorunv(git.program, {"remote", "-v"}, {curdir = opt.repodir}) end }
if remoteinfo then
for _, line in ipairs(remoteinfo:split('\n', {plain = true})) do
local splitinfo = line:split("%s+")
@@ -86,10 +80,5 @@ function main(opt)
end
-- pull it
- os.vrunv(git.program, argv, {envs = envs})
-
- -- leave repository directory
- if oldir then
- os.cd(oldir)
- end
+ os.vrunv(git.program, argv, {envs = envs, curdir = opt.repodir})
end
diff --git a/xmake/modules/devel/git/reset.lua b/xmake/modules/devel/git/reset.lua
index 28b984008..4ed798d25 100644
--- a/xmake/modules/devel/git/reset.lua
+++ b/xmake/modules/devel/git/reset.lua
@@ -71,17 +71,6 @@ function main(opt)
table.insert(argv, opt.commit)
end
- -- enter repository directory
- local oldir = nil
- if opt.repodir then
- oldir = os.cd(opt.repodir)
- end
-
-- reset it
- os.vrunv(git.program, argv)
-
- -- leave repository directory
- if oldir then
- os.cd(oldir)
- end
+ os.vrunv(git.program, argv, {curdir = opt.repodir})
end
diff --git a/xmake/modules/devel/git/submodule/update.lua b/xmake/modules/devel/git/submodule/update.lua
index 5d9323a02..511684c1c 100644
--- a/xmake/modules/devel/git/submodule/update.lua
+++ b/xmake/modules/devel/git/submodule/update.lua
@@ -58,37 +58,26 @@ function main(opt)
table.join2(argv, opt.paths)
end
- -- enter repository directory
- local oldir = nil
- if opt.repodir then
- oldir = os.cd(opt.repodir)
- end
-
-- enable long paths
local longpaths_old
local longpaths_changed = false
if opt.longpaths then
- local longpaths_old = try {function () return os.iorunv(git.program, {"config", "--get", "--global", "core.longpaths"}) end}
+ local longpaths_old = try {function () return os.iorunv(git.program, {"config", "--get", "--global", "core.longpaths"}, {curdir = opt.repodir}) end}
if not longpaths_old or not longpaths_old:find("true") then
- os.vrunv(git.program, {"config", "--global", "core.longpaths", "true"})
+ os.vrunv(git.program, {"config", "--global", "core.longpaths", "true"}, {curdir = opt.repodir})
longpaths_changed = true
end
end
-- submodule it
- os.vrunv(git.program, argv)
+ os.vrunv(git.program, argv, {curdir = opt.repodir})
-- restore old long paths configuration
if longpaths_changed then
if longpaths_old and longpaths_old:find("false") then
- os.vrunv(git.program, {"config", "--global", "core.longpaths", "false"})
+ os.vrunv(git.program, {"config", "--global", "core.longpaths", "false"}, {curdir = opt.repodir})
else
- os.vrunv(git.program, {"config", "--global", "--unset", "core.longpaths"})
+ os.vrunv(git.program, {"config", "--global", "--unset", "core.longpaths"}, {curdir = opt.repodir})
end
end
-
- -- leave repository directory
- if oldir then
- os.cd(oldir)
- end
end
diff --git a/xmake/modules/lib/detect/check_cxsnippets.lua b/xmake/modules/lib/detect/check_cxsnippets.lua
index aa728e27b..ea0e941d3 100644
--- a/xmake/modules/lib/detect/check_cxsnippets.lua
+++ b/xmake/modules/lib/detect/check_cxsnippets.lua
@@ -77,7 +77,11 @@ function _sourcecode(snippets, opt)
-- add includes
local sourcecode = ""
- for _, include in ipairs(opt.includes) do
+ local includes = table.wrap(opt.includes)
+ if opt.tryrun and opt.output then
+ table.insert(includes, "stdio.h")
+ end
+ for _, include in ipairs(includes) do
sourcecode = format("%s\n#include <%s>", sourcecode, include)
end
sourcecode = sourcecode .. "\n"
@@ -88,11 +92,13 @@ function _sourcecode(snippets, opt)
end
sourcecode = sourcecode .. "\n"
- -- add snippets
- for _, snippet in pairs(snippets) do
- sourcecode = sourcecode .. "\n" .. snippet
+ -- add snippets (build only)
+ if not opt.tryrun then
+ for _, snippet in pairs(snippets) do
+ sourcecode = sourcecode .. "\n" .. snippet
+ end
+ sourcecode = sourcecode .. "\n"
end
- sourcecode = sourcecode .. "\n"
-- enter main function
sourcecode = sourcecode .. "int main(int argc, char** argv)\n{\n"
@@ -102,10 +108,19 @@ function _sourcecode(snippets, opt)
sourcecode = format("%s\n %s;", sourcecode, _funccode(funcinfo))
end
- -- leave main function
- sourcecode = sourcecode .. "\n return 0;\n}\n"
-
- -- done
+ -- add snippets (tryrun)
+ if opt.tryrun then
+ for _, snippet in pairs(snippets) do
+ sourcecode = sourcecode .. "\n" .. snippet
+ end
+ if opt.output then
+ sourcecode = sourcecode .. "\nfflush(stdout);\n"
+ end
+ sourcecode = sourcecode .. "\n}\n" -- we need return exit code in snippet
+ else
+ -- leave main function
+ sourcecode = sourcecode .. "\n return 0;\n}\n"
+ end
return sourcecode
end
@@ -116,7 +131,8 @@ end
-- e.g.
-- { verbose = false, target = [target|option], sourcekind = "[cc|cxx]"
-- , types = {"wchar_t", "char*"}, includes = "stdio.h", funcs = {"sigsetjmp", "sigsetjmp((void*)0, 0)"}
--- , configs = {defines = "xx", cxflags = ""}}
+-- , configs = {defines = "xx", cxflags = ""}
+-- , tryrun = true, output = true}
--
-- funcs:
-- sigsetjmp
@@ -127,9 +143,9 @@ end
-- @return true or false
--
-- @code
--- local ok = check_cxsnippets("void test() {}")
--- local ok = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
--- local ok = check_cxsnippets({snippet_name = "void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
+-- local ok, output_or_errors = check_cxsnippets("void test() {}")
+-- local ok, output_or_errors = check_cxsnippets({"void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
+-- local ok, output_or_errors = check_cxsnippets({snippet_name = "void test(){}", "#define TEST 1"}, {types = "wchar_t", includes = "stdio.h"})
-- @endcode
--
function main(snippets, opt)
@@ -189,19 +205,30 @@ function main(snippets, opt)
-- @note cannot cache result, all conditions will be changed
-- attempt to compile it
local errors = nil
- local ok = try
+ local ok, output = try
{
function ()
if option.get("diagnosis") then
cprint("${dim}> %s", compiler.compcmd(sourcefile, objectfile, opt))
end
compiler.compile(sourcefile, objectfile, opt)
- if #links > 0 then
+ if #links > 0 or opt.tryrun then
if option.get("diagnosis") then
cprint("${dim}> %s", linker.linkcmd("binary", {"cc", "cxx"}, objectfile, binaryfile, opt))
end
linker.link("binary", {"cc", "cxx"}, objectfile, binaryfile, opt)
end
+ if opt.tryrun then
+ if opt.output then
+ local output = os.iorun(binaryfile)
+ if output then
+ output = output:trim()
+ end
+ return true, output
+ else
+ os.vrun(binaryfile)
+ end
+ end
return true
end,
catch { function (errs) errors = errs end }
@@ -238,6 +265,6 @@ function main(snippets, opt)
if errors and option.get("diagnosis") and #tostring(errors) > 0 then
cprint("${color.warning}checkinfo:${clear dim} %s", errors)
end
- return ok
+ return ok, ok and output or errors
end
diff --git a/xmake/modules/lib/detect/features.lua b/xmake/modules/lib/detect/features.lua
index 614d8c592..8b9bde45b 100644
--- a/xmake/modules/lib/detect/features.lua
+++ b/xmake/modules/lib/detect/features.lua
@@ -79,12 +79,7 @@ function main(name, opt)
end
_g._checking = nil
- -- no features?
result = result or {}
-
- -- save result to cache
results[key] = result
-
- -- ok?
return result
end
diff --git a/xmake/modules/lib/detect/find_package.lua b/xmake/modules/lib/detect/find_package.lua
index 7b7ba7032..d3c9e57d1 100644
--- a/xmake/modules/lib/detect/find_package.lua
+++ b/xmake/modules/lib/detect/find_package.lua
@@ -24,6 +24,30 @@ import("core.project.config")
import("core.cache.detectcache")
import("package.manager.find_package")
+-- concat packages
+function _concat_packages(a, b)
+ local result = table.copy(a)
+ for k, v in pairs(b) do
+ local o = result[k]
+ if o ~= nil then
+ v = table.join(o, v)
+ end
+ result[k] = v
+ end
+ for k, v in pairs(result) do
+ if k == "links" then
+ if type(v) == "table" and #v > 1 then
+ -- we need ensure link orders when removing repeat values
+ v = table.reverse_unique(v)
+ end
+ else
+ v = table.unique(v)
+ end
+ result[k] = v
+ end
+ return result
+end
+
-- find package using the package manager
--
-- @param name the package name
@@ -113,5 +137,10 @@ function main(name, opt)
if not opt.version and result then
result.version = nil
end
+
+ -- register concat
+ if result and type(result) == "table" then
+ debug.setmetatable(result, {__concat = _concat_packages})
+ end
return result and result or nil
end
diff --git a/xmake/modules/lib/detect/pkgconfig.lua b/xmake/modules/lib/detect/pkgconfig.lua
index 9cd07a1e7..cf6b6d97d 100644
--- a/xmake/modules/lib/detect/pkgconfig.lua
+++ b/xmake/modules/lib/detect/pkgconfig.lua
@@ -24,7 +24,15 @@ import("core.project.target")
import("core.project.config")
import("lib.detect.find_file")
import("lib.detect.find_library")
-import("detect.tools.find_pkg_config")
+import("lib.detect.find_tool")
+
+-- get pkgconfig
+function _get_pkgconfig()
+ local pkgconfig = find_tool("pkg-config") or find_tool("pkgconf")
+ if pkgconfig then
+ return pkgconfig.program
+ end
+end
-- get version
--
@@ -34,7 +42,7 @@ import("detect.tools.find_pkg_config")
function version(name, opt)
-- attempt to add search paths from pkg-config
- local pkgconfig = find_pkg_config()
+ local pkgconfig = _get_pkgconfig()
if not pkgconfig then
return
end
@@ -46,7 +54,7 @@ function version(name, opt)
local configdirs_old = os.getenv("PKG_CONFIG_PATH")
local configdirs = table.wrap(opt.configdirs)
if #configdirs > 0 then
- os.setenv("PKG_CONFIG_PATH", unpack(configdirs))
+ os.setenv("PKG_CONFIG_PATH", table.unpack(configdirs))
end
-- get version
@@ -73,7 +81,7 @@ end
function variables(name, variables, opt)
-- attempt to add search paths from pkg-config
- local pkgconfig = find_pkg_config()
+ local pkgconfig = _get_pkgconfig()
if not pkgconfig then
return
end
@@ -85,7 +93,7 @@ function variables(name, variables, opt)
local configdirs_old = os.getenv("PKG_CONFIG_PATH")
local configdirs = table.wrap(opt.configdirs)
if #configdirs > 0 then
- os.setenv("PKG_CONFIG_PATH", unpack(configdirs))
+ os.setenv("PKG_CONFIG_PATH", table.unpack(configdirs))
end
-- get variable value
@@ -125,7 +133,7 @@ end
function libinfo(name, opt)
-- attempt to add search paths from pkg-config
- local pkgconfig = find_pkg_config()
+ local pkgconfig = _get_pkgconfig()
if not pkgconfig then
return
end
diff --git a/xmake/modules/net/ping.lua b/xmake/modules/net/ping.lua
index 5f555cccd..93e9b4bec 100644
--- a/xmake/modules/net/ping.lua
+++ b/xmake/modules/net/ping.lua
@@ -88,7 +88,7 @@ function main(hosts, opt)
end
-- trace
- vprint("pinging for the host(%s) ... %d ms", host, timeval)
+ vprint("pinging for the host(%s) ... %d ms", host, math.floor(timeval))
end
end
end, {total = #hosts})
diff --git a/xmake/modules/package/manager/apt/find_package.lua b/xmake/modules/package/manager/apt/find_package.lua
index f27968c0e..e2617b4ec 100644
--- a/xmake/modules/package/manager/apt/find_package.lua
+++ b/xmake/modules/package/manager/apt/find_package.lua
@@ -24,26 +24,8 @@ import("core.project.config")
import("core.project.target")
import("lib.detect.find_tool")
--- find package using the dpkg package manager
---
--- @param name the package name
--- @param opt the options, e.g. {verbose = true, version = "1.12.0")
---
-function main(name, opt)
-
- -- check
- opt = opt or {}
- if not is_host(opt.plat) or os.arch() ~= opt.arch then
- return
- end
-
- -- find dpkg
- local dpkg = find_tool("dpkg")
- if not dpkg then
- return
- end
-
- -- find package
+-- find package
+function _find_package(dpkg, name, opt)
local result = nil
local listinfo = try {function () return os.iorunv(dpkg.program, {"--listfiles", name}) end}
if listinfo then
@@ -51,14 +33,11 @@ function main(name, opt)
line = line:trim()
-- get includedirs
- -- we need not add it, gcc/clang will use /usr/ as default sysroot
- --[[
local pos = line:find("include/", 1, true)
if pos then
+ -- we need not add includedirs, gcc/clang will use /usr/ as default sysroot
result = result or {}
- result.includedirs = result.includedirs or {}
- table.insert(result.includedirs, line:sub(1, pos + 7))
- end]]
+ end
-- get linkdirs and links
if line:endswith(".a") or line:endswith(".so") then
@@ -67,12 +46,30 @@ function main(name, opt)
result.linkdirs = result.linkdirs or {}
result.libfiles = result.libfiles or {}
table.insert(result.linkdirs, path.directory(line))
- table.insert(result.links, target.linkname(path.filename(line)))
+ table.insert(result.links, target.linkname(path.filename(line), {plat = opt.plat}))
table.insert(result.libfiles, path.join(path.directory(line), path.filename(line)))
end
end
end
+ -- meta/alias package? e.g. libboost-dev -> libboost1.74-dev
+ -- @see https://github.com/xmake-io/xmake/issues/1786
+ if not result then
+ local statusinfo = try {function () return os.iorunv(dpkg.program, {"--status", name}) end}
+ if statusinfo then
+ for _, line in ipairs(statusinfo:split("\n", {plain = true})) do
+ -- parse depends, e.g. Depends: libboost1.74-dev
+ if line:startswith("Depends:") then
+ local depends = line:sub(9):split("%s+")
+ if #depends == 1 then
+ return _find_package(dpkg, depends[1], opt)
+ end
+ break
+ end
+ end
+ end
+ end
+
-- remove repeat
if result then
if result.links then
@@ -87,3 +84,26 @@ function main(name, opt)
end
return result
end
+
+-- find package using the dpkg package manager
+--
+-- @param name the package name
+-- @param opt the options, e.g. {verbose = true, version = "1.12.0")
+--
+function main(name, opt)
+
+ -- check
+ opt = opt or {}
+ if not is_host(opt.plat) or os.arch() ~= opt.arch then
+ return
+ end
+
+ -- find dpkg
+ local dpkg = find_tool("dpkg")
+ if not dpkg then
+ return
+ end
+
+ -- find package
+ return _find_package(dpkg, name, opt)
+end
diff --git a/xmake/modules/package/manager/brew/find_package.lua b/xmake/modules/package/manager/brew/find_package.lua
index 49db5a464..9706bfd8e 100644
--- a/xmake/modules/package/manager/brew/find_package.lua
+++ b/xmake/modules/package/manager/brew/find_package.lua
@@ -67,14 +67,16 @@ function main(name, opt)
-- find package from pkg-config/*.pc, attempt to find it from `brew --prefix`/package first
local result = nil
- local pcfile = find_file(pcname .. ".pc", path.join(brew_pkg_rootdir, nameinfo[1], "*/lib/pkgconfig"))
+ local pcfile = find_file(pcname .. ".pc", path.join(brew_pkg_rootdir, nameinfo[1], "*/lib/pkgconfig")) or
+ find_file(pcname .. ".pc", path.join(brew_pkg_rootdir, nameinfo[1], "*/share/pkgconfig"))
if not pcfile then
-- attempt to find it from `brew --prefix package`
local brew = find_tool("brew")
local brew_pkgdir = brew and try {function () return os.iorunv(brew.program, {"--prefix", nameinfo[1]}) end}
if brew_pkgdir then
brew_pkgdir = brew_pkgdir:trim()
- pcfile = find_file(pcname .. ".pc", path.join(brew_pkgdir, "lib/pkgconfig"))
+ pcfile = find_file(pcname .. ".pc", path.join(brew_pkgdir, "lib/pkgconfig")) or
+ find_file(pcname .. ".pc", path.join(brew_pkgdir, "share/pkgconfig"))
end
end
if pcfile then
@@ -97,11 +99,11 @@ function main(name, opt)
if pkgdir then
local links = {}
for _, libfile in ipairs(os.files(path.join(pkgdir, "lib", "*.a"))) do
- table.insert(links, target.linkname(path.filename(libfile)))
+ table.insert(links, target.linkname(path.filename(libfile), {plat = opt.plat}))
end
for _, libfile in ipairs(os.files(path.join(pkgdir, "lib", opt.plat == "macosx" and "*.dylib" or "*.so"))) do
if not os.islink(libfile) then
- table.insert(links, target.linkname(path.filename(libfile)))
+ table.insert(links, target.linkname(path.filename(libfile), {plat = opt.plat}))
end
end
opt.links = links
diff --git a/xmake/modules/package/manager/cargo/configurations.lua b/xmake/modules/package/manager/cargo/configurations.lua
new file mode 100644
index 000000000..a3f85a0ea
--- /dev/null
+++ b/xmake/modules/package/manager/cargo/configurations.lua
@@ -0,0 +1,28 @@
+--!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 configurations.lua
+--
+
+-- get configurations
+function main()
+ return
+ {
+ features = {description = "set the features of dependency."},
+ default_features = {description = "enables or disables any defaults provided by the dependency.", default = true},
+ }
+end
diff --git a/xmake/modules/package/manager/cargo/find_package.lua b/xmake/modules/package/manager/cargo/find_package.lua
new file mode 100644
index 000000000..7fd151d5c
--- /dev/null
+++ b/xmake/modules/package/manager/cargo/find_package.lua
@@ -0,0 +1,58 @@
+--!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 find_package.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.semver")
+import("core.project.config")
+import("core.project.target")
+import("lib.detect.find_tool")
+import("lib.detect.find_file")
+
+-- find package using the cargo package manager
+--
+-- @param name the package name
+-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x")
+--
+function main(name, opt)
+ local frameworkdirs
+ local frameworks
+ local librarydir = path.join(opt.installdir, "lib")
+ local libfiles = os.files(path.join(librarydir, "*.rlib"))
+ for _, libraryfile in ipairs(libfiles) do
+ local filename = path.filename(libraryfile)
+ if filename:startswith("lib" .. name .. "-") then
+ frameworkdirs = frameworkdirs or {}
+ frameworks = frameworks or {}
+ table.insert(frameworkdirs, librarydir)
+ table.insert(frameworks, libraryfile)
+ break
+ end
+ end
+ local result
+ if frameworks and frameworkdirs then
+ result = result or {}
+ result.libfiles = libfiles
+ result.frameworkdirs = frameworkdirs
+ result.frameworks = frameworks
+ result.version = opt.require_version
+ end
+ return result
+end
diff --git a/xmake/modules/package/manager/cargo/install_package.lua b/xmake/modules/package/manager/cargo/install_package.lua
new file mode 100644
index 000000000..9ea709dd7
--- /dev/null
+++ b/xmake/modules/package/manager/cargo/install_package.lua
@@ -0,0 +1,95 @@
+--!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 install_package.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.config")
+import("lib.detect.find_tool")
+
+-- install package
+--
+-- e.g.
+-- add_requires("cargo::base64")
+-- add_requires("cargo::base64 0.13.0")
+-- add_requires("cargo::flate2 1.0.17", {configs = {features = {"zlib"}, ["default-features"] = false}})
+--
+-- @param name the package name, e.g. cargo::base64
+-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"}
+--
+-- @return true or false
+--
+function main(name, opt)
+
+ -- find cargo
+ local cargo = find_tool("cargo")
+ if not cargo then
+ raise("cargo not found!")
+ end
+
+ -- get required version
+ opt = opt or {}
+ local configs = opt.configs or {}
+ local require_version = opt.require_version
+ if not require_version or require_version == "latest" then
+ require_version = "*"
+ end
+
+ -- build dependencies
+ local sourcedir = path.join(opt.cachedir, "source")
+ local cargotoml = path.join(sourcedir, "Cargo.toml")
+ os.tryrm(sourcedir)
+ local tomlfile = io.open(cargotoml, "w")
+ tomlfile:print("[package]")
+ tomlfile:print("name = \"cargodeps\"")
+ tomlfile:print("version = \"0.1.0\"")
+ tomlfile:print("edition = \"2018\"")
+ tomlfile:print("")
+ tomlfile:print("[dependencies]")
+ local features = configs.features
+ if features then
+ features = table.wrap(features)
+ tomlfile:print("%s = {version = \"%s\", features = [\"%s\"], default-features = %s}", name, require_version, table.concat(features, "\", \""), configs.default_features)
+ else
+ tomlfile:print("%s = \"%s\"", name, require_version)
+ end
+ tomlfile:close()
+
+ -- generate main.rs
+ io.writefile(path.join(sourcedir, "src", "main.rs"), [[
+fn main() {
+ println!("Hello, world!");
+}
+ ]])
+
+ -- do build
+ local argv = {"build"}
+ if opt.mode ~= "debug" then
+ table.insert(argv, "--release")
+ end
+ if option.get("verbose") then
+ table.insert(argv, option.get("diagnosis") and "-vv" or "-v")
+ end
+ os.vrunv(cargo.program, argv, {curdir = sourcedir})
+
+ -- do install
+ local installdir = opt.installdir
+ os.tryrm(path.join(installdir, "lib"))
+ os.vcp(path.join(sourcedir, "target", opt.mode == "debug" and "debug" or "release", "deps"), path.join(installdir, "lib"))
+end
diff --git a/xmake/modules/package/manager/clib/configurations.lua b/xmake/modules/package/manager/clib/configurations.lua
new file mode 100644
index 000000000..4f59ea70d
--- /dev/null
+++ b/xmake/modules/package/manager/clib/configurations.lua
@@ -0,0 +1,30 @@
+--!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 Adel Vilkov (aka RaZeR-RBI)
+-- @file configurations.lua
+--
+
+-- get configurations
+function main()
+ return
+ {
+ save = {description = "save dependency in project's package.json", default = false, type = "boolean"},
+ save_dev = {description = "save as development dependency in project's package.json", default = false, type = "boolean"},
+ outputdir = {description = "package installation directory relative to project root", default = "clib"},
+ }
+end
+
diff --git a/xmake/modules/package/manager/clib/install_package.lua b/xmake/modules/package/manager/clib/install_package.lua
index 1b61af5b4..0257ff8fe 100644
--- a/xmake/modules/package/manager/clib/install_package.lua
+++ b/xmake/modules/package/manager/clib/install_package.lua
@@ -23,42 +23,35 @@ import("core.base.option")
import("core.project.config")
import("lib.detect.find_tool")
--- get configurations
-function configurations()
- return
- {
- save = {description = "save dependency in project's package.json", default = false, type = "boolean"},
- save_dev = {description = "save as development dependency in project's package.json", default = false, type = "boolean"},
- outputdir = {description = "package installation directory relative to project root", default = "clib"},
- }
-end
-
-- install package
-- @param name the package name, e.g. clib::clibs/[email protected]
-- @param opt the options, e.g. { verbose = true,
--- settings = {outputdir = "clib", save = false, save_dev = false}}
+-- configs = {outputdir = "clib", save = false, save_dev = false}}
--
-- @return true or false
--
function main(name, opt)
+
-- find clib
local clib = find_tool("clib")
if not clib then
raise("clib not found!")
end
+ opt = opt or {}
+ local configs = opt.configs or {}
local argv = {"install", name}
- local abs_out = path.join(os.projectdir(), opt.outputdir)
+ local abs_out = path.join(os.projectdir(), configs.outputdir)
dprint("installing %s to %s", name, abs_out)
table.insert(argv, "-o " .. abs_out)
if not option.get("verbose") then
table.insert(argv, "-q")
end
- if opt.save then
+ if configs.save then
table.insert(argv, "--save")
end
- if opt.save_dev then
+ if configs.save_dev then
table.insert(argv, "--save-dev")
end
diff --git a/xmake/modules/package/manager/cmake/configurations.lua b/xmake/modules/package/manager/cmake/configurations.lua
new file mode 100644
index 000000000..e65525f6d
--- /dev/null
+++ b/xmake/modules/package/manager/cmake/configurations.lua
@@ -0,0 +1,31 @@
+--!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 configurations.lua
+--
+
+-- get configurations
+function main()
+ return
+ {
+ components = {description = "Set the cmake package components, e.g. {\"regex\", \"system\"}"},
+ moduledirs = {description = "Set the cmake modules directories."},
+ presets = {description = "Set the preset values, e.g. {Boost_USE_STATIC_LIB = true}"},
+ envs = {description = "Set the run environments of cmake, e.g. {CMAKE_PREFIX_PATH = \"xxx\"}"},
+ }
+end
+
diff --git a/xmake/modules/package/manager/cmake/find_package.lua b/xmake/modules/package/manager/cmake/find_package.lua
new file mode 100644
index 000000000..d9abd6b00
--- /dev/null
+++ b/xmake/modules/package/manager/cmake/find_package.lua
@@ -0,0 +1,282 @@
+--!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 find_package.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.target")
+import("lib.detect.find_tool")
+
+-- find package
+function _find_package(cmake, name, opt)
+
+ -- get work directory
+ local workdir = os.tmpfile() .. ".dir"
+ os.tryrm(workdir)
+ os.mkdir(workdir)
+ io.writefile(path.join(workdir, "test.cpp"), "")
+
+ -- generate CMakeLists.txt
+ local cmakefile = io.open(path.join(workdir, "CMakeLists.txt"), "w")
+ if cmake.version then
+ cmakefile:print("cmake_minimum_required(VERSION %s)", cmake.version)
+ end
+ cmakefile:print("project(find_package)")
+
+ -- e.g. OpenCV 4.1.1, Boost COMPONENTS regex system
+ local requirestr = name
+ local configs = opt.configs or {}
+ if opt.required_version then
+ requirestr = requirestr .. " " .. opt.required_version
+ end
+ -- use opt.components is for backward compatibility
+ local components = configs.components or opt.components
+ if components then
+ requirestr = requirestr .. " COMPONENTS"
+ for _, component in ipairs(components) do
+ requirestr = requirestr .. " " .. component
+ end
+ end
+ local moduledirs = configs.moduledirs or opt.moduledirs
+ if moduledirs then
+ for _, moduledir in ipairs(moduledirs) do
+ cmakefile:print("add_cmake_modules(%s)", moduledir)
+ end
+ end
+ -- e.g. set(Boost_USE_STATIC_LIB ON)
+ local presets = configs.presets or opt.presets
+ if presets then
+ for k, v in pairs(presets) do
+ if type(v) == "boolean" then
+ cmakefile:print("set(%s %s)", k, v and "ON" or "OFF")
+ else
+ cmakefile:print("set(%s %s)", k, tostring(v))
+ end
+ end
+ end
+ cmakefile:print("find_package(%s REQUIRED)", requirestr)
+ cmakefile:print("if(%s_FOUND)", name)
+ cmakefile:print(" add_executable(%s test.cpp)", name)
+ cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})",
+ name, name, name)
+ cmakefile:print(" target_include_directories(%s PRIVATE ${%s_INCLUDE_DIR} ${%s_INCLUDE_DIRS})",
+ name, name:upper(), name:upper())
+ cmakefile:print(" target_include_directories(%s PRIVATE ${%s_CXX_INCLUDE_DIRS})",
+ name, name)
+ cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})",
+ name, name, name, name)
+ cmakefile:print(" target_link_libraries(%s ${%s_LIBRARY} ${%s_LIBRARIES} ${%s_LIBS})",
+ name, name:upper(), name:upper(), name:upper())
+ cmakefile:print("endif(%s_FOUND)", name)
+ cmakefile:close()
+
+ -- run cmake
+ local envs = configs.envs or opt.envs
+ try {function() return os.vrunv(cmake.program, {workdir}, {curdir = workdir, envs = envs}) end}
+
+ -- pares defines and includedirs for macosx/linux
+ local links
+ local linkdirs
+ local libfiles
+ local defines
+ local includedirs
+ local ldflags
+ local flagsfile = path.join(workdir, "CMakeFiles", name .. ".dir", "flags.make")
+ if os.isfile(flagsfile) then
+ local flagsdata = io.readfile(flagsfile)
+ if flagsdata then
+ if option.get("diagnosis") then
+ vprint(flagsdata)
+ end
+ for _, line in ipairs(flagsdata:split("\n", {plain = true})) do
+ if line:find("CXX_INCLUDES =", 1, true) then
+ local has_include = false
+ local flags = os.argv(line:split("=", {plain = true})[2]:trim())
+ for _, flag in ipairs(flags) do
+ if has_include or (flag:startswith("-I") and #flag > 2) then
+ local includedir = has_include and flag or flag:sub(3)
+ if includedir and os.isdir(includedir) then
+ includedirs = includedirs or {}
+ table.insert(includedirs, includedir)
+ end
+ has_include = false
+ elseif flag == "-isystem" or flag == "-I" then
+ has_include = true
+ end
+ end
+ elseif line:find("CXX_DEFINES =", 1, true) then
+ local flags = os.argv(line:split("=", {plain = true})[2]:trim())
+ for _, flag in ipairs(flags) do
+ if flag:startswith("-D") and #flag > 2 then
+ local define = flag:sub(3)
+ if define then
+ defines = defines or {}
+ table.insert(defines, define)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ -- parse links and linkdirs for macosx/linux
+ local linkfile = path.join(workdir, "CMakeFiles", name .. ".dir", "link.txt")
+ if os.isfile(linkfile) then
+ local linkdata = io.readfile(linkfile)
+ if linkdata then
+ if option.get("diagnosis") then
+ vprint(linkdata)
+ end
+ for _, line in ipairs(os.argv(linkdata)) do
+ local is_ldflags = false
+ local is_library = false
+ for _, suffix in ipairs({".so", ".dylib", ".dylib", ".tbd", ".lib"}) do
+ if line:startswith("-Wl,") then
+ is_ldflags = true
+ break
+ elseif line:find(suffix, 1, true) then
+ is_library = true
+ break
+ end
+ end
+ if is_ldflags then
+ ldflags = ldflags or {}
+ table.insert(ldflags, line)
+ elseif is_library then
+ -- strip library version suffix, e.g. libxxx.so.1.1 -> libxxx.so
+ if line:find(".so", 1, true) then
+ line = line:gsub("lib(.-)%.so%..+$", "lib%1.so")
+ end
+
+ -- get libfiles
+ if os.isfile(line) then
+ libfiles = libfiles or {}
+ table.insert(libfiles, line)
+ end
+
+ -- get links and linkdirs
+ local linkdir = path.directory(line)
+ if linkdir ~= "." then
+ linkdirs = linkdirs or {}
+ table.insert(linkdirs, linkdir)
+ end
+ local link = target.linkname(path.filename(line))
+ if link then
+ links = links or {}
+ table.insert(links, link)
+ end
+ end
+ end
+ end
+ end
+
+ -- pares includedirs and links/linkdirs for windows
+ local vcprojfile = path.join(workdir, name .. ".vcxproj")
+ if os.isfile(vcprojfile) then
+ local vcprojdata = io.readfile(vcprojfile)
+ if vcprojdata then
+ for _, line in ipairs(vcprojdata:split("\n", {plain = true})) do
+ local values = line:match("<AdditionalIncludeDirectories>(.+);%%%(AdditionalIncludeDirectories%)</AdditionalIncludeDirectories>")
+ if values then
+ includedirs = includedirs or {}
+ table.join2(includedirs, path.splitenv(values))
+ end
+
+ values = line:match("<AdditionalDependencies>(.+)</AdditionalDependencies>")
+ if not values then
+ -- we need also parse libraries from here
+ -- https://github.com/xmake-io/xmake/issues/1822
+ values = line:match("<ImportLibrary>(.+)</ImportLibrary>")
+ end
+ if values then
+ for _, library in ipairs(path.splitenv(values)) do
+ -- get libfiles
+ if os.isfile(library) then
+ libfiles = libfiles or {}
+ table.insert(libfiles, library)
+ end
+
+ -- get links and linkdirs
+ local linkdir = path.directory(library)
+ linkdir = path.translate(linkdir)
+ if linkdir ~= "." and not linkdir:startswith(workdir) then
+ linkdirs = linkdirs or {}
+ table.insert(linkdirs, linkdir)
+ local link = target.linkname(path.filename(library))
+ if link then
+ links = links or {}
+ table.insert(links, link)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ -- remove work directory
+ os.tryrm(workdir)
+
+ -- get results
+ if links or includedirs then
+ local results = {}
+ results.links = table.reverse_unique(links)
+ results.ldflags = table.reverse_unique(ldflags)
+ results.linkdirs = table.unique(linkdirs)
+ results.defines = table.unique(defines)
+ results.libfiles = table.unique(libfiles)
+ results.includedirs = table.unique(includedirs)
+ print(results)
+ return results
+ end
+end
+
+-- find package using the cmake package manager
+--
+-- e.g.
+--
+-- find_package("cmake::ZLIB")
+-- find_package("cmake::OpenCV", {required_version = "4.1.1"})
+-- find_package("cmake::Boost", {configs = {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}})
+-- find_package("cmake::Foo", {configs = {moduledirs = "xxx"}})
+--
+-- we can use add_requires with {system = true}
+--
+-- add_requires("cmake::ZLIB", {system = true})
+-- add_requires("cmake::OpenCV 4.1.1", {system = true})
+-- add_requires("cmake::Boost", {configs = {components = {"regex", "system"}, presets = {Boost_USE_STATIC_LIB = true}}})
+-- add_requires("cmake::Foo", {configs = {moduledirs = "xxx"}})
+--
+-- @param name the package name
+-- @param opt the options, e.g. {verbose = true, required_version = "1.0",
+-- configs = {
+-- components = {"regex", "system"},
+-- moduledirs = "xxx",
+-- presets = {Boost_USE_STATIC_LIB = true},
+-- envs = {CMAKE_PREFIX_PATH = "xxx"}})
+--
+function main(name, opt)
+ opt = opt or {}
+ local cmake = find_tool("cmake", {version = true})
+ if not cmake then
+ return
+ end
+ return _find_package(cmake, name, opt)
+end
diff --git a/xmake/modules/package/manager/conan/configurations.lua b/xmake/modules/package/manager/conan/configurations.lua
new file mode 100644
index 000000000..b4ed38fc3
--- /dev/null
+++ b/xmake/modules/package/manager/conan/configurations.lua
@@ -0,0 +1,33 @@
+--!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 configurations.lua
+--
+
+-- get configurations
+function main()
+ return
+ {
+ build = {description = "Use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}},
+ remote = {description = "Set the conan remote server."},
+ options = {description = "Set the options values, e.g. OpenSSL:shared=True"},
+ imports = {description = "Set the imports for conan."},
+ settings = {description = "Set the build settings for conan."},
+ build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"}
+ }
+end
+
diff --git a/xmake/modules/package/manager/conan/find_package.lua b/xmake/modules/package/manager/conan/find_package.lua
index d372e2a75..fca3d3891 100644
--- a/xmake/modules/package/manager/conan/find_package.lua
+++ b/xmake/modules/package/manager/conan/find_package.lua
@@ -59,7 +59,7 @@ end
-- find package using the conan package manager
--
-- @param name the package name
--- @param opt the options, e.g. {verbose = true, version = "1.12.x")
+-- @param opt the options, e.g. {verbose = true)
--
function main(name, opt)
diff --git a/xmake/modules/package/manager/conan/install_package.lua b/xmake/modules/package/manager/conan/install_package.lua
index 97af3b4b8..9f5a52a18 100644
--- a/xmake/modules/package/manager/conan/install_package.lua
+++ b/xmake/modules/package/manager/conan/install_package.lua
@@ -49,15 +49,15 @@ function _conan_get_build_directory(name)
end
-- generate conanfile.txt
-function _conan_generate_conanfile(name, opt)
+function _conan_generate_conanfile(name, configs)
-- trace
dprint("generate %s ..", path.join(_conan_get_build_directory(name), "conanfile.txt"))
-- get conan options, imports and build_requires
- local options = table.wrap(opt.options)
- local imports = table.wrap(opt.imports)
- local build_requires = table.wrap(opt.build_requires)
+ local options = table.wrap(configs.options)
+ local imports = table.wrap(configs.imports)
+ local build_requires = table.wrap(configs.build_requires)
-- @see https://docs.conan.io/en/latest/systems_cross_building/cross_building.html
-- generate it
@@ -109,30 +109,22 @@ function _conan_install_xmake_generator(conan)
end
end
--- get configurations
-function configurations()
- return
- {
- build = {description = "use it to choose if you want to build from sources.", default = "missing", values = {"all", "never", "missing", "outdated"}},
- remote = {description = "Set the conan remote server."},
- options = {description = "Set the options values, e.g. OpenSSL:shared=True"},
- imports = {description = "Set the imports for conan."},
- settings = {description = "Set the build settings for conan."},
- build_requires = {description = "Set the build requires for conan.", default = "xmake_generator/0.1.0@bincrafters/testing"}
- }
-end
-
-- install package
--
-- @param name the package name, e.g. conan::OpenSSL/1.0.2n@conan/stable
-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = ,
--- remote = "", build = "all", options = {}, imports = {}, build_requires = {},
--- settings = {"compiler=Visual Studio", "compiler.version=10", "compiler.runtime=MD"}}
+-- configs = {
+-- remote = "", build = "all", options = {}, imports = {}, build_requires = {},
+-- settings = {"compiler=Visual Studio", "compiler.version=10", "compiler.runtime=MD"}}}
--
-- @return true or false
--
function main(name, opt)
+ -- get configs
+ opt = opt or {}
+ local configs = opt.configs or {}
+
-- find conan
local conan = find_tool("conan")
if not conan then
@@ -155,15 +147,15 @@ function main(name, opt)
_conan_install_xmake_generator(conan)
-- generate conanfile.txt
- _conan_generate_conanfile(name, opt)
+ _conan_generate_conanfile(name, configs)
-- install package
local argv = {"install", "."}
- if opt.build then
- if opt.build == "all" then
+ if configs.build then
+ if configs.build == "all" then
table.insert(argv, "--build")
else
- table.insert(argv, "--build=" .. opt.build)
+ table.insert(argv, "--build=" .. configs.build)
end
end
@@ -241,15 +233,15 @@ function main(name, opt)
end
-- set custom settings
- for _, setting in ipairs(opt.settings) do
+ for _, setting in ipairs(configs.settings) do
table.insert(argv, "-s")
table.insert(argv, setting)
end
-- set remote
- if opt.remote then
+ if configs.remote then
table.insert(argv, "-r")
- table.insert(argv, opt.remote)
+ table.insert(argv, configs.remote)
end
-- TODO set environments
diff --git a/xmake/modules/package/manager/conda/find_package.lua b/xmake/modules/package/manager/conda/find_package.lua
index 5d2634d63..1e09072d4 100644
--- a/xmake/modules/package/manager/conda/find_package.lua
+++ b/xmake/modules/package/manager/conda/find_package.lua
@@ -52,7 +52,7 @@ end
-- find package using the conda package manager
--
-- @param name the package name
--- @param opt the options, e.g. {verbose = true, version = "1.12.0")
+-- @param opt the options, e.g. {verbose = true, require_version = "1.12.0")
--
function main(name, opt)
@@ -124,7 +124,7 @@ function main(name, opt)
result.linkdirs = result.linkdirs or {}
result.libfiles = result.libfiles or {}
table.insert(result.linkdirs, path.join(packagedir, path.directory(line)))
- table.insert(result.links, target.linkname(path.filename(line)))
+ table.insert(result.links, target.linkname(path.filename(line), {plat = opt.plat}))
table.insert(result.libfiles, path.join(packagedir, path.directory(line), path.filename(line)))
end
diff --git a/xmake/modules/package/manager/dub/find_package.lua b/xmake/modules/package/manager/dub/find_package.lua
index 55ad2d6ef..5d49d695e 100644
--- a/xmake/modules/package/manager/dub/find_package.lua
+++ b/xmake/modules/package/manager/dub/find_package.lua
@@ -30,7 +30,7 @@ import("lib.detect.find_file")
-- find package using the dub package manager
--
-- @param name the package name
--- @param opt the options, e.g. {verbose = true, version = "1.12.x")
+-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x")
--
function main(name, opt)
@@ -67,7 +67,7 @@ function main(name, opt)
if pkgdir then
local links = {}
for _, libraryfile in ipairs(os.files(path.join(pkgdir, libpattern))) do
- table.insert(links, target.linkname(path.filename(libraryfile)))
+ table.insert(links, target.linkname(path.filename(libraryfile), {plat = opt.plat}))
end
local includedirs = {}
local dubjson = path.join(pkgdir, "dub.json")
diff --git a/xmake/modules/package/manager/dub/install_package.lua b/xmake/modules/package/manager/dub/install_package.lua
index 84406af5f..d459bfd92 100644
--- a/xmake/modules/package/manager/dub/install_package.lua
+++ b/xmake/modules/package/manager/dub/install_package.lua
@@ -26,7 +26,7 @@ import("lib.detect.find_tool")
-- install package
--
-- @param name the package name, e.g. dub::log
--- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x", buildhash = "xxxxxx"}
+-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"}
--
-- @return true or false
--
diff --git a/xmake/modules/package/manager/find_package.lua b/xmake/modules/package/manager/find_package.lua
index 41c110796..7d82043b2 100644
--- a/xmake/modules/package/manager/find_package.lua
+++ b/xmake/modules/package/manager/find_package.lua
@@ -174,7 +174,7 @@ function main(name, opt)
opt.mode = opt.mode or config.mode() or "release"
-- get package manager name
- local manager_name, package_name = unpack(name:split("::", {plain = true, strict = true}))
+ local manager_name, package_name = table.unpack(name:split("::", {plain = true, strict = true}))
if package_name == nil then
package_name = manager_name
manager_name = nil
@@ -184,7 +184,7 @@ function main(name, opt)
-- get package name and require version
local require_version = nil
- package_name, require_version = unpack(package_name:trim():split("%s"))
+ package_name, require_version = table.unpack(package_name:trim():split("%s"))
opt.require_version = require_version or opt.require_version
-- find package
diff --git a/xmake/modules/package/manager/install_package.lua b/xmake/modules/package/manager/install_package.lua
index 1c5d5ab07..05e13ed27 100644
--- a/xmake/modules/package/manager/install_package.lua
+++ b/xmake/modules/package/manager/install_package.lua
@@ -93,7 +93,7 @@ function main(name, opt)
opt.mode = opt.mode or config.mode() or "release"
-- get package manager name
- local manager_name, package_name = unpack(name:split("::", {plain = true, strict = true}))
+ local manager_name, package_name = table.unpack(name:split("::", {plain = true, strict = true}))
if package_name == nil then
package_name = manager_name
manager_name = nil
@@ -103,7 +103,7 @@ function main(name, opt)
-- get package name and require version
local require_version = nil
- package_name, require_version = unpack(package_name:trim():split("%s"))
+ package_name, require_version = table.unpack(package_name:trim():split("%s"))
opt.require_version = require_version or opt.require_version
-- do install package
diff --git a/xmake/modules/package/manager/nimble/find_package.lua b/xmake/modules/package/manager/nimble/find_package.lua
new file mode 100644
index 000000000..c39d6ed34
--- /dev/null
+++ b/xmake/modules/package/manager/nimble/find_package.lua
@@ -0,0 +1,67 @@
+--!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 find_package.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.base.semver")
+import("core.project.config")
+import("core.project.target")
+import("lib.detect.find_tool")
+import("lib.detect.find_file")
+
+-- find package using the nimble package manager
+--
+-- @param name the package name
+-- @param opt the options, e.g. {verbose = true, require_version = "1.12.x")
+--
+function main(name, opt)
+
+ -- find nimble
+ local nimble = find_tool("nimble")
+ if not nimble then
+ raise("nimble not found!")
+ end
+
+ -- find it from all installed package list
+ local result
+ local list = os.iorunv(nimble.program, {"list", "-i"})
+ for _, line in ipairs(list:split("\n", {plain = true})) do
+ local splitinfo = line:split("%s+")
+ local package_name = splitinfo[1]
+ local package_version = splitinfo[2]
+ if package_name == name and package_version then
+ if package_version then
+ package_version = package_version:match("%[(.+)%]")
+ end
+ if opt.require_version then
+ if package_version and (opt.require_version == "latest" or semver.match(package_version, 1, opt.require_version)) then
+ result = {version = package_version}
+ break
+ end
+ else
+ result = {}
+ break
+ end
+ end
+ end
+ -- @note we need not return links and includedirs information,
+ -- because it's nim source code package and nim will find them automatically
+ return result
+end
diff --git a/xmake/modules/package/manager/nimble/install_package.lua b/xmake/modules/package/manager/nimble/install_package.lua
new file mode 100644
index 000000000..326758e8c
--- /dev/null
+++ b/xmake/modules/package/manager/nimble/install_package.lua
@@ -0,0 +1,58 @@
+--!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 install_package.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.config")
+import("lib.detect.find_tool")
+
+-- install package
+--
+-- e.g.
+-- add_requires("nimble::zip")
+-- add_requires("nimble::zip >0.3")
+-- add_requires("nimble::zip 0.3.1")
+--
+-- @param name the package name, e.g. nimble::zip
+-- @param opt the options, e.g. { verbose = true, mode = "release", plat = , arch = , require_version = "x.x.x"}
+--
+-- @return true or false
+--
+function main(name, opt)
+
+ -- find nimble
+ local nimble = find_tool("nimble")
+ if not nimble then
+ raise("nimble not found!")
+ end
+
+ -- install the given package
+ local argv = {"install", "-y"}
+ if option.get("verbose") then
+ table.insert(argv, "--verbose")
+ end
+ local require_str = name
+ if opt.require_version and opt.require_version ~= "latest" and opt.require_version ~= "master" then
+ name = name .. "@"
+ name = name .. opt.require_version
+ end
+ table.insert(argv, name)
+ os.vrunv(nimble.program, argv)
+end
diff --git a/xmake/modules/package/manager/pacman/find_package.lua b/xmake/modules/package/manager/pacman/find_package.lua
index 4b2be0403..c47edaad6 100644
--- a/xmake/modules/package/manager/pacman/find_package.lua
+++ b/xmake/modules/package/manager/pacman/find_package.lua
@@ -20,9 +20,74 @@
-- imports
import("core.base.option")
+import("core.project.target")
import("lib.detect.find_tool")
import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"})
+-- get result from list of file inside pacman package
+function _find_package_from_list(list, name, pacman, opt)
+
+ -- mingw + pacman = cygpath available
+ local cygpath = nil
+ if is_subhost("msys") and opt.plat == "mingw" then
+ cygpath = find_tool("cygpath")
+ if not cygpath then
+ return
+ end
+ end
+
+ -- iterate over each file path inside the pacman package
+ local result = {includedirs = {}, linkdirs = {}, links = {}}
+ for _, line in ipairs(list:split('\n', {plain = true})) do -- on msys cygpath should be used to convert local path to windows path
+ line = line:trim():split('%s+')[2]
+ if line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then
+ local hpath = line
+ if is_subhost("msys") and opt.plat == "mingw" then
+ hpath = os.iorunv(cygpath.program, {"--windows", line})
+
+ if opt.arch == "x86_64" then
+ local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw64/include"})
+ table.insert(result.includedirs, basehpath)
+ else
+ local basehpath = os.iorunv(cygpath.program, {"--windows", "/mingw32/include"})
+ table.insert(result.includedirs, basehpath)
+ end
+ end
+ table.insert(result.includedirs, path.directory(hpath))
+ -- remove lib and .a, .dll.a and .so to have the links
+ elseif line:endswith(".dll.a") then -- only for mingw
+ local apath = os.iorunv(cygpath.program, {"--windows", line})
+ apath = apath:trim()
+ table.insert(result.linkdirs, path.directory(apath))
+ table.insert(result.links, target.linkname(path.filename(apath), {plat = opt.plat}))
+ elseif line:endswith(".so") then
+ table.insert(result.linkdirs, path.directory(line))
+ table.insert(result.links, target.linkname(path.filename(line), {plat = opt.plat}))
+ elseif line:endswith(".a") then
+ local apath = line
+ if is_subhost("msys") and opt.plat == "mingw" then
+ apath = os.iorunv(cygpath.program, {"--windows", line})
+ apath = apath:trim()
+ end
+ table.insert(result.linkdirs, path.directory(apath))
+ table.insert(result.links, target.linkname(path.filename(apath), {plat = opt.plat}))
+ end
+ end
+ result.includedirs = table.unique(result.includedirs)
+ result.linkdirs = table.unique(result.linkdirs)
+ result.links = table.reverse_unique(result.links)
+
+ -- use pacman package version as version
+ local version = try { function() return os.iorunv(pacman.program, {"-Q", name}) end }
+ if version then
+ version = version:trim():split('%s+')[2]
+ result.version = version:split('-')[1]
+ else
+ result = nil
+ end
+ return result
+end
+
-- find package from the system directories
--
-- @param name the package name
@@ -30,17 +95,15 @@ import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkg
--
function main(name, opt)
- -- init options
- opt = opt or {}
-
-- find pacman
+ opt = opt or {}
local pacman = find_tool("pacman")
if not pacman then
return
end
-- for msys2/mingw? mingw-w64-[i686|x86_64]-xxx
- if opt.plat == "mingw" then
+ if is_subhost("msys") and opt.plat == "mingw" then
name = (opt.arch == "x86_64" and "mingw-w64-x86_64-" or "mingw-w64-i686-") .. name
end
@@ -52,41 +115,50 @@ function main(name, opt)
-- parse package files list
local linkdirs = {}
- local has_includes = false
local pkgconfig_files = {}
for _, line in ipairs(list:split('\n', {plain = true})) do
line = line:trim():split('%s+')[2]
if line:find("/pkgconfig/", 1, true) and line:endswith(".pc") then
- pkgconfig_files[path.basename(line)] = line
+ table.insert(pkgconfig_files, line)
end
if line:endswith(".so") or line:endswith(".a") or line:endswith(".lib") then
table.insert(linkdirs, path.directory(line))
- elseif line:find("/include/", 1, true) and (line:endswith(".h") or line:endswith(".hpp")) then
- has_includes = true
end
end
+ linkdirs = table.unique(linkdirs)
- -- get pkgconfig file
- local pkgconfig_file = pkgconfig_files[name]
- if not pkgconfig_file then
- for _, file in pairs(pkgconfig_files) do
- pkgconfig_file = file
- break
- end
- end
-
- -- find package
- local result = nil
- if pkgconfig_file then
+ -- we iterate over each pkgconfig file to extract the required data
+ local foundpc = false
+ local result = {includedirs = {}, linkdirs = {}, links = {}}
+ for _, pkgconfig_file in ipairs(pkgconfig_files) do
local pkgconfig_dir = path.directory(pkgconfig_file)
local pkgconfig_name = path.basename(pkgconfig_file)
- linkdirs = table.unique(linkdirs)
- includedirs = table.unique(includedirs)
- result = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs})
- if not result and has_includes then
- -- header only and hidden /usr/include? we need only return empty {}
- result = {}
+ local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = linkdirs})
+
+ -- the pkgconfig file has been parse successfully
+ if pcresult then
+ for _, includedir in ipairs(pcresult.includedirs) do
+ table.insert(result.includedirs, includedir)
+ end
+ for _, linkdir in ipairs(pcresult.linkdirs) do
+ table.insert(result.linkdirs, linkdir)
+ end
+ for _, link in ipairs(pcresult.links) do
+ table.insert(result.links, link)
+ end
+ -- version should be the same if a pacman package contains multiples .pc
+ result.version = pcresult.version
+ foundpc = true
end
end
+
+ if foundpc == true then
+ result.includedirs = table.unique(result.includedirs)
+ result.linkdirs = table.unique(result.linkdirs)
+ result.links = table.reverse_unique(result.links)
+ else
+ -- if there is no .pc, we parse the package content to obtain the data we want
+ result = _find_package_from_list(list, name, pacman, opt)
+ end
return result
end
diff --git a/xmake/modules/package/manager/pkgconfig/find_package.lua b/xmake/modules/package/manager/pkgconfig/find_package.lua
index a7dbf377a..ddc7efeb4 100644
--- a/xmake/modules/package/manager/pkgconfig/find_package.lua
+++ b/xmake/modules/package/manager/pkgconfig/find_package.lua
@@ -20,7 +20,6 @@
-- imports
import("lib.detect.pkgconfig")
-import("lib.detect.find_library")
import("package.manager.system.find_package", {alias = "find_package_from_system"})
-- find package from the pkg-config package manager
diff --git a/xmake/modules/package/manager/system/find_package.lua b/xmake/modules/package/manager/system/find_package.lua
index 9bb04566d..1e0d58c77 100644
--- a/xmake/modules/package/manager/system/find_package.lua
+++ b/xmake/modules/package/manager/system/find_package.lua
@@ -26,41 +26,13 @@ import("lib.detect.pkgconfig")
import("detect.sdks.find_xcode")
import("core.project.config")
--- find package from the unix-like system directories
-function _find_package_from_unixdirs(name, links, opt)
-
- -- add default search includedirs on pc host
- local includedirs = table.wrap(opt.includedirs)
- if #includedirs == 0 then
- if opt.plat == "linux" or opt.plat == "macosx" then
- table.insert(includedirs, "/usr/local/include")
- table.insert(includedirs, "/usr/include")
- table.insert(includedirs, "/opt/local/include")
- table.insert(includedirs, "/opt/include")
- end
- end
-
- -- add default search linkdirs on pc host
- local linkdirs = table.wrap(opt.linkdirs)
- if #linkdirs == 0 then
- if opt.plat == "linux" or opt.plat == "macosx" then
- table.insert(linkdirs, "/usr/local/lib")
- table.insert(linkdirs, "/usr/lib")
- table.insert(linkdirs, "/opt/local/lib")
- table.insert(linkdirs, "/opt/lib")
- if opt.plat == "linux" and opt.arch == "x86_64" then
- table.insert(linkdirs, "/usr/local/lib/x86_64-linux-gnu")
- table.insert(linkdirs, "/usr/lib/x86_64-linux-gnu")
- table.insert(linkdirs, "/usr/lib64")
- table.insert(linkdirs, "/opt/lib64")
- end
- end
- end
+-- find package
+function _find_package(name, links, linkdirs, includedirs, opt)
-- find library
local result = nil
for _, link in ipairs(links) do
- local libinfo = find_library(link, linkdirs)
+ local libinfo = find_library(link, linkdirs, {plat = opt.plat})
if libinfo then
result = result or {}
result.links = table.join(result.links or {}, libinfo.link)
@@ -91,6 +63,68 @@ function _find_package_from_unixdirs(name, links, opt)
return result
end
+-- find package from the environment variables
+-- @see https://github.com/xmake-io/xmake/issues/1776
+--
+function _find_package_from_envs(name, links, opt)
+
+ -- add default search includedirs on pc host
+ local includedirs = table.wrap(opt.includedirs)
+ if #includedirs == 0 then
+ if opt.plat == "windows" then
+ table.insert(includedirs, "$(env INCLUDE)")
+ else
+ table.insert(includedirs, "$(env CPATH)")
+ table.insert(includedirs, "$(env C_INCLUDE_PATH)")
+ table.insert(includedirs, "$(env CPLUS_INCLUDE_PATH)")
+ end
+ end
+
+ -- add default search linkdirs on pc host
+ local linkdirs = table.wrap(opt.linkdirs)
+ if #linkdirs == 0 then
+ if opt.plat == "windows" then
+ table.insert(linkdirs, "$(env LIB)")
+ else
+ table.insert(linkdirs, "$(env LIBRARY_PATH)")
+ end
+ end
+ return _find_package(name, links, linkdirs, includedirs, opt)
+end
+
+-- find package from the unix-like system directories
+function _find_package_from_unixdirs(name, links, opt)
+
+ -- add default search includedirs on pc host
+ local includedirs = table.wrap(opt.includedirs)
+ if #includedirs == 0 then
+ if opt.plat == "linux" or opt.plat == "macosx" then
+ table.insert(includedirs, "/usr/local/include")
+ table.insert(includedirs, "/usr/include")
+ table.insert(includedirs, "/opt/local/include")
+ table.insert(includedirs, "/opt/include")
+ end
+ end
+
+ -- add default search linkdirs on pc host
+ local linkdirs = table.wrap(opt.linkdirs)
+ if #linkdirs == 0 then
+ if opt.plat == "linux" or opt.plat == "macosx" then
+ table.insert(linkdirs, "/usr/local/lib")
+ table.insert(linkdirs, "/usr/lib")
+ table.insert(linkdirs, "/opt/local/lib")
+ table.insert(linkdirs, "/opt/lib")
+ if opt.plat == "linux" and opt.arch == "x86_64" then
+ table.insert(linkdirs, "/usr/local/lib/x86_64-linux-gnu")
+ table.insert(linkdirs, "/usr/lib/x86_64-linux-gnu")
+ table.insert(linkdirs, "/usr/lib64")
+ table.insert(linkdirs, "/opt/lib64")
+ end
+ end
+ end
+ return _find_package(name, links, linkdirs, includedirs, opt)
+end
+
-- find package from the xcode directories
function _find_package_from_xcodedirs(name, links, opt)
@@ -166,6 +200,7 @@ function main(name, opt)
if opt.plat ~= "windows" then
table.insert(finders, _find_package_from_unixdirs)
end
+ table.insert(finders, _find_package_from_envs)
end
if opt.plat == "macosx" or opt.plat == "iphoneos" or opt.plat == "watchos" then
table.insert(finders, _find_package_from_xcodedirs)
diff --git a/xmake/modules/package/manager/vcpkg/configurations.lua b/xmake/modules/package/manager/vcpkg/configurations.lua
new file mode 100644
index 000000000..9021edff0
--- /dev/null
+++ b/xmake/modules/package/manager/vcpkg/configurations.lua
@@ -0,0 +1,48 @@
+--!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 configurations.lua
+--
+
+-- get architecture for vcpkg
+function arch(arch)
+ local archs = {
+ x86_64 = "x64",
+ i386 = "x86",
+
+ -- android: armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mip64
+ -- Offers a doc: https://github.com/microsoft/vcpkg/blob/master/docs/users/android.md
+ ["armeabi-v7a"] = "arm",
+ ["arm64-v8a"] = "arm64",
+
+ -- ios: arm64 armv7 armv7s i386
+ armv7 = "arm",
+ armv7s = "arm",
+ arm64 = "arm64",
+ }
+ return archs[arch] or arch
+end
+
+-- get configurations
+function main()
+ return {
+ baseline = {description = "set the builtin baseline."},
+ features = {description = "set the features of dependency."},
+ default_features = {description = "enables or disables any defaults provided by the dependency.", default = true}
+ }
+end
+
diff --git a/xmake/modules/package/manager/vcpkg/find_package.lua b/xmake/modules/package/manager/vcpkg/find_package.lua
index e965ace73..e61e56c29 100644
--- a/xmake/modules/package/manager/vcpkg/find_package.lua
+++ b/xmake/modules/package/manager/vcpkg/find_package.lua
@@ -20,29 +20,51 @@
-- imports
import("lib.detect.find_file")
-import("lib.detect.find_library")
import("lib.detect.find_tool")
import("core.base.option")
import("core.project.config")
import("core.project.target")
import("detect.sdks.find_vcpkgdir")
+import("package.manager.vcpkg.configurations")
+import("package.manager.pkgconfig.find_package", {alias = "find_package_from_pkgconfig"})
--- find package from the vcpkg package manager
---
--- @param name the package name, e.g. zlib, pcre
--- @param opt the options, e.g. {verbose = true, version = "1.12.x")
---
-function main(name, opt)
+-- we iterate over each pkgconfig file to extract the required data
+function _find_package_from_pkgconfig(pkgconfig_files, opt)
+ opt = opt or {}
+ local foundpc = false
+ local result = {includedirs = {}, linkdirs = {}, links = {}}
+ for _, pkgconfig_file in ipairs(pkgconfig_files) do
+ local pkgconfig_dir = path.join(opt.installdir, path.directory(pkgconfig_file))
+ local pkgconfig_name = path.basename(pkgconfig_file)
+ local pcresult = find_package_from_pkgconfig(pkgconfig_name, {configdirs = pkgconfig_dir, linkdirs = opt.linkdirs})
- -- attempt to find vcpkg directory
- local vcpkgdir = find_vcpkgdir()
- if not vcpkgdir then
- if option.get("diagnosis") then
- cprint("${color.warning}checkinfo: ${clear dim}vcpkg root directory not found, maybe you need set $VCPKG_ROOT!")
+ -- the pkgconfig file has been parse successfully
+ if pcresult then
+ for _, includedir in ipairs(pcresult.includedirs) do
+ table.insert(result.includedirs, includedir)
+ end
+ for _, linkdir in ipairs(pcresult.linkdirs) do
+ table.insert(result.linkdirs, linkdir)
+ end
+ for _, link in ipairs(pcresult.links) do
+ table.insert(result.links, link)
+ end
+ -- version should be the same if a pacman package contains multiples .pc
+ result.version = pcresult.version
+ foundpc = true
end
- return
end
+ if foundpc == true then
+ result.includedirs = table.unique(result.includedirs)
+ result.linkdirs = table.unique(result.linkdirs)
+ result.links = table.reverse_unique(result.links)
+ return result
+ end
+end
+
+function _find_package(vcpkgdir, name, opt)
+
-- fix name, e.g. ffmpeg[x264] as ffmpeg
-- @see https://github.com/xmake-io/xmake/issues/925
name = name:gsub("%[.-%]", "")
@@ -51,50 +73,36 @@ function main(name, opt)
local arch = opt.arch
local plat = opt.plat
local mode = opt.mode
-
- -- mapping plat
if plat == "macosx" then
plat = "osx"
end
+ arch = configurations.arch(arch)
- -- archs mapping for vcpkg
- local archs = {
- x86_64 = "x64",
- i386 = "x86",
-
- -- android: armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mip64
- -- Offers a doc: https://github.com/microsoft/vcpkg/blob/master/docs/users/android.md
- ["armeabi-v7a"] = "arm",
- ["arm64-v8a"] = "arm64",
-
- -- ios: arm64 armv7 armv7s i386
- armv7 = "arm",
- armv7s = "arm",
- arm64 = "arm64",
+ -- get the vcpkg info directories
+ local infodirs = {
+ path.join(opt.installdir, "vcpkg_installed", "vcpkg", "info"),
+ path.join(vcpkgdir, "installed", "vcpkg", "info")
}
- -- mapping arch
- arch = archs[arch] or arch
-
- -- get the vcpkg installed directory
- local installdir = path.join(vcpkgdir, "installed")
-
- -- get the vcpkg info directory
- local infodir = path.join(installdir, "vcpkg", "info")
-- find the package info file, e.g. zlib_1.2.11-3_x86-windows[-static].list
local triplet = arch .. "-" .. plat
- local pkgconfigs = opt.pkgconfigs
- if plat == "windows" and pkgconfigs and pkgconfigs.shared ~= true then
+ local configs = opt.configs or {}
+ if plat == "windows" and configs.shared ~= true then
triplet = triplet .. "-static"
- if pkgconfigs.vs_runtime and pkgconfigs.vs_runtime:startswith("MD") then
+ if configs.vs_runtime and configs.vs_runtime:startswith("MD") then
triplet = triplet .. "-md"
end
end
- local infofile = find_file(format("%s_*_%s.list", name, triplet), infodir)
+ local infofile = find_file(format("%s_*_%s.list", name, triplet), infodirs)
+ if not infofile then
+ return
+ end
+ local installdir = path.directory(path.directory(path.directory(infofile)))
-- save includedirs, linkdirs and links
local result = nil
- local info = infofile and io.readfile(infofile) or nil
+ local pkgconfig_files = {}
+ local info = io.readfile(infofile)
if info then
for _, line in ipairs(info:split('\n')) do
line = line:trim()
@@ -102,6 +110,11 @@ function main(name, opt)
line = line:lower()
end
+ -- get pkgconfig files
+ if line:find(triplet .. (mode == "debug" and "/debug" or "") .. "/lib/pkgconfig/", 1, true) and line:endswith(".pc") then
+ table.insert(pkgconfig_files, line)
+ end
+
-- get includedirs
if line:endswith("/include/") then
result = result or {}
@@ -110,14 +123,14 @@ function main(name, opt)
end
-- get linkdirs and links
- if (plat == "windows" and line:endswith(".lib")) or line:endswith(".a") then
+ if (plat == "windows" and line:endswith(".lib")) or line:endswith(".a") or line:endswith(".so") then
if line:find(triplet .. (mode == "debug" and "/debug" or "") .. "/lib/", 1, true) then
result = result or {}
result.links = result.links or {}
result.linkdirs = result.linkdirs or {}
result.libfiles = result.libfiles or {}
table.insert(result.linkdirs, path.join(installdir, path.directory(line)))
- table.insert(result.links, target.linkname(path.filename(line)))
+ table.insert(result.links, target.linkname(path.filename(line), {plat = plat}))
table.insert(result.libfiles, path.join(installdir, path.directory(line), path.filename(line)))
end
end
@@ -135,8 +148,16 @@ function main(name, opt)
end
end
+ -- find result from pkgconfig first
+ if #pkgconfig_files > 0 then
+ local pkgconfig_result = _find_package_from_pkgconfig(pkgconfig_files, {installdir = installdir, linkdirs = result and result.linkdirs})
+ if pkgconfig_result then
+ result = pkgconfig_result
+ end
+ end
+
-- save version
- if result and infofile then
+ if result then
local infoname = path.basename(infofile)
result.version = infoname:match(name .. "_(%d+%.?%d*%.?%d*.-)_" .. arch)
if not result.version then
@@ -156,3 +177,22 @@ function main(name, opt)
return result
end
+-- find package from the vcpkg package manager
+--
+-- @param name the package name, e.g. zlib, pcre
+-- @param opt the options, e.g. {verbose = true)
+--
+function main(name, opt)
+
+ -- attempt to find vcpkg directory
+ local vcpkgdir = find_vcpkgdir()
+ if not vcpkgdir then
+ if option.get("diagnosis") then
+ cprint("${color.warning}checkinfo: ${clear dim}vcpkg root directory not found, maybe you need set $VCPKG_ROOT!")
+ end
+ return
+ end
+
+ -- do find package
+ return _find_package(vcpkgdir, name, opt)
+end
diff --git a/xmake/modules/package/manager/vcpkg/install_package.lua b/xmake/modules/package/manager/vcpkg/install_package.lua
index eaf28710e..962c72f83 100644
--- a/xmake/modules/package/manager/vcpkg/install_package.lua
+++ b/xmake/modules/package/manager/vcpkg/install_package.lua
@@ -20,52 +20,67 @@
-- imports
import("core.base.option")
+import("core.base.json")
+import("core.base.semver")
import("lib.detect.find_tool")
+import("package.manager.vcpkg.configurations")
--- install package
---
--- @param name the package name, e.g. pcre2, pcre2/libpcre2-8
--- @param opt the options, e.g. {verbose = true}
---
--- @return true or false
---
-function main(name, opt)
-
- -- attempt to find vcpkg
- local vcpkg = find_tool("vcpkg")
- if not vcpkg then
- raise("vcpkg not found!")
+-- need manifest mode?
+function _need_manifest(opt)
+ local require_version = opt.require_version
+ if require_version ~= nil and require_version ~= "latest" then
+ return true
+ end
+ local configs = opt.configs
+ if configs and (configs.features or configs.default_features == false or configs.baseline) then
+ return true
end
+end
+
+-- install for classic mode
+function _install_for_classic(vcpkg, name, opt)
-- get arch, plat and mode
local arch = opt.arch
local plat = opt.plat
local mode = opt.mode
-
- -- mapping plat
if plat == "macosx" then
plat = "osx"
end
+ arch = configurations.arch(arch)
- -- archs mapping for vcpkg
- local archs = {
- x86_64 = "x64",
- i386 = "x86",
+ -- init triplet
+ local triplet = arch .. "-" .. plat
+ if opt.plat == "windows" and opt.shared ~= true then
+ triplet = triplet .. "-static"
+ if opt.vs_runtime and opt.vs_runtime:startswith("MD") then
+ triplet = triplet .. "-md"
+ end
+ end
- -- android: armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mip64
- -- Offers a doc: https://github.com/microsoft/vcpkg/blob/master/docs/users/android.md
- ["armeabi-v7a"] = "arm",
- ["arm64-v8a"] = "arm64",
+ -- init argv
+ local argv = {"install", name .. ":" .. triplet}
+ if option.get("diagnosis") then
+ table.insert(argv, "--debug")
+ end
+
+ -- install package
+ os.vrunv(vcpkg, argv)
+end
- -- ios: arm64 armv7 armv7s i386
- armv7 = "arm",
- armv7s = "arm",
- arm64 = "arm64",
- }
- -- mapping arch
- arch = archs[arch] or arch
+-- install for manifest mode
+function _install_for_manifest(vcpkg, name, opt)
+
+ -- get configs
+ local configs = opt.configs or {}
-- init triplet
+ local arch = opt.arch
+ local plat = opt.plat
+ if plat == "macosx" then
+ plat = "osx"
+ end
+ arch = configurations.arch(arch)
local triplet = arch .. "-" .. plat
if opt.plat == "windows" and opt.shared ~= true then
triplet = triplet .. "-static"
@@ -75,11 +90,83 @@ function main(name, opt)
end
-- init argv
- local argv = {"install", name .. ":" .. triplet}
+ local argv = {"--feature-flags=\"versions\"", "install", "--x-wait-for-lock", "--triplet", triplet}
if option.get("diagnosis") then
table.insert(argv, "--debug")
end
+ -- generate platform
+ local platform = plat .. " & " .. arch
+
+ -- generate dependencies
+ local require_version = opt.require_version
+ if require_version == "latest" then
+ require_version = nil
+ end
+ -- 1.2.11+13 -> 1.2.11#13
+ if require_version then
+ require_version = require_version:gsub("%+", "#")
+ end
+ local minversion = require_version
+ if minversion and minversion:startswith(">=") then
+ minversion = minversion:sub(3)
+ end
+ local dependencies = {}
+ table.insert(dependencies, {
+ name = name,
+ ["version>="] = minversion,
+ platform = platform,
+ features = configs.features,
+ ["default-features"] = configs.default_features})
+
+ -- generate overrides to use fixed version
+ local overrides
+ if require_version and semver.is_valid(require_version) then
+ overrides = {{name = name, version = require_version}}
+ end
+
+ -- generate manifest
+ local baseline = configs.baseline or "44d94c2edbd44f0c01d66c2ad95eb6982a9a61bc" -- 2021.04.30
+ local manifest = {
+ name = "stub",
+ version = "1.0",
+ dependencies = dependencies,
+ ["builtin-baseline"] = baseline,
+ overrides = overrides}
+ local installdir = assert(opt.installdir, "installdir not found!")
+ json.savefile(path.join(installdir, "vcpkg.json"), manifest)
+ if not os.isdir(installdir) then
+ os.mkdir(installdir)
+ end
+ if option.get("diagnosis") then
+ vprint(path.join(installdir, "vcpkg.json"))
+ vprint(manifest)
+ end
+
-- install package
- os.vrunv(vcpkg.program, argv)
+ os.vrunv(vcpkg, argv, {curdir = installdir})
+end
+
+-- install package
+--
+-- @param name the package name, e.g. pcre2, pcre2/libpcre2-8
+-- @param opt the options, e.g. {verbose = true}
+--
+-- @return true or false
+--
+function main(name, opt)
+
+ -- attempt to find vcpkg
+ local vcpkg = find_tool("vcpkg")
+ if not vcpkg then
+ raise("vcpkg not found!")
+ end
+
+ -- do install
+ opt = opt or {}
+ if _need_manifest(opt) then
+ _install_for_manifest(vcpkg.program, name, opt)
+ else
+ _install_for_classic(vcpkg.program, name, opt)
+ end
end
diff --git a/xmake/modules/package/manager/xmake/find_package.lua b/xmake/modules/package/manager/xmake/find_package.lua
index dab32de33..503d1beda 100644
--- a/xmake/modules/package/manager/xmake/find_package.lua
+++ b/xmake/modules/package/manager/xmake/find_package.lua
@@ -38,7 +38,11 @@ function _find_package_from_repo(name, opt)
-- find the manifest file of package, e.g. ~/.xmake/packages/z/zlib/1.1.12/ed41d5327fad3fc06fe376b4a94f62ef/manifest.txt
local packagedirs = {}
- table.insert(packagedirs, path.join(package.installdir(), name:lower():sub(1, 1), name:lower(), opt.require_version, opt.buildhash))
+ if opt.installdir then
+ table.insert(packagedirs, opt.installdir)
+ else
+ table.insert(packagedirs, path.join(package.installdir(), name:lower():sub(1, 1), name:lower(), opt.require_version, opt.buildhash))
+ end
local manifest_file = find_file("manifest.txt", packagedirs)
if not manifest_file then
return
@@ -73,39 +77,35 @@ function _find_package_from_repo(name, opt)
local links = {}
local linkdirs = {}
local libfiles = {}
- for _, linkdir in ipairs(vars.linkdirs) do
- table.insert(linkdirs, path.join(installdir, linkdir))
- end
if vars.links then
table.join2(links, vars.links)
- end
- if not vars.linkdirs or not vars.links then
+ else
+ -- we scan links automatically
local found = false
- for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do
- if file:endswith(".lib") or file:endswith(".a") then
- found = true
- if not vars.linkdirs then
- table.insert(linkdirs, path.directory(file))
- end
- if not vars.links then
- table.insert(links, target.linkname(path.filename(file)))
+ for _, libdir in ipairs(vars.linkdirs or "lib") do
+ for _, file in ipairs(os.files(path.join(installdir, libdir, "*"))) do
+ if file:endswith(".lib") or file:endswith(".a") then
+ found = true
+ table.insert(links, target.linkname(path.filename(file), {plat = opt.plat}))
+ table.insert(libfiles, file)
end
end
- end
- if not found then
- for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do
- if file:endswith(".so") or file:endswith(".dylib") then
- if not vars.linkdirs then
- table.insert(linkdirs, path.directory(file))
- end
- if not vars.links then
- table.insert(links, target.linkname(path.filename(file)))
+ if not found then
+ for _, file in ipairs(os.files(path.join(installdir, "lib", "*"))) do
+ if file:endswith(".so") or file:match(".+%.so%..+$") or file:endswith(".dylib") then -- maybe symlink to libxxx.so.1
+ table.insert(links, target.linkname(path.filename(file), {plat = opt.plat}))
+ table.insert(libfiles, file)
end
end
end
end
end
- if opt.plat == "windows" then
+ if #links > 0 then
+ for _, libdir in ipairs(vars.linkdirs or "lib") do
+ table.insert(linkdirs, path.join(installdir, libdir))
+ end
+ end
+ if opt.plat == "windows" or opt.plat == "mingw" then
for _, file in ipairs(os.files(path.join(installdir, "lib", "*.dll"))) do
result.shared = true
table.insert(libfiles, file)
@@ -128,7 +128,7 @@ function _find_package_from_repo(name, opt)
-- find library
for _, link in ipairs(links) do
- local libinfo = find_library(link, linkdirs)
+ local libinfo = find_library(link, linkdirs, {plat = opt.plat})
if libinfo then
if libinfo.kind == "shared" then
result.shared = true
@@ -145,7 +145,7 @@ function _find_package_from_repo(name, opt)
result.links = table.unique(result.links)
end
if result.libfiles then
- result.libfiles = table.join(result.libfiles, libfiles)
+ result.libfiles = table.unique(table.join(result.libfiles, libfiles))
end
-- inherit the other prefix variables
@@ -245,7 +245,7 @@ function _find_package_from_packagedirs(name, opt)
-- find library
local result = nil
for _, link in ipairs(packageinfo:get("links")) do
- local libinfo = find_library(link, linkdirs)
+ local libinfo = find_library(link, linkdirs, {plat = opt.plat})
if libinfo then
result = result or {}
result.links = table.join(result.links or {}, libinfo.link)
diff --git a/xmake/modules/package/manager/xmake/search_package.lua b/xmake/modules/package/manager/xmake/search_package.lua
index 5b633852c..f4a235246 100644
--- a/xmake/modules/package/manager/xmake/search_package.lua
+++ b/xmake/modules/package/manager/xmake/search_package.lua
@@ -19,6 +19,7 @@
--
-- imports
+import("core.base.semver")
import("core.package.package", {alias = "core_package"})
import("private.action.require.impl.repository")
@@ -33,6 +34,10 @@ function main(name)
if package then
local repo = package:repo()
local versions = package:versions()
+ if versions then
+ versions = table.copy(versions)
+ table.sort(versions, function (a, b) return semver.compare(a, b) > 0 end)
+ end
table.insert(results, {name = package:name(), version = versions and versions[1], description = package:get("description"), reponame = repo and repo:name()})
end
end
diff --git a/xmake/modules/package/tools/autoconf.lua b/xmake/modules/package/tools/autoconf.lua
index 209e6c68a..12b94d64f 100644
--- a/xmake/modules/package/tools/autoconf.lua
+++ b/xmake/modules/package/tools/autoconf.lua
@@ -23,13 +23,22 @@ import("core.base.option")
import("core.project.config")
import("core.tool.linker")
import("core.tool.compiler")
+import("lib.detect.find_tool")
--- translate path
-function _translate_path(package, p)
- if p and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then
- p = p:gsub("\\", "/")
+-- translate paths
+function _translate_paths(package, paths)
+ if paths and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then
+ if type(paths) == "string" then
+ return (paths:gsub("\\", "/"))
+ elseif type(paths) == "table" then
+ local result = {}
+ for _, p in ipairs(paths) do
+ table.insert(result, (p:gsub("\\", "/")))
+ end
+ return result
+ end
end
- return p
+ return paths
end
-- translate windows bin path
@@ -56,7 +65,7 @@ function _get_configs(package, configs)
-- add prefix
local configs = configs or {}
- table.insert(configs, "--prefix=" .. _translate_path(package, package:installdir()))
+ table.insert(configs, "--prefix=" .. _translate_paths(package, package:installdir()))
-- add host for cross-complation
if not configs.host and not package:is_plat(os.subhost()) then
@@ -108,10 +117,45 @@ function _get_configs(package, configs)
return configs
end
+-- get cflags from package deps
+function _get_cflags_from_packagedeps(package, opt)
+ local result = {}
+ for _, depname in ipairs(opt.packagedeps) do
+ local dep = package:dep(depname)
+ if dep then
+ local fetchinfo = dep:fetch({external = false})
+ if fetchinfo then
+ table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines))
+ table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs)))
+ table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs)))
+ end
+ end
+ end
+ return result
+end
+
+-- get ldflags from package deps
+function _get_ldflags_from_packagedeps(package, opt)
+ local result = {}
+ for _, depname in ipairs(opt.packagedeps) do
+ local dep = package:dep(depname)
+ if dep then
+ local fetchinfo = dep:fetch({external = false})
+ if fetchinfo then
+ table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs)))
+ table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links))
+ table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks)))
+ end
+ end
+ end
+ return result
+end
+
-- get the build environments
function buildenvs(package, opt)
opt = opt or {}
local envs = {}
+ local cppflags = {}
if package:is_plat(os.subhost()) then
local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags"))
local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags"))
@@ -127,10 +171,16 @@ function buildenvs(package, opt)
table.join2(cflags, opt.cxflags)
table.join2(cxxflags, opt.cxxflags)
table.join2(cxxflags, opt.cxflags)
+ table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688
table.join2(asflags, opt.asflags)
table.join2(ldflags, opt.ldflags)
+ table.join2(cflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cppflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt))
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
+ envs.CPPFLAGS = table.concat(cppflags, ' ')
envs.ASFLAGS = table.concat(asflags, ' ')
envs.LDFLAGS = table.concat(ldflags, ' ')
else
@@ -150,9 +200,14 @@ function buildenvs(package, opt)
table.join2(cflags, opt.cxflags)
table.join2(cxxflags, opt.cxxflags)
table.join2(cxxflags, opt.cxflags)
+ table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688
table.join2(asflags, opt.asflags)
table.join2(ldflags, opt.ldflags)
table.join2(shflags, opt.shflags)
+ table.join2(cflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cppflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt))
table.join2(cflags, _map_compflags(package, "c", "define", defines))
table.join2(cflags, _map_compflags(package, "c", "includedir", includedirs))
table.join2(cflags, _map_compflags(package, "c", "sysincludedir", sysincludedirs))
@@ -177,6 +232,7 @@ function buildenvs(package, opt)
envs.RANLIB = package:build_getenv("ranlib")
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
+ envs.CPPFLAGS = table.concat(cppflags, ' ')
envs.ASFLAGS = table.concat(asflags, ' ')
envs.ARFLAGS = table.concat(arflags, ' ')
envs.LDFLAGS = table.concat(ldflags, ' ')
@@ -291,25 +347,75 @@ function configure(package, configs, opt)
os.vrunv("sh", argv, {envs = envs})
end
--- install package
-function install(package, configs, opt)
+-- do make
+function make(package, argv, opt)
+ opt = opt or {}
+ local program
+ if package:is_plat("mingw") and is_subhost("windows") then
+ local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!")
+ program = path.join(mingw, "bin", "mingw32-make.exe")
+ else
+ local tool = find_tool("make")
+ if tool then
+ program = tool.program
+ end
+ end
+ assert(program, "make not found!")
+ os.vrunv(program, argv)
+end
+
+-- build package
+function build(package, configs, opt)
-- do configure
configure(package, configs, opt)
-- do make and install
opt = opt or {}
- local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2))
+ local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob())
local argv = {"-j" .. njob}
if option.get("verbose") then
table.insert(argv, "V=1")
end
- if is_host("bsd") then
- os.vrunv("gmake", argv)
- os.vrun("gmake install")
- else
- os.vrunv("make", argv)
- os.vrun("make install")
+ if opt.makeconfigs then
+ for name, value in pairs(opt.makeconfigs) do
+ value = tostring(value):trim()
+ if value ~= "" then
+ if type(name) == "number" then
+ table.insert(argv, value)
+ else
+ table.insert(argv, name .. "=" .. value)
+ end
+ end
+ end
+ end
+ make(package, argv, opt)
+end
+
+-- install package
+function install(package, configs, opt)
+
+ -- do build
+ opt = opt or {}
+ build(package, configs, opt)
+
+ -- do install
+ local argv = {"install"}
+ if option.get("verbose") then
+ table.insert(argv, "V=1")
+ end
+ if opt.makeconfigs then
+ for name, value in pairs(opt.makeconfigs) do
+ value = tostring(value):trim()
+ if value ~= "" then
+ if type(name) == "number" then
+ table.insert(argv, value)
+ else
+ table.insert(argv, name .. "=" .. value)
+ end
+ end
+ end
end
+ make(package, argv, opt)
end
diff --git a/xmake/modules/package/tools/cmake.lua b/xmake/modules/package/tools/cmake.lua
index 3e48fee40..f49cedf0b 100644
--- a/xmake/modules/package/tools/cmake.lua
+++ b/xmake/modules/package/tools/cmake.lua
@@ -30,7 +30,7 @@ import("package.tools.ninja")
-- get the number of parallel jobs
function _get_parallel_njobs(opt)
- return opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2))
+ return opt.jobs or option.get("jobs") or tostring(os.default_njob())
end
-- translate paths
@@ -272,10 +272,13 @@ function _get_configs_for_windows(package, configs, opt)
table.insert(configs, "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL")
end
if vs_runtime then
- table.insert(configs, '-DCMAKE_CXX_FLAGS_DEBUG="/' .. vs_runtime .. '"')
- table.insert(configs, '-DCMAKE_CXX_FLAGS_RELEASE="/' .. vs_runtime .. '"')
- table.insert(configs, '-DCMAKE_C_FLAGS_DEBUG="/' .. vs_runtime .. '"')
- table.insert(configs, '-DCMAKE_C_FLAGS_RELEASE="/' .. vs_runtime .. '"')
+ -- CMake default MSVC flags as of 3.21.2
+ local default_debug_flags = "/Zi /Ob0 /Od /RTC1"
+ local default_release_flags = "/O2 /Ob2 /DNDEBUG"
+ table.insert(configs, '-DCMAKE_CXX_FLAGS_DEBUG=/' .. vs_runtime .. ' ' .. default_debug_flags)
+ table.insert(configs, '-DCMAKE_CXX_FLAGS_RELEASE=/' .. vs_runtime .. ' ' .. default_release_flags)
+ table.insert(configs, '-DCMAKE_C_FLAGS_DEBUG=/' .. vs_runtime .. ' ' .. default_debug_flags)
+ table.insert(configs, '-DCMAKE_C_FLAGS_RELEASE=/' .. vs_runtime .. ' ' .. default_release_flags)
end
_get_configs_for_generic(package, configs, opt)
end
@@ -296,6 +299,12 @@ function _get_configs_for_android(package, configs, opt)
if ndk_cxxstl then
table.insert(configs, "-DANDROID_STL=" .. ndk_cxxstl)
end
+ if is_host("windows") then
+ local make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe")
+ if os.isfile(make) then
+ table.insert(configs, "-DCMAKE_MAKE_PROGRAM=" .. make)
+ end
+ end
end
_get_configs_for_generic(package, configs, opt)
end
@@ -363,6 +372,16 @@ function _get_configs_for_mingw(package, configs, opt)
envs.CMAKE_OSX_SYSROOT = ""
-- Avoid cmake to add the flags -search_paths_first and -headerpad_max_install_names on macOS
envs.HAVE_FLAG_SEARCH_PATHS_FIRST = "0"
+ -- CMAKE_MAKE_PROGRAM may be required for some CMakeLists.txt (libcurl)
+ if is_subhost("windows") then
+ local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!")
+ envs.CMAKE_MAKE_PROGRAM = path.join(mingw, "bin", "mingw32-make.exe")
+ end
+
+ if opt.cmake_generator == "Ninja" then
+ envs.CMAKE_MAKE_PROGRAM = "ninja"
+ end
+
for k, v in pairs(envs) do
table.insert(configs, "-D" .. k .. "=" .. v)
end
@@ -535,8 +554,12 @@ end
-- do build for make
function _build_for_make(package, configs, opt)
+ local argv = {}
+ if opt.target then
+ table.insert(argv, opt.target)
+ end
local jobs = _get_parallel_njobs(opt)
- local argv = {"-j" .. jobs}
+ table.insert(argv, "-j" .. jobs)
if option.get("verbose") then
table.insert(argv, "VERBOSE=1")
end
@@ -546,6 +569,16 @@ function _build_for_make(package, configs, opt)
local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!")
local mingw_make = path.join(mingw, "bin", "mingw32-make.exe")
os.vrunv(mingw_make, argv)
+ elseif package:is_plat("android") and is_host("windows") then
+ local make
+ local ndk = get_config("ndk")
+ if ndk then
+ make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe")
+ end
+ if not make or not os.isfile(make) then
+ make = "make"
+ end
+ os.vrunv(make, argv)
else
os.vrunv("make", argv)
end
@@ -602,6 +635,17 @@ function _install_for_make(package, configs, opt)
local mingw_make = path.join(mingw, "bin", "mingw32-make.exe")
os.vrunv(mingw_make, argv)
os.vrunv(mingw_make, {"install"})
+ elseif package:is_plat("android") and is_host("windows") then
+ local make
+ local ndk = get_config("ndk")
+ if ndk then
+ make = path.join(ndk, "prebuilt", "windows-x86_64", "bin", "make.exe")
+ end
+ if not make or not os.isfile(make) then
+ make = "make"
+ end
+ os.vrunv(make, argv)
+ os.vrunv(make, {"install"})
else
os.vrunv("make", argv)
os.vrunv("make", {"install"})
@@ -629,7 +673,7 @@ function build(package, configs, opt)
opt = opt or {}
-- enter build directory
- local buildir = opt.buildir or "build_" .. hash.uuid4():split('%-')[1]
+ local buildir = opt.buildir or package:buildir()
os.mkdir(path.join(buildir, "install"))
local oldir = os.cd(buildir)
@@ -688,7 +732,7 @@ function install(package, configs, opt)
opt = opt or {}
-- enter build directory
- local buildir = opt.buildir or "build_" .. hash.uuid4():split('%-')[1]
+ local buildir = opt.buildir or package:buildir()
os.mkdir(path.join(buildir, "install"))
local oldir = os.cd(buildir)
@@ -733,4 +777,3 @@ function install(package, configs, opt)
end
os.cd(oldir)
end
-
diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua
index b236b9da6..27e73b412 100644
--- a/xmake/modules/package/tools/make.lua
+++ b/xmake/modules/package/tools/make.lua
@@ -21,6 +21,15 @@
-- imports
import("core.base.option")
import("core.project.config")
+import("lib.detect.find_tool")
+
+-- translate bin path
+function _translate_bin_path(bin_path)
+ if is_host("windows") and bin_path then
+ return bin_path:gsub("\\", "/") .. ".exe"
+ end
+ return bin_path
+end
-- get the build environments
function buildenvs(package)
@@ -43,13 +52,14 @@ function buildenvs(package)
else
local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags"))
local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags"))
- envs.CC = package:build_getenv("cc")
- envs.AS = package:build_getenv("as")
- envs.AR = package:build_getenv("ar")
- envs.LD = package:build_getenv("ld")
- envs.LDSHARED = package:build_getenv("sh")
- envs.CPP = package:build_getenv("cpp")
- envs.RANLIB = package:build_getenv("ranlib")
+ envs.CC = _translate_bin_path(package:build_getenv("cc"))
+ envs.CXX = _translate_bin_path(package:build_getenv("cxx"))
+ envs.AS = _translate_bin_path(package:build_getenv("as"))
+ envs.AR = _translate_bin_path(package:build_getenv("ar"))
+ envs.LD = _translate_bin_path(package:build_getenv("ld"))
+ envs.LDSHARED = _translate_bin_path(package:build_getenv("sh"))
+ envs.CPP = _translate_bin_path(package:build_getenv("cpp"))
+ envs.RANLIB = _translate_bin_path(package:build_getenv("ranlib"))
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ')
@@ -75,9 +85,32 @@ function buildenvs(package)
end
envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH)
envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH)
+ -- some Makefile use ComSpec to detect Windows (e.g. Makefiles generated by Premake) and require this env
+ if is_subhost("windows") then
+ envs.ComSpec = os.getenv("ComSpec")
+ end
+
return envs
end
+-- do make
+function make(package, argv, opt)
+ opt = opt or {}
+ local program
+ local runenvs = opt.envs or buildenvs(package)
+ if package:is_plat("mingw") and is_subhost("windows") then
+ local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!")
+ program = path.join(mingw, "bin", "mingw32-make.exe")
+ else
+ local tool = find_tool("make", {envs = runenvs})
+ if tool then
+ program = tool.program
+ end
+ end
+ assert(program, "make not found!")
+ os.vrunv(program, argv, {envs = runenvs, curdir = opt.curdir})
+end
+
-- build package
function build(package, configs, opt)
@@ -85,7 +118,7 @@ function build(package, configs, opt)
opt = opt or {}
-- pass configurations
- local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2))
+ local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob())
local argv = {"-j" .. njob}
if option.get("verbose") then
table.insert(argv, "VERBOSE=1")
@@ -102,11 +135,7 @@ function build(package, configs, opt)
end
-- do build
- if is_host("bsd") then
- os.vrunv("gmake", argv, {envs = opt.envs or buildenvs(package)})
- else
- os.vrunv("make", argv, {envs = opt.envs or buildenvs(package)})
- end
+ make(package, argv, opt)
end
-- install package
@@ -121,9 +150,5 @@ function install(package, configs, opt)
if option.get("verbose") then
table.insert(argv, "VERBOSE=1")
end
- if is_host("bsd") then
- os.vrunv("gmake", argv, {envs = opt.envs or buildenvs(package)})
- else
- os.vrunv("make", argv, {envs = opt.envs or buildenvs(package)})
- end
+ make(package, argv, opt)
end
diff --git a/xmake/modules/package/tools/meson.lua b/xmake/modules/package/tools/meson.lua
index 6361f2a0e..0ee1839b6 100644
--- a/xmake/modules/package/tools/meson.lua
+++ b/xmake/modules/package/tools/meson.lua
@@ -22,18 +22,31 @@
import("core.base.option")
import("core.project.config")
import("core.tool.toolchain")
+import("core.tool.linker")
+import("core.tool.compiler")
import("package.tools.ninja")
+import("lib.detect.find_tool")
-- get build directory
-function _get_buildir(opt)
+function _get_buildir(package, opt)
if opt and opt.buildir then
return opt.buildir
else
- _g.buildir = _g.buildir or ("build_" .. hash.uuid4():split('%-')[1])
+ _g.buildir = _g.buildir or package:buildir()
return _g.buildir
end
end
+-- map compiler flags
+function _map_compflags(package, langkind, name, values)
+ return compiler.map_flags(langkind, name, values, {target = package})
+end
+
+-- map linker flags
+function _map_linkflags(package, targetkind, sourcekinds, name, values)
+ return linker.map_flags(targetkind, sourcekinds, name, values, {target = package})
+end
+
-- get configs
function _get_configs(package, configs, opt)
@@ -56,7 +69,7 @@ function _get_configs(package, configs, opt)
end
-- add build directory
- table.insert(configs, _get_buildir(opt))
+ table.insert(configs, _get_buildir(package, opt))
return configs
end
@@ -79,21 +92,91 @@ function _fix_libname_on_windows(package)
end
end
+-- get cflags from package deps
+function _get_cflags_from_packagedeps(package, opt)
+ local result = {}
+ for _, depname in ipairs(opt.packagedeps) do
+ local dep = package:dep(depname)
+ if dep then
+ local fetchinfo = dep:fetch({external = false})
+ if fetchinfo then
+ table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines))
+ table.join2(result, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs))
+ table.join2(result, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs))
+ end
+ end
+ end
+ return result
+end
+
+-- get ldflags from package deps
+function _get_ldflags_from_packagedeps(package, opt)
+ local result = {}
+ for _, depname in ipairs(opt.packagedeps) do
+ local dep = package:dep(depname)
+ if dep then
+ local fetchinfo = dep:fetch({external = false})
+ if fetchinfo then
+ table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs))
+ table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links))
+ table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks))
+ end
+ end
+ end
+ return result
+end
+
-- get the build environments
-function buildenvs(package)
+function buildenvs(package, opt)
local envs = {}
+ opt = opt or {}
if package:is_plat(os.host()) then
local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags"))
local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags"))
+ local asflags = table.wrap(package:config("asflags"))
+ local ldflags = table.wrap(package:config("ldflags"))
+ local shflags = table.wrap(package:config("shflags"))
+ table.join2(cflags, opt.cflags)
+ table.join2(cflags, opt.cxflags)
+ table.join2(cxxflags, opt.cxxflags)
+ table.join2(cxxflags, opt.cxflags)
+ table.join2(asflags, opt.asflags)
+ table.join2(ldflags, opt.ldflags)
+ table.join2(shflags, opt.shflags)
+ table.join2(cflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt))
+ table.join2(shflags, _get_ldflags_from_packagedeps(package, opt))
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
- envs.ASFLAGS = table.concat(table.wrap(package:config("asflags")), ' ')
+ envs.ASFLAGS = table.concat(asflags, ' ')
+ envs.LDFLAGS = table.concat(ldflags, ' ')
+ envs.SHFLAGS = table.concat(shflags, ' ')
if package:is_plat("windows") then
envs = os.joinenvs(envs, _get_msvc_runenvs(package))
+ local pkgconf = find_tool("pkgconf")
+ if pkgconf then
+ envs.PKG_CONFIG = pkgconf.program
+ end
end
else
local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags"))
local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags"))
+ local asflags = table.wrap(package:build_getenv("asflags"))
+ local arflags = table.wrap(package:build_getenv("arflags"))
+ local ldflags = table.wrap(package:build_getenv("ldflags"))
+ local shflags = table.wrap(package:build_getenv("shflags"))
+ table.join2(cflags, opt.cflags)
+ table.join2(cflags, opt.cxflags)
+ table.join2(cxxflags, opt.cxxflags)
+ table.join2(cxxflags, opt.cxflags)
+ table.join2(asflags, opt.asflags)
+ table.join2(ldflags, opt.ldflags)
+ table.join2(shflags, opt.shflags)
+ table.join2(cflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt))
+ table.join2(shflags, _get_ldflags_from_packagedeps(package, opt))
envs.CC = package:build_getenv("cc")
envs.AS = package:build_getenv("as")
envs.AR = package:build_getenv("ar")
@@ -103,10 +186,10 @@ function buildenvs(package)
envs.RANLIB = package:build_getenv("ranlib")
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
- envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ')
- envs.ARFLAGS = table.concat(table.wrap(package:build_getenv("arflags")), ' ')
- envs.LDFLAGS = table.concat(table.wrap(package:build_getenv("ldflags")), ' ')
- envs.SHFLAGS = table.concat(table.wrap(package:build_getenv("shflags")), ' ')
+ envs.ASFLAGS = table.concat(asflags, ' ')
+ envs.ARFLAGS = table.concat(arflags, ' ')
+ envs.LDFLAGS = table.concat(ldflags, ' ')
+ envs.SHFLAGS = table.concat(shflags, ' ')
end
local ACLOCAL_PATH = {}
local PKG_CONFIG_PATH = {}
@@ -149,7 +232,7 @@ function generate(package, configs, opt)
end
-- do configure
- os.vrunv("meson", argv, {envs = opt.envs or buildenvs(package)})
+ os.vrunv("meson", argv, {envs = opt.envs or buildenvs(package, opt)})
end
-- build package
@@ -160,7 +243,7 @@ function build(package, configs, opt)
generate(package, configs, opt)
-- do build
- local buildir = _get_buildir(opt)
+ local buildir = _get_buildir(package, opt)
ninja.build(package, {}, {buildir = buildir, envs = opt.envs or buildenvs(package, opt)})
end
@@ -172,7 +255,7 @@ function install(package, configs, opt)
generate(package, configs, opt)
-- do build and install
- local buildir = _get_buildir(opt)
+ local buildir = _get_buildir(package, opt)
ninja.install(package, {}, {buildir = buildir, envs = opt.envs or buildenvs(package, opt)})
-- fix static libname on windows
diff --git a/xmake/modules/package/tools/ninja.lua b/xmake/modules/package/tools/ninja.lua
index e1feccc14..0d3ad9708 100644
--- a/xmake/modules/package/tools/ninja.lua
+++ b/xmake/modules/package/tools/ninja.lua
@@ -26,9 +26,14 @@ import("lib.detect.find_tool")
function build(package, configs, opt)
opt = opt or {}
local buildir = opt.buildir or os.curdir()
- local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2))
+ local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob())
local ninja = assert(find_tool("ninja"), "ninja not found!")
- local argv = {"-C", buildir}
+ local argv = {}
+ if opt.target then
+ table.insert(argv, opt.target)
+ end
+ table.insert(argv, "-C")
+ table.insert(argv, buildir)
if option.get("verbose") then
table.insert(argv, "-v")
end
@@ -44,7 +49,7 @@ end
function install(package, configs, opt)
opt = opt or {}
local buildir = opt.buildir or os.curdir()
- local njob = tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2))
+ local njob = tostring(os.default_njob())
local ninja = assert(find_tool("ninja"), "ninja not found!")
local argv = {"install", "-C", buildir}
if option.get("verbose") then
diff --git a/xmake/modules/package/tools/scons.lua b/xmake/modules/package/tools/scons.lua
index 386645bba..0c197933f 100644
--- a/xmake/modules/package/tools/scons.lua
+++ b/xmake/modules/package/tools/scons.lua
@@ -86,7 +86,7 @@ end
function build(package, configs, opt)
opt = opt or {}
local buildir = opt.buildir or os.curdir()
- local njob = opt.jobs or option.get("jobs") or tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2))
+ local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob())
local scons = assert(find_tool("scons"), "scons not found!")
local argv = {"-C", buildir, "-j", njob}
configs = _get_configs(package, configs)
diff --git a/xmake/modules/package/tools/xmake.lua b/xmake/modules/package/tools/xmake.lua
index 0c7d9c294..9bfcffaff 100644
--- a/xmake/modules/package/tools/xmake.lua
+++ b/xmake/modules/package/tools/xmake.lua
@@ -59,13 +59,28 @@ function _get_configs(package, configs)
table.insert(configs, "--cross=" .. cross)
end
local bindir = _get_config_from_toolchains(package, "bindir") or get_config("bin")
- if cross then
+ if bindir then
table.insert(configs, "--bin=" .. bindir)
end
local sdkdir = _get_config_from_toolchains(package, "sdkdir") or get_config("sdk")
- if cross then
+ if sdkdir then
table.insert(configs, "--sdk=" .. sdkdir)
end
+ -- we can only modify toolchain for cross-compilation
+ --
+ -- e.g. xrepo install -p cross --toolchain=muslcc meson,
+ -- we cannot pass muslcc toolchain to it's deps(zlib, ..), because meson is always host binary and zlib is host library.
+ local toolchain_name = get_config("toolchain")
+ if toolchain_name then
+ table.insert(configs, "--toolchain=" .. toolchain_name)
+ end
+ local names = {"ld", "sh", "ar", "cc", "cxx"}
+ for _, name in ipairs(names) do
+ local value = get_config(name)
+ if value ~= nil then
+ table.insert(configs, "--" .. name .. "=" .. tostring(value))
+ end
+ end
else
local names = {"ndk", "ndk_sdkver", "vs", "mingw", "ld", "sh", "ar", "cc", "cxx", "mm", "mxx"}
for _, name in ipairs(names) do
diff --git a/xmake/modules/private/action/build/object.lua b/xmake/modules/private/action/build/object.lua
index 50397cda4..e07ab76b7 100644
--- a/xmake/modules/private/action/build/object.lua
+++ b/xmake/modules/private/action/build/object.lua
@@ -25,7 +25,7 @@ import("core.tool.compiler")
import("core.project.depend")
import("private.tools.ccache")
import("private.async.runjobs")
-import("private.utils.progress")
+import("utils.progress")
-- do build file
function _do_build_file(target, sourcefile, opt)
@@ -85,7 +85,7 @@ function _do_build_file(target, sourcefile, opt)
end
-- build object
-function _build_object(target, sourcefile, opt)
+function build_object(target, sourcefile, opt)
local script = target:script("build_file", _do_build_file)
if script then
script(target, sourcefile, opt)
@@ -99,7 +99,7 @@ function build(target, sourcebatch, opt)
opt.objectfile = sourcebatch.objectfiles[i]
opt.dependfile = sourcebatch.dependfiles[i]
opt.sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile)
- _build_object(target, sourcefile, opt)
+ build_object(target, sourcefile, opt)
end
end
@@ -113,7 +113,7 @@ function main(target, batchjobs, sourcebatch, opt)
local sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile)
batchjobs:addjob(sourcefile, function (index, total)
local build_opt = table.join({objectfile = objectfile, dependfile = dependfile, sourcekind = sourcekind, progress = (index * 100) / total}, opt)
- _build_object(target, sourcefile, build_opt)
+ build_object(target, sourcefile, build_opt)
end, {rootjob = rootjob})
end
end
diff --git a/xmake/modules/private/action/require/impl/actions/download.lua b/xmake/modules/private/action/require/impl/actions/download.lua
index bee421052..f2c8eeba7 100644
--- a/xmake/modules/private/action/require/impl/actions/download.lua
+++ b/xmake/modules/private/action/require/impl/actions/download.lua
@@ -70,13 +70,13 @@ function _checkout(package, url, sourcedir, url_alias)
if package:branch() then
-- only shadow clone this branch
- git.clone(proxy.mirror(url) or url, {depth = 1, recursive = true, longpaths = longpaths, branch = package:branch(), outputdir = packagedir})
+ git.clone(url, {depth = 1, recursive = true, longpaths = longpaths, branch = package:branch(), outputdir = packagedir})
-- download package from revision or tag?
else
-- clone whole history and tags
- git.clone(proxy.mirror(url) or url, {longpaths = longpaths, outputdir = packagedir})
+ git.clone(url, {longpaths = longpaths, outputdir = packagedir})
-- attempt to checkout the given version
local revision = package:revision(url_alias) or package:tag() or package:version_str()
@@ -139,7 +139,7 @@ function _download(package, url, sourcedir, url_alias, url_excludes)
-- we can use local package from the search directories directly if network is too slow
os.cp(localfile, packagefile)
else
- http.download(proxy.mirror(url) or url, packagefile)
+ http.download(url, packagefile)
end
end
@@ -151,15 +151,20 @@ function _download(package, url, sourcedir, url_alias, url_excludes)
-- extract package file
os.rm(sourcedir .. ".tmp")
+ local extension = archive.extension(packagefile)
if archive.extract(packagefile, sourcedir .. ".tmp", {excludes = url_excludes}) then
-- move to source directory
os.rm(sourcedir)
os.mv(sourcedir .. ".tmp", sourcedir)
- else
+ elseif extension and extension ~= "" then
-- create an empty source directory if do not extract package file
os.tryrm(sourcedir)
os.mkdir(sourcedir)
- raise("cannot extract %s", packagefile)
+ raise("cannot extract %s, maybe missing extractor or invalid package file!", packagefile)
+ else
+ -- if it is not archive file, we need only create empty source file and use package:originfile()
+ os.tryrm(sourcedir)
+ os.mkdir(sourcedir)
end
-- save original file path
@@ -224,7 +229,13 @@ function main(package)
-- filter url
url = filter.handle(url, package)
+ -- use proxy url?
+ if not os.isfile(url) then
+ url = proxy.mirror(url) or url
+ end
+
-- download url
+ local allerrors = {}
ok = try
{
function ()
@@ -243,8 +254,12 @@ function main(package)
function (errors)
-- show or save the last errors
- if errors and (option.get("verbose") or option.get("diagnosis")) then
- cprint("${dim color.error}error: ${clear}%s", errors)
+ if errors then
+ if (option.get("verbose") or option.get("diagnosis")) then
+ cprint("${dim color.error}error: ${clear}%s", errors)
+ else
+ table.insert(allerrors, errors)
+ end
end
-- trace
@@ -270,7 +285,11 @@ function main(package)
cprint(" ${bright}- %s", table.concat(searchnames:to_array(), ", "))
cprint("and we can run `xmake g --pkg_searchdirs=/xxx` to set the search directories.")
end
- raise("download failed!")
+ if #allerrors then
+ raise(table.concat(allerrors, "\n"))
+ else
+ raise("download failed!")
+ end
end
end
}
diff --git a/xmake/modules/private/action/require/impl/actions/download_resources.lua b/xmake/modules/private/action/require/impl/actions/download_resources.lua
index fa115c04a..c6af29151 100644
--- a/xmake/modules/private/action/require/impl/actions/download_resources.lua
+++ b/xmake/modules/private/action/require/impl/actions/download_resources.lua
@@ -32,6 +32,7 @@ import("utils.archive")
function _checkout(package, resource_name, resource_url, resource_revision)
-- trace
+ resource_url = proxy.mirror(resource_url) or resource_url
vprint("cloning resource(%s: %s) to %s-%s ..", resource_name, resource_revision, package:name(), package:version_str())
-- get the resource directory
@@ -62,7 +63,7 @@ function _checkout(package, resource_name, resource_url, resource_revision)
local longpaths = package:policy("platform.longpaths")
-- clone whole history and tags
- git.clone(proxy.mirror(resource_url) or resource_url, {longpaths = longpaths, outputdir = resourcedir})
+ git.clone(resource_url, {longpaths = longpaths, outputdir = resourcedir})
-- attempt to checkout the given version
git.checkout(resource_revision, {repodir = resourcedir})
@@ -77,6 +78,7 @@ end
function _download(package, resource_name, resource_url, resource_hash)
-- trace
+ resource_url = proxy.mirror(resource_url) or resource_url
vprint("downloading resource(%s: %s) to %s-%s ..", resource_name, resource_url, package:name(), package:version_str())
-- get the resource file
@@ -103,7 +105,7 @@ function _download(package, resource_name, resource_url, resource_hash)
-- we can use local resource from the search directories directly if network is too slow
os.cp(localfile, resource_file)
elseif resource_url:find(string.ipattern("https-://")) or resource_url:find(string.ipattern("ftps-://")) then
- http.download(proxy.mirror(resource_url) or resource_url, resource_file)
+ http.download(resource_url, resource_file)
else
raise("invalid resource url(%s)", resource_url)
end
diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua
index 81f93681e..cbe836ed2 100644
--- a/xmake/modules/private/action/require/impl/actions/install.lua
+++ b/xmake/modules/private/action/require/impl/actions/install.lua
@@ -55,8 +55,11 @@ function _patch_pkgconfig(package)
-- get libs
local libs = ""
+ local installdir = package:installdir()
for _, linkdir in ipairs(fetchinfo.linkdirs) do
- libs = libs .. "-L" .. linkdir
+ if linkdir ~= path.join(installdir, "lib") then
+ libs = libs .. " -L" .. (linkdir:gsub("\\", "/"))
+ end
end
libs = libs .. " -L${libdir}"
for _, link in ipairs(fetchinfo.links) do
@@ -69,14 +72,16 @@ function _patch_pkgconfig(package)
-- cflags
local cflags = ""
for _, includedir in ipairs(fetchinfo.includedirs) do
- cflags = cflags .. "-I" .. includedir
+ if includedir ~= path.join(installdir, "include") then
+ cflags = cflags .. " -I" .. (includedir:gsub("\\", "/"))
+ end
end
cflags = cflags .. " -I${includedir}"
-- patch a *.pc file
local file = io.open(pcfile, 'w')
if file then
- file:print("prefix=%s", package:installdir())
+ file:print("prefix=%s", installdir:gsub("\\", "/"))
file:print("exec_prefix=${prefix}")
file:print("libdir=${exec_prefix}/lib")
file:print("includedir=${prefix}/include")
@@ -91,6 +96,32 @@ function _patch_pkgconfig(package)
end
end
+-- fix paths for the precompiled package
+-- @see https://github.com/xmake-io/xmake/issues/1671
+function _fix_paths_for_precompiled_package(package)
+ local filepaths = {path.join(package:installdir(), "**.cmake|include/**")}
+ for _, filepath in ipairs(filepaths) do
+ for _, file in ipairs(os.files(filepath)) do
+ io.gsub(file, "(\"(.-)\")", function(_, value)
+ if value:find(package:buildhash(), 1, true) and value:find(package:name(), 1, true) then
+ local result
+ local splitinfo = value:split(package:buildhash(), {plain = true})
+ if #splitinfo == 2 then
+ result = path.join(package:installdir(), splitinfo[2])
+ elseif #splitinfo == 1 then
+ result = package:installdir()
+ end
+ if result then
+ result = result:gsub("\\", "/")
+ vprint("fix path: %s in %s", result, path.filename(file))
+ return "\"" .. result .. "\""
+ end
+ end
+ end)
+ end
+ end
+end
+
-- check package toolchains
function _check_package_toolchains(package)
for _, toolchain_inst in pairs(package:toolchains()) do
@@ -111,7 +142,10 @@ function main(package)
-- enter the working directory
local oldir = nil
- if #package:urls() > 0 then
+ local sourcedir = package:sourcedir()
+ if sourcedir then
+ oldir = os.cd(sourcedir)
+ elseif #package:urls() > 0 then
-- only one root directory? skip it
local filedirs = os.filedirs(path.join(workdir, "source", "*"))
if #filedirs == 1 and os.isdir(filedirs[1]) then
@@ -196,6 +230,11 @@ function main(package)
-- this package is installed now
if installed_now then
+ -- fix paths for the precompiled package
+ if package:is_plat("windows") and not package:is_built() and not package:is_system() then
+ _fix_paths_for_precompiled_package(package)
+ end
+
-- patch pkg-config files for package
_patch_pkgconfig(package)
@@ -247,7 +286,16 @@ function main(package)
-- failed
if not package:requireinfo().optional then
if os.isfile(errorfile) then
- print("if you want to get verbose errors, please see:")
+ if errors then
+ print("")
+ for idx, line in ipairs(errors:split("\n")) do
+ print(line)
+ if idx > 16 then
+ break
+ end
+ end
+ end
+ cprint("if you want to get more verbose errors, please see:")
cprint(" -> ${bright}%s", errorfile)
end
raise("install failed!")
diff --git a/xmake/modules/private/action/require/impl/actions/patch_sources.lua b/xmake/modules/private/action/require/impl/actions/patch_sources.lua
index 23d46f3d3..d5874f8f5 100644
--- a/xmake/modules/private/action/require/impl/actions/patch_sources.lua
+++ b/xmake/modules/private/action/require/impl/actions/patch_sources.lua
@@ -50,6 +50,7 @@ end
function _patch(package, patch_url, patch_hash)
-- trace
+ patch_url = proxy.mirror(patch_url) or patch_url
vprint("patching %s to %s-%s ..", patch_url, package:name(), package:version_str())
-- get the patch file
@@ -72,7 +73,7 @@ function _patch(package, patch_url, patch_hash)
-- download the patch file
if patch_url:find(string.ipattern("https-://")) or patch_url:find(string.ipattern("ftps-://")) then
- http.download(proxy.mirror(patch_url) or patch_url, patch_file)
+ http.download(patch_url, patch_file)
else
-- copy the patch file
if os.isfile(patch_url) then
diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua
index 7e83ae939..f62a0fb52 100644
--- a/xmake/modules/private/action/require/impl/install_packages.lua
+++ b/xmake/modules/private/action/require/impl/install_packages.lua
@@ -25,11 +25,12 @@ import("core.base.scheduler")
import("core.project.project")
import("core.base.tty")
import("private.async.runjobs")
-import("private.utils.progress")
+import("utils.progress")
import("actions.install", {alias = "action_install"})
import("actions.download", {alias = "action_download"})
import("net.fasturl")
import("private.action.require.impl.package")
+import("private.action.require.impl.lock_packages")
import("private.action.require.impl.register_packages")
-- sort packages urls
@@ -242,6 +243,19 @@ function _get_confirm(packages)
return result, packages_modified
end
+-- show upgraded packages
+function _show_upgraded_packages(packages)
+ local upgraded_count = 0
+ for _, instance in ipairs(packages) do
+ local locked_requireinfo = package.get_locked_requireinfo(instance:requireinfo(), {force = true})
+ if locked_requireinfo and locked_requireinfo.version and instance:version() and instance:version():gt(locked_requireinfo.version) then
+ cprint(" ${color.dump.string}%s${clear}: %s -> ${color.success}%s", instance:displayname(), locked_requireinfo.version, instance:version_str())
+ upgraded_count = upgraded_count + 1
+ end
+ end
+ cprint("${bright}%d packages are upgraded!", upgraded_count)
+end
+
-- install packages
function _install_packages(packages_install, packages_download, installdeps)
@@ -254,6 +268,9 @@ function _install_packages(packages_install, packages_download, installdeps)
packages_installed[tostring(instance)] = false
end
+ -- save terminal mode for stdout, @see https://github.com/xmake-io/xmake/issues/1924
+ local term_mode_stdout = tty.term_mode("stdout")
+
-- do install
local progress_helper = show_wait and progress.new() or nil
local packages_installing = {}
@@ -424,6 +441,12 @@ function _install_packages(packages_install, packages_download, installdeps)
end
end
+ -- fix terminal mode to avoid some subprocess to change it
+ -- @see https://github.com/xmake-io/xmake/issues/1924
+ if term_mode_stdout ~= tty.term_mode("stdout") then
+ tty.term_mode("stdout", term_mode_stdout)
+ end
+
-- trace
progress_helper:clear()
tty.erase_line_to_start().cr()
@@ -579,6 +602,11 @@ function main(requires, opt)
end
end
+ -- show upgraded information
+ if option.get("upgrade") then
+ print("upgrading packages ..")
+ end
+
-- some packages are modified? we need fix packages list and all deps
if packages_modified then
order_packages = {}
@@ -600,6 +628,14 @@ function main(requires, opt)
-- re-register and refresh all root packages to local cache,
-- because there may be some missing optional dependencies reinstalled
register_packages(packages)
+
+ -- show upgraded packages
+ if option.get("upgrade") then
+ _show_upgraded_packages(packages)
+ end
+
+ -- lock packages
+ lock_packages(packages)
return packages
end
diff --git a/xmake/modules/private/action/require/impl/lock_packages.lua b/xmake/modules/private/action/require/impl/lock_packages.lua
new file mode 100644
index 000000000..6a962ba77
--- /dev/null
+++ b/xmake/modules/private/action/require/impl/lock_packages.lua
@@ -0,0 +1,72 @@
+--!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 lock_packages.lua
+--
+
+-- imports
+import("core.project.project")
+import("core.project.config")
+import("devel.git")
+import("private.action.require.impl.utils.filter")
+import("private.action.require.impl.utils.requirekey")
+
+-- get locked package key
+function _get_packagelock_key(instance)
+ local requireinfo = instance:requireinfo()
+ return requireinfo and requireinfo.requirekey
+end
+
+-- lock package
+function _lock_package(instance)
+ local result = {}
+ local repo = instance:repo()
+ result.version = instance:version_str()
+ result.branch = instance:branch()
+ result.tag = instance:tag()
+ if repo then
+ local lastcommit
+ local manifest = instance:manifest_load()
+ if manifest and manifest.repo then
+ lastcommit = manifest.repo.commit
+ end
+ if not lastcommit then
+ lastcommit = repo:commit()
+ end
+ result.repo = {url = repo:url(), commit = lastcommit, branch = repo:branch()}
+ end
+ return result
+end
+
+-- lock all required packages
+function main(packages)
+ if project.policy("package.requires_lock") then
+ local plat = config.plat() or os.subhost()
+ local arch = config.arch() or so.subarch()
+ local key = plat .. "|" .. arch
+ local results = os.isfile(project.requireslock()) and io.load(project.requireslock()) or {}
+ results.__meta__ = results.__meta__ or {}
+ results.__meta__.version = project.requireslock_version()
+ results[key] = {}
+ for _, instance in ipairs(packages) do
+ local packagelock_key = _get_packagelock_key(instance)
+ results[key][packagelock_key] = _lock_package(instance)
+ end
+ io.writefile(project.requireslock(), string.serialize(results, {orderkeys = true}))
+ end
+end
+
diff --git a/xmake/modules/private/action/require/impl/package.lua b/xmake/modules/private/action/require/impl/package.lua
index 612911429..1d013b91e 100644
--- a/xmake/modules/private/action/require/impl/package.lua
+++ b/xmake/modules/private/action/require/impl/package.lua
@@ -23,13 +23,15 @@ import("core.base.semver")
import("core.base.option")
import("core.base.global")
import("core.base.hashset")
-import("private.utils.progress")
+import("utils.progress")
import("core.cache.memcache")
import("core.project.project")
+import("core.project.config")
import("core.tool.toolchain")
import("core.package.package", {alias = "core_package"})
import("devel.git")
import("private.action.require.impl.repository")
+import("private.action.require.impl.utils.requirekey", {alias = "_get_requirekey"})
-- get memcache
function _memcache()
@@ -150,8 +152,23 @@ function _load_require(require_str, requires_extra, parentinfo)
-- require packge in the current host platform
if require_extra.host then
- require_extra.plat = os.host()
- require_extra.arch = os.arch()
+ if is_subhost(core_package.targetplat()) and os.subarch() == core_package.targetarch() then
+ -- we need pass plat/arch to avoid repeat installation
+ -- @see https://github.com/xmake-io/xmake/issues/1579
+ else
+ require_extra.plat = os.subhost()
+ require_extra.arch = os.subarch()
+ end
+ end
+
+ -- check require options
+ local extra_options = hashset.of("plat", "arch", "kind", "host", "targetos",
+ "alias", "group", "system", "option", "default", "optional", "debug",
+ "verify", "external", "private", "build", "configs", "version")
+ for name, value in pairs(require_extra) do
+ if not extra_options:has(name) then
+ wprint("add_requires(\"%s\") has unknown option: {%s=%s}!", require_str, name, tostring(value))
+ end
end
-- init required item
@@ -193,13 +210,41 @@ function _load_package_from_project(packagename)
end
-- load package package from repositories
-function _load_package_from_repository(packagename, reponame)
- local packagedir, repo = repository.packagedir(packagename, reponame)
+function _load_package_from_repository(packagename, opt)
+ local packagedir, repo = repository.packagedir(packagename, opt)
if packagedir then
return core_package.load_from_repository(packagename, repo, packagedir)
end
end
+-- has locked requires?
+function _has_locked_requires(opt)
+ opt = opt or {}
+ if not option.get("upgrade") or opt.force then
+ return project.policy("package.requires_lock") and os.isfile(project.requireslock())
+ end
+end
+
+-- get locked requires
+function _get_locked_requires(requirekey, opt)
+ opt = opt or {}
+ local requireslock = _memcache():get("requireslock")
+ if requireslock == nil or opt.force then
+ if _has_locked_requires(opt) then
+ requireslock = io.load(project.requireslock())
+ end
+ _memcache():set("requireslock", requireslock or false)
+ end
+ if requireslock then
+ local plat = config.plat() or os.subhost()
+ local arch = config.arch() or os.subarch()
+ local key = plat .. "|" .. arch
+ if requireslock[key] then
+ return requireslock[key][requirekey], requireslock.__meta__.version
+ end
+ end
+end
+
-- sort package deps
--
-- e.g.
@@ -209,18 +254,39 @@ end
--
-- orderdeps: c -> b -> a
--
-function _sort_packagedeps(package, onlylink)
+function _sort_packagedeps(package)
-- we must use native deps list instead of package:deps() to generate correct linkdeps
local orderdeps = {}
for _, dep in ipairs(package:plaindeps()) do
- if dep and (onlylink ~= true or (dep:is_library() and not dep:is_private())) then
- table.join2(orderdeps, _sort_packagedeps(dep, onlylink))
+ if dep then
+ table.join2(orderdeps, _sort_packagedeps(dep))
table.insert(orderdeps, dep)
end
end
return orderdeps
end
+-- sort link deps
+--
+-- e.g.
+--
+-- a.deps = b
+-- b.deps = c
+--
+-- orderdeps: a -> b -> c
+--
+function _sort_linkdeps(package)
+ -- we must use native deps list instead of package:deps() to generate correct linkdeps
+ local orderdeps = {}
+ for _, dep in ipairs(package:plaindeps()) do
+ if dep and dep:is_library() and not dep:is_private() then
+ table.insert(orderdeps, dep)
+ table.join2(orderdeps, _sort_linkdeps(dep))
+ end
+ end
+ return orderdeps
+end
+
-- add some builtin configurations to package
function _add_package_configurations(package)
-- we can define configs to override it and it's default value in package()
@@ -246,10 +312,22 @@ function _add_package_configurations(package)
end
-- select package version
-function _select_package_version(package, requireinfo)
+function _select_package_version(package, requireinfo, locked_requireinfo)
- -- exists urls? otherwise be phony package (only as package group)
- if #package:urls() > 0 then
+ -- get it from the locked requireinfo
+ if locked_requireinfo then
+ local version = locked_requireinfo.version
+ local source = "version"
+ if locked_requireinfo.branch then
+ source = "branch"
+ elseif locked_requireinfo.tag then
+ source = "tag"
+ end
+ return version, source
+ end
+
+ -- if not phony package (only as package group)
+ if not requireinfo.group then
-- has git url?
local has_giturl = false
@@ -270,14 +348,19 @@ function _select_package_version(package, requireinfo)
-- @see https://github.com/xmake-io/xmake/issues/930
-- https://github.com/xmake-io/xmake/issues/1009
version = require_version
- source = "versions"
+ source = "version"
elseif #package:versions() > 0 then -- select version?
version, source = try { function () return semver.select(require_version, package:versions()) end }
end
- if not version and has_giturl and not require_version:find('.', 1, true) then -- select branch?
- version, source = require_version ~= "latest" and require_version or "master", "branches"
+ if not version and has_giturl and not semver.is_valid(require_version) then -- select branch?
+ version, source = require_version ~= "latest" and require_version or "master", "branch"
end
- if not version then
+ -- local source package? we use a phony version
+ if not version and require_version == "latest" and #package:urls() == 0 then
+ version = "latest"
+ source = "version"
+ end
+ if not version and not package:is_thirdparty() then
raise("package(%s): version(%s) not found!", package:name(), require_version)
end
return version, source
@@ -477,26 +560,17 @@ end
-- get package key
function _get_packagekey(packagename, requireinfo, version)
- local key = packagename .. "/" .. (version or requireinfo.version)
- if requireinfo.plat then
- key = key .. "/" .. requireinfo.plat
- end
- if requireinfo.arch then
- key = key .. "/" .. requireinfo.arch
- end
- if requireinfo.label then
- key = key .. "/" .. requireinfo.label
- end
- local configs = requireinfo.configs
- if configs then
- local configs_order = {}
- for k, v in pairs(configs) do
- table.insert(configs_order, k .. "=" .. tostring(v))
- end
- table.sort(configs_order)
- key = key .. ":" .. string.serialize(configs_order, true)
- end
- return key
+ return _get_requirekey(requireinfo, {name = packagename,
+ plat = requireinfo.plat,
+ arch = requireinfo.arch,
+ version = version or requireinfo.version})
+end
+
+-- get locked package key
+function _get_packagelock_key(requireinfo)
+ local requirestr = requireinfo.originstr
+ local key = _get_requirekey(requireinfo, {hash = true})
+ return string.format("%s#%s", requirestr, key)
end
-- inherit some builtin configs of parent package if these config values are not default value
@@ -520,9 +594,6 @@ function _inherit_parent_configs(requireinfo, package, parentinfo)
if parentinfo.arch then
requireinfo.arch = parentinfo.arch
end
- if parentinfo.private ~= nil then
- requireinfo.private = parentinfo.private
- end
requireinfo_configs.toolchains = requireinfo_configs.toolchains or parentinfo_configs.toolchains
requireinfo_configs.vs_runtime = requireinfo_configs.vs_runtime or parentinfo_configs.vs_runtime
requireinfo.configs = requireinfo_configs
@@ -610,6 +681,13 @@ function _load_package(packagename, requireinfo, opt)
requireinfo.label = splitinfo[2]
end
+ -- save requirekey
+ local requirekey = _get_packagelock_key(requireinfo)
+ requireinfo.requirekey = requirekey
+
+ -- get locked requireinfo
+ local locked_requireinfo = get_locked_requireinfo(requireinfo)
+
-- load package from project first
local package
if os.isfile(os.projectfile()) then
@@ -619,7 +697,8 @@ function _load_package(packagename, requireinfo, opt)
-- load package from repositories
local from_repo = false
if not package then
- package = _load_package_from_repository(packagename, requireinfo.reponame)
+ package = _load_package_from_repository(packagename, {
+ name = requireinfo.reponame, locked_repo = locked_requireinfo and locked_requireinfo.repo})
if package then
from_repo = true
end
@@ -652,7 +731,7 @@ function _load_package(packagename, requireinfo, opt)
_finish_requireinfo(requireinfo, package)
-- select package version
- local version, source = _select_package_version(package, requireinfo)
+ local version, source = _select_package_version(package, requireinfo, locked_requireinfo)
if version then
package:version_set(version, source)
end
@@ -760,7 +839,7 @@ function _load_packages(requires, opt)
package._DEPS = packagedeps
package._PLAINDEPS = plaindeps
package._ORDERDEPS = table.unique(_sort_packagedeps(package))
- package._LINKDEPS = table.unique(_sort_packagedeps(package, true))
+ package._LINKDEPS = table.reverse_unique(_sort_linkdeps(package))
end
end
@@ -889,7 +968,7 @@ function get_configs_str(package)
if type(v) == "boolean" then
table.insert(configs, k .. ":" .. (v and "y" or "n"))
else
- table.insert(configs, k .. ":" .. v)
+ table.insert(configs, k .. ":" .. string.serialize(v, {strip = true, indent = false}))
end
end
end
@@ -898,13 +977,26 @@ function get_configs_str(package)
table.insert(configs, "from:" .. parents_str)
end
local configs_str = #configs > 0 and "[" .. table.concat(configs, ", ") .. "]" or ""
- local limitwidth = os.getwinsize().width * 2 / 3
+ local limitwidth = math.floor(os.getwinsize().width * 2 / 3)
if #configs_str > limitwidth then
configs_str = configs_str:sub(1, limitwidth) .. " ..)"
end
return configs_str
end
+-- get locked requireinfo
+function get_locked_requireinfo(requireinfo, opt)
+ local requirekey = requireinfo.requirekey
+ local locked_requireinfo, requireslock_version
+ if _has_locked_requires(opt) and requirekey then
+ locked_requireinfo, requireslock_version = _get_locked_requires(requirekey, opt)
+ if requireslock_version and semver.compare(project.requireslock_version(), requireslock_version) < 0 then
+ locked_requireinfo = nil
+ end
+ end
+ return locked_requireinfo, requireslock_version
+end
+
-- load requires
function load_requires(requires, requires_extra, opt)
opt = opt or {}
diff --git a/xmake/modules/private/action/require/impl/packagenv.lua b/xmake/modules/private/action/require/impl/packagenv.lua
index 12a98d36f..06a70df91 100644
--- a/xmake/modules/private/action/require/impl/packagenv.lua
+++ b/xmake/modules/private/action/require/impl/packagenv.lua
@@ -33,7 +33,7 @@ function _enter_package(package_name, envs, installdir)
end
end
else
- os.addenv(name, unpack(table.wrap(values)))
+ os.addenv(name, table.unpack(table.wrap(values)))
end
end
end
diff --git a/xmake/modules/private/action/require/impl/register_packages.lua b/xmake/modules/private/action/require/impl/register_packages.lua
index 4c326e770..afc84eb98 100644
--- a/xmake/modules/private/action/require/impl/register_packages.lua
+++ b/xmake/modules/private/action/require/impl/register_packages.lua
@@ -88,16 +88,9 @@ function _register_required_package(instance, required_package)
_register_required_package_base(instance, required_package)
_register_required_package_libs(instance, required_package)
_register_required_package_envs(instance, envs)
- local linkdeps = instance:linkdeps()
- if linkdeps then
- local total = #linkdeps
- for idx, _ in ipairs(linkdeps) do
- local dep = linkdeps[total + 1 - idx]
- if dep then
- if instance:is_library() then
- _register_required_package_libs(dep, required_package, true)
- end
- end
+ for _, dep in ipairs(instance:linkdeps()) do
+ if instance:is_library() then
+ _register_required_package_libs(dep, required_package, true)
end
end
for _, dep in ipairs(instance:orderdeps()) do
diff --git a/xmake/modules/private/action/require/impl/remove_packages.lua b/xmake/modules/private/action/require/impl/remove_packages.lua
index b65627256..f8f93c663 100644
--- a/xmake/modules/private/action/require/impl/remove_packages.lua
+++ b/xmake/modules/private/action/require/impl/remove_packages.lua
@@ -36,7 +36,7 @@ function _get_package_configs_str(manifest_file)
end
end
local configs_str = #configs > 0 and "[" .. table.concat(configs, ", ") .. "]" or ""
- local limitwidth = os.getwinsize().width * 2 / 3
+ local limitwidth = math.floor(os.getwinsize().width * 2 / 3)
if #configs_str > limitwidth then
configs_str = configs_str:sub(1, limitwidth) .. " ..)"
end
diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua
index 4dbf44e52..189fad594 100644
--- a/xmake/modules/private/action/require/impl/repository.lua
+++ b/xmake/modules/private/action/require/impl/repository.lua
@@ -19,8 +19,86 @@
--
-- imports
+import("core.base.option")
import("core.base.global")
+import("core.project.config")
import("core.package.repository")
+import("devel.git")
+import("net.proxy")
+
+-- get package directory from the locked repository
+function _get_packagedir_from_locked_repo(packagename, locked_repo)
+
+ -- find global repository directory
+ local repo_global
+ for _, repo in ipairs(repositories()) do
+ if locked_repo.url == repo:url() and locked_repo.branch == repo:branch() then
+ repo_global = repo
+ break
+ end
+ end
+ local reponame = hash.uuid(locked_repo.url):gsub("%-", ""):lower() .. ".lock"
+
+ -- get local repodir
+ local repodir_local
+ if os.isdir(locked_repo.url) then
+ repodir_local = locked_repo.url
+ elseif not locked_repo.commit and repo_global then
+ repodir_local = repo_global:directory()
+ else
+ repodir_local = path.join(config.directory(), "repositories", reponame)
+ end
+
+ -- clone repository to local
+ local lastcommit
+ if not os.isdir(repodir_local) then
+ if repo_global then
+ git.clone(repo_global:directory(), {verbose = option.get("verbose"), outputdir = repodir_local})
+ lastcommit = repo_global:commit()
+ elseif global.get("network") ~= "private" then
+ local remoteurl = proxy.mirror(locked_repo.url) or locked_repo.url
+ git.clone(remoteurl, {verbose = option.get("verbose"), branch = locked_repo.branch, outputdir = repodir_local})
+ else
+ wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url)
+ return
+ end
+ end
+
+ -- lock commit
+ if locked_repo.commit and os.isdir(path.join(repodir_local, ".git")) then
+ lastcommit = lastcommit or try {function()
+ return git.lastcommit({repodir = repodir_local})
+ end}
+ if locked_repo.commit ~= lastcommit then
+ -- try checkout to the given commit
+ local ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end}
+ if not ok then
+ if global.get("network") ~= "private" then
+ -- pull the latest commit
+ local remoteurl = proxy.mirror(locked_repo.url) or locked_repo.url
+ git.pull({verbose = option.get("verbose"), remote = remoteurl, branch = locked_repo.branch, repodir = repodir_local})
+ -- re-checkout to the given commit
+ ok = try {function () git.checkout(locked_repo.commit, {verbose = option.get("verbose"), repodir = repodir_local}); return true end}
+ else
+ wprint("we cannot lock repository(%s) in private network mode!", locked_repo.url)
+ return
+ end
+ end
+ end
+ end
+
+ -- find package directory
+ local foundir
+ if ok then
+ local dir = path.join(repodir_local, "packages", packagename:sub(1, 1), packagename)
+ if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) then
+ local repo = repository.load(reponame, locked_repo.url, locked_repo.branch, false)
+ foundir = {dir, repo}
+ vprint("lock package(%s) in %s from repository(%s)/%s", packagename, dir, locked_repo.url, locked_repo.commit)
+ end
+ end
+ return foundir
+end
-- get all repositories
function repositories()
@@ -48,34 +126,66 @@ function pulled()
end
-- get package directory from repositories
-function packagedir(packagename, reponame)
+function packagedir(packagename, opt)
-- strip trailng ~tag, e.g. zlib~debug
+ opt = opt or {}
packagename = packagename:lower()
if packagename:find('~', 1, true) then
packagename = packagename:gsub("~.+$", "")
end
- -- get it from cache it
- local packagedirs = _g._PACKAGEDIRS or {}
- local foundir = packagedirs[packagename]
- if foundir then
- return foundir[1], foundir[2]
+ -- get cache key
+ local reponame = opt.name
+ local cachekey = packagename
+ local locked_repo = opt.locked_repo
+ if locked_repo then
+ cachekey = cachekey .. locked_repo.url .. (locked_repo.commit or "") .. (locked_repo.branch or "")
+ end
+ local packagedirs = _g._PACKAGEDIRS
+ if not packagedirs then
+ packagedirs = {}
+ _g._PACKAGEDIRS = packagedirs
end
- -- find the package directory from repositories
- for _, repo in ipairs(repositories()) do
- local dir = path.join(repo:directory(), "packages", packagename:sub(1, 1), packagename)
- if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) and (not reponame or reponame == repo:name()) then
- foundir = {dir, repo}
- break
+ -- get the package directory
+ local foundir = packagedirs[cachekey]
+ if not foundir then
+
+ -- find the package directory from the locked repository
+ if locked_repo then
+ local dir, repo = _get_packagedir_from_locked_repo(packagename, locked_repo)
+ if dir and repo then
+ foundir = {dir, repo}
+ end
+ end
+
+ -- find the package directory from repositories
+ if not foundir then
+ for _, repo in ipairs(repositories()) do
+ local dir = path.join(repo:directory(), "packages", packagename:sub(1, 1), packagename)
+ if os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")) and (not reponame or reponame == repo:name()) then
+ foundir = {dir, repo}
+ break
+ end
+ end
end
+ foundir = foundir or {}
+ packagedirs[cachekey] = foundir
end
- if foundir then
- packagedirs[packagename] = foundir
- _g._PACKAGEDIRS = packagedirs
- return foundir[1], foundir[2]
+
+ -- save the current commit
+ local dir = foundir[1]
+ local repo = foundir[2]
+ if repo and not repo:commit() then
+ local lastcommit = try {function()
+ if os.isdir(path.join(repo:directory(), ".git")) then
+ return git.lastcommit({repodir = repo:directory()})
+ end
+ end}
+ repo:commit_set(lastcommit)
end
+ return dir, repo
end
-- get artifacts manifest from repositories
diff --git a/xmake/modules/private/action/require/impl/search_packages.lua b/xmake/modules/private/action/require/impl/search_packages.lua
index 00cf1ffbf..276747db4 100644
--- a/xmake/modules/private/action/require/impl/search_packages.lua
+++ b/xmake/modules/private/action/require/impl/search_packages.lua
@@ -22,7 +22,7 @@
function _search_packages(name)
-- get package manager name
- local manager_name, package_name = unpack(name:split("::", {plain = true, strict = true}))
+ local manager_name, package_name = table.unpack(name:split("::", {plain = true, strict = true}))
if package_name == nil then
package_name = manager_name
manager_name = "xmake"
diff --git a/xmake/modules/private/action/require/impl/utils/requirekey.lua b/xmake/modules/private/action/require/impl/utils/requirekey.lua
new file mode 100644
index 000000000..d1792e50c
--- /dev/null
+++ b/xmake/modules/private/action/require/impl/utils/requirekey.lua
@@ -0,0 +1,60 @@
+--!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 requirekey.lua
+--
+
+-- get require key from requireinfo
+function main(requireinfo, opt)
+ opt = opt or {}
+ local key = ""
+ if opt.name then
+ key = key .. "/" .. opt.name
+ end
+ if opt.plat then
+ key = key .. "/" .. opt.plat
+ end
+ if opt.arch then
+ key = key .. "/" .. opt.arch
+ end
+ if opt.version then
+ key = key .. "/" .. opt.version
+ end
+ if requireinfo.label then
+ key = key .. "/" .. requireinfo.label
+ end
+ if key:startswith("/") then
+ key = key:sub(2)
+ end
+ local configs = requireinfo.configs
+ if configs then
+ local configs_order = {}
+ for k, v in pairs(configs) do
+ table.insert(configs_order, k .. "=" .. tostring(v))
+ end
+ table.sort(configs_order)
+ key = key .. ":" .. string.serialize(configs_order, true)
+ end
+ if opt.hash then
+ if key == "" then
+ key = "_" -- we need generate a fixed hash value
+ end
+ return hash.uuid(key):split("-", {plain = true})[1]:lower()
+ else
+ return key
+ end
+end
diff --git a/xmake/modules/private/action/require/install.lua b/xmake/modules/private/action/require/install.lua
index 821991dee..e27e627cb 100644
--- a/xmake/modules/private/action/require/install.lua
+++ b/xmake/modules/private/action/require/install.lua
@@ -76,7 +76,7 @@ function main(requires_raw)
--
-- attempt to install git from the builtin-packages first if git not found
--
- if git and not repository.pulled() then
+ if git and (not repository.pulled() or option.get("upgrade")) then
task.run("repo", {update = true})
end
diff --git a/xmake/modules/private/action/trybuild/autotools.lua b/xmake/modules/private/action/trybuild/autotools.lua
index 14434f1c5..1d4090522 100644
--- a/xmake/modules/private/action/trybuild/autotools.lua
+++ b/xmake/modules/private/action/trybuild/autotools.lua
@@ -19,7 +19,6 @@
--
-- imports
-import("core.base.cli")
import("core.base.option")
import("core.project.config")
import("core.platform.platform")
@@ -142,7 +141,7 @@ function _get_configs(artifacts_dir)
-- add extra user configs
local tryconfigs = config.get("tryconfigs")
if tryconfigs then
- for _, opt in ipairs(cli.parse(tryconfigs)) do
+ for _, opt in ipairs(os.argv(tryconfigs)) do
table.insert(configs, tostring(opt))
end
end
diff --git a/xmake/modules/private/action/trybuild/cmake.lua b/xmake/modules/private/action/trybuild/cmake.lua
index e2022b7b8..4217e98a5 100644
--- a/xmake/modules/private/action/trybuild/cmake.lua
+++ b/xmake/modules/private/action/trybuild/cmake.lua
@@ -19,7 +19,6 @@
--
-- imports
-import("core.base.cli")
import("core.base.option")
import("core.project.config")
import("core.tool.toolchain")
@@ -199,7 +198,7 @@ function _get_configs(artifacts_dir)
-- add extra user configs
local tryconfigs = config.get("tryconfigs")
if tryconfigs then
- for _, opt in ipairs(cli.parse(tryconfigs)) do
+ for _, opt in ipairs(os.argv(tryconfigs)) do
table.insert(configs, tostring(opt))
end
end
diff --git a/xmake/modules/private/action/trybuild/meson.lua b/xmake/modules/private/action/trybuild/meson.lua
index 312e24d22..f2baaff21 100644
--- a/xmake/modules/private/action/trybuild/meson.lua
+++ b/xmake/modules/private/action/trybuild/meson.lua
@@ -19,7 +19,6 @@
--
-- imports
-import("core.base.cli")
import("core.base.option")
import("core.project.config")
import("lib.detect.find_file")
@@ -47,7 +46,7 @@ function _get_configs(artifacts_dir, buildir)
-- add extra user configs
local tryconfigs = config.get("tryconfigs")
if tryconfigs then
- for _, opt in ipairs(cli.parse(tryconfigs)) do
+ for _, opt in ipairs(os.argv(tryconfigs)) do
table.insert(configs, tostring(opt))
end
end
diff --git a/xmake/modules/private/async/jobpool.lua b/xmake/modules/private/async/jobpool.lua
index 299700534..f7eef0c1b 100644
--- a/xmake/modules/private/async/jobpool.lua
+++ b/xmake/modules/private/async/jobpool.lua
@@ -35,8 +35,23 @@ function jobpool:rootjob()
return self._rootjob
end
+-- new run job
+--
+-- e.g.
+-- local job = jobpool:newjob("xxx", function (index, total) end)
+-- jobpool:add(job, rootjob1)
+-- jobpool:add(job, rootjob2)
+-- jobpool:add(job, rootjob3)
+--
+function jobpool:newjob(name, run)
+ return {name = name, run = run}
+end
+
-- add run job to the given job node
--
+-- e.g.
+-- local job = jobpool:addjob("xxx", function (index, total) end, {rootjob = rootjob})
+--
-- @param name the job name
-- @param run the run command/script
-- @param opt the options (rootjob)
diff --git a/xmake/modules/private/async/runjobs.lua b/xmake/modules/private/async/runjobs.lua
index 0361399dc..a4ea2bc10 100644
--- a/xmake/modules/private/async/runjobs.lua
+++ b/xmake/modules/private/async/runjobs.lua
@@ -20,7 +20,7 @@
-- imports
import("core.base.scheduler")
-import("private.utils.progress")
+import("utils.progress")
-- print back characters
function _print_backchars(backnum)
@@ -37,7 +37,7 @@ end
-- e.g.
-- runjobs("test", function (index) print("hello") end, {total = 100, comax = 6, timeout = 1000, on_timer = function (running_jobs_indices) end})
-- runjobs("test", function () os.sleep(10000) end, { progress = true })
--- runjobs("test", function () os.sleep(10000) end, { progress = { chars = {'/','\'} } }) -- see module private.utils.progress
+-- runjobs("test", function () os.sleep(10000) end, { progress = { chars = {'/','\'} } }) -- see module utils.progress
--
-- local jobs = jobpool.new()
-- local root = jobs:addjob("job/root", function (idx, total)
diff --git a/xmake/modules/private/tools/gcc/parse_deps.lua b/xmake/modules/private/tools/gcc/parse_deps.lua
index cb06d091c..3b682753c 100644
--- a/xmake/modules/private/tools/gcc/parse_deps.lua
+++ b/xmake/modules/private/tools/gcc/parse_deps.lua
@@ -54,9 +54,18 @@ end
-- src/tbox/libc/string/../../prefix/../config.h \
-- build/iphoneos/x86_64/release/tbox.config.h \
--
+-- with c++ modules:
+-- build/.objs/dependence/linux/x86_64/release/src/foo.mpp.o: src/foo.mpp\
+-- build/.objs/dependence/linux/x86_64/release/src/foo.mpp.o gcm.cache/foo.gcm: bar.c++m cat.c++m\
+-- foo.c++m: gcm.cache/foo.gcm\
+-- .PHONY: foo.c++m\
+-- gcm.cache/foo.gcm:| build/.objs/dependence/linux/x86_64/release/src/foo.mpp.o\
+-- CXX_IMPORTS += bar.c++m cat.c++m\
+--
function main(depsdata)
-- we assume there is only one valid line
+ local block = 0
local results = hashset.new()
local projectdir = os.projectdir()
local line = depsdata:rtrim() -- maybe there will be an empty newline at the end. so we trim it first
@@ -68,8 +77,15 @@ function main(depsdata)
if is_host("windows") and includefile:match("^%w\\:") then
includefile = includefile:replace("\\:", ":", plain)
end
- if not includefile:endswith(":") then -- ignore "xxx.o:" prefix
+ if includefile:endswith(":") then -- ignore "xxx.o:" prefix
+ block = block + 1
+ if block > 1 then
+ -- skip other `xxx.o:` block
+ break
+ end
+ else
includefile = includefile:replace(space_placeholder, ' ', plain)
+ includefile = includefile:split("\n", {plain = true})[1]
if #includefile > 0 then
includefile = _normailize_dep(includefile, projectdir)
if includefile then
diff --git a/xmake/modules/private/utils/batchcmds.lua b/xmake/modules/private/utils/batchcmds.lua
index 371735321..bb5204072 100644
--- a/xmake/modules/private/utils/batchcmds.lua
+++ b/xmake/modules/private/utils/batchcmds.lua
@@ -28,7 +28,7 @@ import("core.theme.theme")
import("core.tool.linker")
import("core.tool.compiler")
import("core.language.language")
-import("private.utils.progress", {alias = "progress_utils"})
+import("utils.progress", {alias = "progress_utils"})
-- define module
local batchcmds = batchcmds or object { _init = {"_TARGET", "_CMDS", "_DEPS", "_tip"}}
@@ -117,6 +117,14 @@ function _runcmd_mkdir(cmd, opt)
end
end
+-- run command: os.cd
+function _runcmd_cd(cmd, opt)
+ local dir = cmd.dir
+ if not opt.dryrun then
+ os.cd(dir)
+ end
+end
+
-- run command: os.rm
function _runcmd_rm(cmd, opt)
local filepath = cmd.filepath
@@ -128,21 +136,21 @@ end
-- run command: os.cp
function _runcmd_cp(cmd, opt)
if not opt.dryrun then
- os.cp(opt.srcpath, opt.dstpath, opt.opt)
+ os.cp(cmd.srcpath, cmd.dstpath, opt.opt)
end
end
-- run command: os.mv
function _runcmd_mv(cmd, opt)
if not opt.dryrun then
- os.mv(opt.srcpath, opt.dstpath, opt.opt)
+ os.mv(cmd.srcpath, cmd.dstpath, opt.opt)
end
end
-- run command: os.ln
function _runcmd_ln(cmd, opt)
if not opt.dryrun then
- os.ln(opt.srcpath, opt.dstpath, opt.opt)
+ os.ln(cmd.srcpath, cmd.dstpath, opt.opt)
end
end
@@ -158,6 +166,7 @@ function _runcmd(cmd, opt)
vrunv = _runcmd_vrunv,
execv = _runcmd_execv,
mkdir = _runcmd_mkdir,
+ cd = _runcmd_cd,
rm = _runcmd_rm,
cp = _runcmd_cp,
mv = _runcmd_mv,
@@ -268,6 +277,11 @@ function batchcmds:ln(srcpath, dstpath, opt)
table.insert(self:cmds(), {kind = "ln", srcpath = srcpath, dstpath = dstpath, opt = opt})
end
+-- add command: os.cd
+function batchcmds:cd(dir, opt)
+ table.insert(self:cmds(), {kind = "cd", dir = dir, opt = opt})
+end
+
-- add command: show
function batchcmds:show(format, ...)
local showtext = string.format(format, ...)
diff --git a/xmake/modules/private/utils/bin2c.lua b/xmake/modules/private/utils/bin2c.lua
index 91ea1eafe..6f18833fc 100644
--- a/xmake/modules/private/utils/bin2c.lua
+++ b/xmake/modules/private/utils/bin2c.lua
@@ -23,9 +23,10 @@ import("core.base.bytes")
import("core.base.option")
local options = {
- {'w', "linewidth", "kv", nil, "Set the line width"},
- {'i', "binarypath", "kv", nil, "Set the binary file path."},
- {'o', "outputpath", "kv", nil, "Set the output file path."}
+ {'w', "linewidth", "kv", nil, "Set the line width"},
+ {nil, "nozeroend", "k", false, "Disable to patch zero terminating character"},
+ {'i', "binarypath", "kv", nil, "Set the binary file path."},
+ {'o', "outputpath", "kv", nil, "Set the output file path."}
}
function _do_dump(binarydata, outputfile, opt)
@@ -84,7 +85,9 @@ function _do_bin2c(binarypath, outputpath, opt)
local binarydata = bytes(io.readfile(binarypath, {encoding = "binary"}))
local outputfile = io.open(outputpath, 'w')
if outputfile then
- binarydata = binarydata .. bytes('\0')
+ if not opt.nozeroend then
+ binarydata = binarydata .. bytes('\0')
+ end
_do_dump(binarydata, outputfile, opt)
outputfile:close()
end
diff --git a/xmake/modules/private/xrepo/action/env.lua b/xmake/modules/private/xrepo/action/env.lua
index cb6936006..bf5b2ec44 100644
--- a/xmake/modules/private/xrepo/action/env.lua
+++ b/xmake/modules/private/xrepo/action/env.lua
@@ -22,6 +22,7 @@
import("core.base.option")
import("core.base.task")
import("core.base.hashset")
+import("core.base.global")
import("core.project.config")
import("core.project.project")
import("core.tool.toolchain")
@@ -47,16 +48,29 @@ function menu_options()
{nil, "show", "k", nil, "Only show environment information." },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo env -f \"vs_runtime=MD\" zlib cmake ..",
+ " - xrepo env -f \"vs_runtime='MD'\" zlib cmake ..",
" - xrepo env -f \"regex=true,thread=true\" \"zlib,boost\" cmake .."},
- {'b', "packages", "kv", nil, "Set the packages to be bound",
+ {nil, "add", "k", nil, "Add global environment config.",
"e.g.",
+ " - xrepo env --add base.lua",
+ " - xrepo env --add myenv.lua"},
+ {nil, "remove", "k", nil, "Remove global environment config.",
+ "e.g.",
+ " - xrepo env --remove base",
+ " - xrepo env --remove myenv"},
+ {"l", "list", "k", nil, "List all global environment configs.",
+ "e.g.",
+ " - xrepo env --list"},
+ {'b', "bind", "kv", nil, "Bind the specified environment or package.",
+ "e.g.",
+ " - xrepo env -b base",
+ " - xrepo env -b myenv",
" - xrepo env -b \"python 3.x\" python",
" - xrepo env -b \"llvm 11.x\" bash",
" $ clang --version",
" - xrepo env -p android -b \"zlib,luajit 2.x\" luajit xx.lua"},
{},
- {nil, "program", "v", nil, "Set the program name to be run",
+ {nil, "program", "v", nil, "Set the program name to be run.",
"e.g.",
" - xrepo env",
" - xrepo env bash",
@@ -70,7 +84,7 @@ function menu_options()
local function show_options()
-- show usage
- cprint("${bright}Usage: $${clear cyan}xrepo env [options] [packages] [program] [arguments]")
+ cprint("${bright}Usage: $${clear cyan}xrepo env [options] [program] [arguments]")
-- show description
print("")
@@ -112,9 +126,10 @@ function _get_requires(packages)
end
-- enter project
-function _enter_project()
+function _enter_project(opt)
-- enter working project directory
+ opt = opt or {}
local workdir = path.join(os.tmpdir(), "xrepo", "working")
if not os.isdir(workdir) then
os.mkdir(workdir)
@@ -123,6 +138,10 @@ function _enter_project()
else
os.cd(workdir)
end
+ if opt.enteronly then
+ project.chdir(workdir)
+ return
+ end
-- do configure first
local config_argv = {"f", "-c"}
@@ -157,7 +176,7 @@ function _enter_project()
end
-- remove repeat environment values
-function _remove_repeat_pathenv(value)
+function _deduplicate_pathenv(value)
if value then
local itemset = {}
local results = {}
@@ -174,6 +193,23 @@ function _remove_repeat_pathenv(value)
return value
end
+-- get environment directory
+function _get_envsdir()
+ return path.join(global.directory(), "envs")
+end
+
+-- get bound environment or packages
+function _get_boundenv(opt)
+ local bind = (opt and opt.bind) or option.get("bind")
+ if bind then
+ local envfile = path.join(_get_envsdir(), bind .. ".lua")
+ if envfile and os.isfile(envfile) then
+ return envfile
+ end
+ end
+ return bind
+end
+
-- add values to environment variable
function _addenvs(envs, name, ...)
local values = {...}
@@ -208,7 +244,7 @@ function _package_addenvs(envs, instance)
end
end
else
- _addenvs(envs, name, unpack(table.wrap(values)))
+ _addenvs(envs, name, table.unpack(table.wrap(values)))
end
end
@@ -227,6 +263,13 @@ function _package_addenvs(envs, instance)
_addenvs(envs, "ACLOCAL_PATH", aclocal)
end
_addenvs(envs, "CMAKE_PREFIX_PATH", installdir)
+ if instance:is_plat("windows") then
+ _addenvs(envs, "INCLUDE", path.join(installdir, "include"))
+ _addenvs(envs, "LIBPATH", path.join(installdir, "lib"))
+ else
+ _addenvs(envs, "CPATH", path.join(installdir, "include"))
+ _addenvs(envs, "LIBRARY_PATH", path.join(installdir, "lib"))
+ end
end
end
@@ -237,36 +280,47 @@ function _toolchain_addenvs(envs)
local toolchain_inst = toolchain.load(name, toolchain_opt)
if toolchain_inst then
for k, v in pairs(toolchain_inst:runenvs()) do
- _addenvs(envs, k, unpack(path.splitenv(v)))
+ _addenvs(envs, k, table.unpack(path.splitenv(v)))
end
end
end
end
-- get package environments
-function _package_getenvs()
+function _package_getenvs(opt)
local envs = os.getenvs()
- if os.isfile(os.projectfile()) and not option.get("packages") then
+ local boundenv = _get_boundenv(opt)
+ local has_envfile = false
+ local packages = nil
+ if boundenv and os.isfile(boundenv) then
+ has_envfile = true
+ else
+ packages = boundenv or option.get("program")
+ end
+ if os.isfile(os.projectfile()) or has_envfile then
+ if not os.isfile(os.projectfile()) then
+ _enter_project({enteronly = true})
+ end
+ if has_envfile then
+ table.insert(project.rcfiles(), boundenv)
+ end
task.run("config", {target = "all"}, {disable_dump = true})
_toolchain_addenvs(envs)
local requires, requires_extra = get_requires()
for _, instance in ipairs(package.load_packages(requires, {requires_extra = requires_extra})) do
_package_addenvs(envs, instance)
end
- else
- local packages = option.get("packages") or option.get("program")
- if packages then
- _enter_project()
- packages = packages:split(',', {plain = true})
- local requires, requires_extra = _get_requires(packages)
- for _, instance in ipairs(package.load_packages(requires, {requires_extra = requires_extra})) do
- _package_addenvs(envs, instance)
- end
+ elseif packages then
+ _enter_project()
+ packages = packages:split(',', {plain = true})
+ local requires, requires_extra = _get_requires(packages)
+ for _, instance in ipairs(package.load_packages(requires, {requires_extra = requires_extra})) do
+ _package_addenvs(envs, instance)
end
end
local results = {}
for k, v in pairs(envs) do
- results[k] = _remove_repeat_pathenv(v)
+ results[k] = _deduplicate_pathenv(v)
end
return results
end
@@ -285,40 +339,66 @@ function _get_env_script(envs, shell, del)
elseif shell == "cmd" then
prefix = "@set \""
suffix = "\""
+ elseif shell:endswith("sh") then
+ if del then
+ prefix = "unset '"
+ connector = "'"
+ else
+ prefix = "export '"
+ connector = "'='"
+ suffix = "'"
+ end
end
+ local exceptions = hashset.of("_", "PS1", "PROMPT", "!;", "!EXITCODE")
local ret = ""
if del then
for name, _ in pairs(envs) do
- ret = ret .. prefix .. name .. connector .. default .. suffix .. "\n"
+ if not exceptions:has(name) then
+ ret = ret .. prefix .. name .. connector .. default .. suffix .. "\n"
+ end
end
else
for name, value in pairs(envs) do
- ret = ret .. prefix .. name .. connector .. value .. suffix .. "\n"
+ if not exceptions:has(name) then
+ ret = ret .. prefix .. name .. connector .. value .. suffix .. "\n"
+ end
end
end
return ret
end
-- get information of current virtual environment
-function info(key)
+function info(key, bnd)
if key == "prompt" then
- assert(os.isfile(os.projectfile()), "xmake.lua not found!")
- print("[%s]", path.filename(os.projectdir()))
+ local boundenv = _get_boundenv({bind = bnd})
+ if boundenv then
+ assert(os.isfile(boundenv), "environment not found!")
+ io.write("[" .. path.basename(boundenv) .. "]")
+ elseif not bnd then
+ assert(os.isfile(os.projectfile()), "xmake.lua not found!")
+ io.write("[" .. path.filename(os.projectdir()) .. "]")
+ end
elseif key == "envfile" then
print(os.tmpfile())
elseif key == "config" then
- if os.isfile(os.projectfile()) then
+ local boundenv = _get_boundenv({bind = bnd})
+ local has_envfile = (boundenv and os.isfile(boundenv)) and true or false
+ if has_envfile or os.isfile(os.projectfile()) then
+ if has_envfile then
+ _enter_project({enteronly = true})
+ table.insert(project.rcfiles(), boundenv)
+ end
task.run("config", {target = "all"}, {disable_dump = true})
end
elseif key:startswith("script.") then
local shell = key:match("script%.(.+)")
- print(_get_env_script(_package_getenvs(), shell, false))
+ io.write(_get_env_script(_package_getenvs({bind = bnd}), shell, false))
elseif key:startswith("backup.") then
local shell = key:match("backup%.(.+)")
-- remove current environment variables first
- print(_get_env_script(_package_getenvs(), shell, true))
- print(_get_env_script(os.getenvs(), shell, false))
+ io.write(_get_env_script(_package_getenvs({bind = bnd}), shell, true))
+ io.write(_get_env_script(os.getenvs(), shell, false))
end
end
@@ -350,18 +430,37 @@ end
-- main entry
function main()
- local envs = _package_getenvs()
- local program = option.get("program")
- if program and not option.get("show") then
- if envs and envs.PATH then
- os.setenv("PATH", envs.PATH)
+ if option.get("list") then
+ print("%s:", _get_envsdir())
+ local count = 0
+ for _, envfile in ipairs(os.files(path.join(_get_envsdir(), "*.lua"))) do
+ local envname = path.basename(envfile)
+ print(" - %s", envname)
+ count = count + 1
end
- if program == "shell" then
- _run_shell(envs)
- else
- os.execv(program, option.get("arguments"), {envs = envs})
+ print("envs(%d) found!", count)
+ elseif option.get("add") then
+ local envfile = assert(option.get("program"), "please set environment config file!")
+ if os.isfile(envfile) then
+ os.vcp(envfile, path.join(_get_envsdir(), path.filename(envfile)))
end
+ elseif option.get("remove") then
+ local envname = assert(option.get("program"), "please set environment config name!")
+ os.rm(path.join(_get_envsdir(), envname .. ".lua"))
else
- print(envs)
+ local envs = _package_getenvs()
+ local program = option.get("program")
+ if program and not option.get("show") then
+ if envs and envs.PATH then
+ os.setenv("PATH", envs.PATH)
+ end
+ if program == "shell" then
+ _run_shell(envs)
+ else
+ os.execv(program, option.get("arguments"), {envs = envs})
+ end
+ else
+ print(envs)
+ end
end
end
diff --git a/xmake/modules/private/xrepo/action/export.lua b/xmake/modules/private/xrepo/action/export.lua
index 4c2e8c445..e6c4b3ffc 100644
--- a/xmake/modules/private/xrepo/action/export.lua
+++ b/xmake/modules/private/xrepo/action/export.lua
@@ -39,7 +39,7 @@ function menu_options()
values = {"release", "debug"} },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo export -f \"vs_runtime=MD\" zlib",
+ " - xrepo export -f \"vs_runtime='MD'\" zlib",
" - xrepo export -f \"regex=true,thread=true\" boost"},
{},
{nil, "shallow", "k", nil, "Does not export dependent packages."},
diff --git a/xmake/modules/private/xrepo/action/fetch.lua b/xmake/modules/private/xrepo/action/fetch.lua
index a577b7c14..57e56c71b 100644
--- a/xmake/modules/private/xrepo/action/fetch.lua
+++ b/xmake/modules/private/xrepo/action/fetch.lua
@@ -38,7 +38,7 @@ function menu_options()
values = {"release", "debug"} },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo fetch --configs=\"vs_runtime=MD\" zlib",
+ " - xrepo fetch --configs=\"vs_runtime='MD'\" zlib",
" - xrepo fetch --configs=\"regex=true,thread=true\" boost"},
{},
{nil, "deps", "k", nil, "Fetch packages with dependencies." },
diff --git a/xmake/modules/private/xrepo/action/import.lua b/xmake/modules/private/xrepo/action/import.lua
index e3805135d..fb7cb15ef 100644
--- a/xmake/modules/private/xrepo/action/import.lua
+++ b/xmake/modules/private/xrepo/action/import.lua
@@ -39,7 +39,7 @@ function menu_options()
values = {"release", "debug"} },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo import -f \"vs_runtime=MD\" zlib",
+ " - xrepo import -f \"vs_runtime='MD'\" zlib",
" - xrepo import -f \"regex=true,thread=true\" boost"},
{},
{'i', "packagedir", "kv", "packages","Set the imported packages directory."},
diff --git a/xmake/modules/private/xrepo/action/info.lua b/xmake/modules/private/xrepo/action/info.lua
index 3258397cf..4d570da19 100644
--- a/xmake/modules/private/xrepo/action/info.lua
+++ b/xmake/modules/private/xrepo/action/info.lua
@@ -38,7 +38,7 @@ function menu_options()
values = {"release", "debug"} },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo fetch --configs=\"vs_runtime=MD\" zlib",
+ " - xrepo fetch --configs=\"vs_runtime='MD'\" zlib",
" - xrepo fetch --configs=\"regex=true,thread=true\" boost"},
{},
{nil, "packages", "vs", nil, "The packages list.",
diff --git a/xmake/modules/private/xrepo/action/install.lua b/xmake/modules/private/xrepo/action/install.lua
index ccd14c839..e14d6701e 100644
--- a/xmake/modules/private/xrepo/action/install.lua
+++ b/xmake/modules/private/xrepo/action/install.lua
@@ -38,9 +38,9 @@ function menu_options()
values = {"release", "debug"} },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo install -f \"vs_runtime=MD\" zlib",
+ " - xrepo install -f \"vs_runtime='MD'\" zlib",
" - xrepo install -f \"regex=true,thread=true\" boost"},
- {'j', "jobs", "kv", tostring(math.ceil(os.cpuinfo().ncpu * 3 / 2)),
+ {'j', "jobs", "kv", tostring(os.default_njob()),
"Set the number of parallel compilation jobs."},
{nil, "linkjobs", "kv", nil, "Set the number of parallel link jobs."},
{nil, "includes", "kv", nil, "Includes extra lua configuration files.",
diff --git a/xmake/modules/private/xrepo/action/remove.lua b/xmake/modules/private/xrepo/action/remove.lua
index 7624fa9cf..c9fce0831 100644
--- a/xmake/modules/private/xrepo/action/remove.lua
+++ b/xmake/modules/private/xrepo/action/remove.lua
@@ -39,7 +39,7 @@ function menu_options()
values = {"release", "debug"} },
{'f', "configs", "kv", nil, "Set the given extra package configs.",
"e.g.",
- " - xrepo remove -f \"vs_runtime=MD\" zlib",
+ " - xrepo remove -f \"vs_runtime='MD'\" zlib",
" - xrepo remove -f \"regex=true,thread=true\" boost"},
{},
{nil, "all", "k", nil, "Remove all packages and ignore extra package configs.",
diff --git a/xmake/modules/target/action/install/cmake_importfiles.lua b/xmake/modules/target/action/install/cmake_importfiles.lua
index 12d044251..1249c9c8b 100644
--- a/xmake/modules/target/action/install/cmake_importfiles.lua
+++ b/xmake/modules/target/action/install/cmake_importfiles.lua
@@ -21,18 +21,33 @@
-- imports
import("core.project.project")
+-- get the lib file of the target
+function _get_libfile(target, installdir)
+ local libfile = path.filename(target:targetfile())
+ if target:is_plat("windows") then
+ libfile = libfile:gsub("%.dll$", ".lib")
+ elseif target:is_plat("mingw") then
+ if os.isfile(path.join(installdir, "lib", libfile:gsub("%.dll$", ".dll.a"))) then
+ libfile = libfile:gsub("%.dll$", ".dll.a")
+ else
+ libfile = libfile:gsub("%.dll$", ".lib")
+ end
+ end
+ return libfile
+end
+
-- get the builtin variables
function _get_builtinvars(target, installdir)
return {TARGETNAME = target:name(),
PROJECTNAME = project.name() or target:name(),
- TARGETFILENAME = path.filename(target:targetfile()),
- TARGETKIND = target:is_shared() and "SHARED" or "STATIC",
+ TARGETFILENAME = target:targetfile() and _get_libfile(target, installdir),
+ TARGETKIND = target:is_headeronly() and "INTERFACE" or (target:is_shared() and "SHARED" or "STATIC"),
PACKAGE_VERSION = target:get("version") or "1.0.0",
TARGET_PTRBYTES = target:is_arch("x86", "i386") and "4" or "8"}
end
--- install cmake import file
-function _install_cmake_importfile(target, installdir, filename, opt)
+-- install cmake config file
+function _install_cmake_configfile(target, installdir, filename, opt)
-- get import file path
local projectname = project.name() or target:name()
@@ -48,6 +63,68 @@ function _install_cmake_importfile(target, installdir, filename, opt)
-- copy and replace builtin variables
local content = io.readfile(importfile_src)
if content then
+ content = content:split("#######################+#")[1]
+ content = content:gsub("(@(.-)@)", function(_, variable)
+ variable = variable:trim()
+ local value = builtinvars[variable]
+ return type(value) == "function" and value() or value
+ end)
+ io.writefile(importfile_dst, content)
+ end
+end
+
+-- append target to cmake config file
+function _append_cmake_configfile(target, installdir, filename, opt)
+
+ -- get import file path
+ local projectname = project.name() or target:name()
+ local importfile_src = path.join(os.programdir(), "scripts", "cmake_importfiles", filename)
+ local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", projectname)))
+
+ -- get the builtin variables
+ local builtinvars = _get_builtinvars(target, installdir)
+
+ -- generate the file if not exist / file is outdated
+ if target:is_headeronly() or not os.isfile(importfile_dst) or os.mtime(importfile_dst) < os.mtime(target:targetfile()) then
+ _install_cmake_configfile(target, installdir, filename, opt)
+ end
+
+ -- copy and replace builtin variables
+ local content = io.readfile(importfile_src)
+ local dst_content = io.readfile(importfile_dst)
+ if content then
+ content = content:split("#######################+#")[2]
+ content = content:gsub("(@(.-)@)", function(_, variable)
+ variable = variable:trim()
+ local value = builtinvars[variable]
+ return type(value) == "function" and value() or value
+ end)
+ content = content:trim()
+
+ -- check if the target already exists
+ if not dst_content:match(format("%sTargets.cmake", target:name())) then
+ io.writefile(importfile_dst, dst_content:trim() .. "\n\n" .. content .. "\n")
+ end
+ end
+end
+
+-- install cmake target file
+function _install_cmake_targetfile(target, installdir, filename, opt)
+
+ -- get import file path
+ local projectname = project.name() or target:name()
+ local importfile_src = path.join(os.programdir(), "scripts", "cmake_importfiles", filename)
+ local importfile_dst = path.join(installdir, opt and opt.libdir or "lib", "cmake", projectname, (filename:gsub("xxx", target:name())))
+
+ -- trace
+ vprint("generating %s ..", importfile_dst)
+
+ -- get the builtin variables
+ local builtinvars = _get_builtinvars(target, installdir)
+
+ -- copy and replace builtin variables
+ local content = io.readfile(importfile_src)
+ if content then
content = content:gsub("(@(.-)@)", function(_, variable)
variable = variable:trim()
local value = builtinvars[variable]
@@ -71,13 +148,15 @@ function main(target, opt)
end
-- do install
- _install_cmake_importfile(target, installdir, "xxxConfig.cmake", opt)
- _install_cmake_importfile(target, installdir, "xxxConfigVersion.cmake", opt)
- _install_cmake_importfile(target, installdir, "xxxTargets.cmake", opt)
- if is_mode("debug") then
- _install_cmake_importfile(target, installdir, "xxxTargets-debug.cmake", opt)
- else
- _install_cmake_importfile(target, installdir, "xxxTargets-release.cmake", opt)
+ _append_cmake_configfile(target, installdir, "xxxConfig.cmake", opt)
+ _install_cmake_configfile(target, installdir, "xxxConfigVersion.cmake", opt)
+ _install_cmake_targetfile(target, installdir, "xxxTargets.cmake", opt)
+ if not target:is_headeronly() then
+ if is_mode("debug") then
+ _install_cmake_targetfile(target, installdir, "xxxTargets-debug.cmake", opt)
+ else
+ _install_cmake_targetfile(target, installdir, "xxxTargets-release.cmake", opt)
+ end
end
end
diff --git a/xmake/modules/target/action/install/main.lua b/xmake/modules/target/action/install/main.lua
index 289d258f0..c115e836e 100644
--- a/xmake/modules/target/action/install/main.lua
+++ b/xmake/modules/target/action/install/main.lua
@@ -20,7 +20,6 @@
-- install files
function _install_files(target)
-
local srcfiles, dstfiles = target:installfiles()
if srcfiles and dstfiles then
local i = 1
@@ -47,12 +46,10 @@ function main(target, opt)
print("installing %s to %s ..", target:name(), installdir)
-- call script
- if not target:is_phony() then
- local install_style = target:is_plat("windows", "mingw") and "windows" or "unix"
- local script = import(install_style, {anonymous = true})["install_" .. target:kind()]
- if script then
- script(target, opt)
- end
+ local install_style = target:is_plat("windows", "mingw") and "windows" or "unix"
+ local script = import(install_style, {anonymous = true})["install_" .. target:kind()]
+ if script then
+ script(target, opt)
end
-- install other files
diff --git a/xmake/modules/target/action/install/pkgconfig_importfiles.lua b/xmake/modules/target/action/install/pkgconfig_importfiles.lua
index 1187bb5e6..979feaee2 100644
--- a/xmake/modules/target/action/install/pkgconfig_importfiles.lua
+++ b/xmake/modules/target/action/install/pkgconfig_importfiles.lua
@@ -24,10 +24,8 @@ function main(target, opt)
-- check
opt = opt or {}
assert(target:is_library(), 'pkgconfig_importfiles: only support for library target(%s)!', target:name())
-
- -- only for unix platform
local installdir = target:installdir()
- if target:is_plat("windows") or not installdir then
+ if not installdir then
return
end
@@ -35,26 +33,32 @@ function main(target, opt)
local pcfile = path.join(installdir, opt and opt.libdir or "lib", "pkgconfig", opt.filename or (target:basename() .. ".pc"))
-- get includedirs
- local includedirs = opt.includedirs or {path.join(installdir, "include")}
+ local includedirs = opt.includedirs
-- get links and linkdirs
local links = opt.links or target:basename()
- local linkdirs = opt.linkdirs or {path.join(installdir, "lib")}
+ local linkdirs = opt.linkdirs
-- get libs
local libs = ""
for _, linkdir in ipairs(linkdirs) do
- libs = libs .. "-L" .. linkdir
+ if linkdir ~= path.join(installdir, "lib") then
+ libs = libs .. " -L" .. (linkdir:gsub("\\", "/"))
+ end
end
libs = libs .. " -L${libdir}"
- for _, link in ipairs(links) do
- libs = libs .. " -l" .. link
+ if not target:is_headeronly() then
+ for _, link in ipairs(links) do
+ libs = libs .. " -l" .. link
+ end
end
-- get cflags
local cflags = ""
for _, includedir in ipairs(includedirs) do
- cflags = cflags .. "-I" .. includedir
+ if includedir ~= path.join(installdir, "include") then
+ cflags = cflags .. " -I" .. (includedir:gsub("\\", "/"))
+ end
end
cflags = cflags .. " -I${includedir}"
@@ -64,7 +68,7 @@ function main(target, opt)
-- generate a *.pc file
local file = io.open(pcfile, 'w')
if file then
- file:print("prefix=%s", installdir)
+ file:print("prefix=%s", installdir:gsub("\\", "/"))
file:print("exec_prefix=${prefix}")
file:print("libdir=${exec_prefix}/lib")
file:print("includedir=${prefix}/include")
@@ -76,7 +80,6 @@ function main(target, opt)
file:print("Version: %s", version)
end
file:print("Libs: %s", libs)
- file:print("Libs.private: ")
file:print("Cflags: %s", cflags)
file:close()
end
diff --git a/xmake/modules/target/action/install/unix.lua b/xmake/modules/target/action/install/unix.lua
index d4311aeea..af641e5bc 100644
--- a/xmake/modules/target/action/install/unix.lua
+++ b/xmake/modules/target/action/install/unix.lua
@@ -18,15 +18,8 @@
-- @file unix.lua
--
--- install library
-function _install_library(target, opt)
-
- -- install libraries
- local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
- os.mkdir(librarydir)
- os.vcp(target:targetfile(), librarydir)
-
- -- install headers
+-- install headers
+function _install_headers(target, opt)
local includedir = path.join(target:installdir(), opt and opt.includedir or "include")
os.mkdir(includedir)
local srcheaders, dstheaders = target:headerfiles(includedir)
@@ -42,19 +35,99 @@ function _install_library(target, opt)
end
end
+-- install shared libraries for package
+function _install_shared_for_package(target, pkg, outputdir)
+ _g.installed_libfiles = _g.installed_libfiles or {}
+ for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do
+ if sopath:endswith(".so") or sopath:match(".+%.so%..+$") or sopath:endswith(".dylib") then
+ -- prevent packages using the same system libfiles from overwriting each other
+ if not _g.installed_libfiles[sopath] then
+ local soname = path.filename(sopath)
+ local targetname = path.join(outputdir, soname)
+ if os.isfile(targetname) then
+ wprint("'%s' already exists in install dir, overwriting it from package(%s).", soname, pkg:name())
+ -- rm because symlink cannot overwrite existing file
+ os.rm(targetname)
+ end
+ -- we need reserve symlink
+ -- @see https://github.com/xmake-io/xmake/issues/1582
+ os.vcp(sopath, outputdir, {symlink = true})
+ _g.installed_libfiles[sopath] = true
+ end
+ end
+ end
+end
+
+-- install shared libraries for packages
+function _install_shared_for_packages(target, outputdir)
+ _g.installed_packages = _g.installed_packages or {}
+ for _, pkg in ipairs(target:orderpkgs()) do
+ if not _g.installed_packages[pkg:name()] then
+ if pkg:enabled() and pkg:get("libfiles") then
+ _install_shared_for_package(target, pkg, outputdir)
+ end
+ _g.installed_packages[pkg:name()] = true
+ end
+ end
+end
+
-- install binary
function install_binary(target, opt)
+
+ -- install binary
local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin")
os.mkdir(binarydir)
os.vcp(target:targetfile(), binarydir)
+
+ -- install libraries
+ local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
+ os.mkdir(librarydir)
+
+ -- install the dependent shared (*.so) target
+ -- @see https://github.com/xmake-io/xmake/issues/961
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:kind() == "shared" then
+ local depfile = dep:targetfile()
+ if os.isfile(depfile) then
+ os.vcp(depfile, librarydir)
+ end
+ end
+ -- install all shared libraries in packages in all deps
+ _install_shared_for_packages(dep, librarydir)
+ end
+
+ -- install shared libraries for all packages
+ _install_shared_for_packages(target, librarydir)
end
-- install shared library
function install_shared(target, opt)
- _install_library(target, opt)
+
+ -- install libraries
+ local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
+ os.mkdir(librarydir)
+ os.vcp(target:targetfile(), librarydir)
+
+ -- install shared libraries for all packages
+ _install_shared_for_packages(target, librarydir)
+
+ -- install headers
+ _install_headers(target, opt)
end
-- install static library
function install_static(target, opt)
- _install_library(target, opt)
+
+ -- install libraries
+ local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
+ os.mkdir(librarydir)
+ os.vcp(target:targetfile(), librarydir)
+
+ -- install headers
+ _install_headers(target, opt)
+end
+
+-- install headeronly library
+function install_headeronly(target, opt)
+ _install_headers(target, opt)
end
diff --git a/xmake/modules/target/action/install/windows.lua b/xmake/modules/target/action/install/windows.lua
index 73e8f5ee3..dfbcad11f 100644
--- a/xmake/modules/target/action/install/windows.lua
+++ b/xmake/modules/target/action/install/windows.lua
@@ -40,12 +40,18 @@ end
-- install shared libraries for package
function _install_shared_for_package(target, pkg, outputdir)
+ _g.installed_dllfiles = _g.installed_dllfiles or {}
for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do
if dllpath:endswith(".dll") then
- if os.isfile(path.join(outputdir, dllname)) then
- wprint("'%s' already exists in install dir, overwriting it from package(%s).", dllname, pkg:name())
+ -- prevent packages using the same libfiles from overwriting each other
+ if not _g.installed_dllfiles[dllpath] then
+ local dllname = path.filename(dllpath)
+ if os.isfile(path.join(outputdir, dllname)) then
+ wprint("'%s' already exists in install dir, overwriting it from package(%s).", dllname, pkg:name())
+ end
+ os.vcp(dllpath, outputdir)
+ _g.installed_dllfiles[dllpath] = true
end
- os.vcp(dllpath, outputdir)
end
end
end
@@ -70,14 +76,19 @@ function install_binary(target, opt)
local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin")
os.mkdir(binarydir)
os.vcp(target:targetfile(), binarydir)
+ os.trycp(target:symbolfile(), binarydir)
-- install the dependent shared/windows (*.dll) target
-- @see https://github.com/xmake-io/xmake/issues/961
+ _g.installed_dllfiles = _g.installed_dllfiles or {}
for _, dep in ipairs(target:orderdeps()) do
if dep:kind() == "shared" then
local depfile = dep:targetfile()
if os.isfile(depfile) then
- os.vcp(depfile, binarydir)
+ if not _g.installed_dllfiles[depfile] then
+ os.vcp(depfile, binarydir)
+ _g.installed_dllfiles[depfile] = true
+ end
end
end
-- install all shared libraries in packages in all deps
@@ -95,12 +106,13 @@ function install_shared(target, opt)
local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin")
os.mkdir(binarydir)
os.vcp(target:targetfile(), binarydir)
+ os.trycp(target:symbolfile(), binarydir)
-- install *.lib for shared/windows (*.dll) target
-- @see https://github.com/xmake-io/xmake/issues/714
local targetfile = target:targetfile()
local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
- local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib")
+ local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib"))
if os.isfile(targetfile_lib) then
os.mkdir(librarydir)
os.vcp(targetfile_lib, librarydir)
@@ -120,7 +132,13 @@ function install_static(target, opt)
local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
os.mkdir(librarydir)
os.vcp(target:targetfile(), librarydir)
+ os.trycp(target:symbolfile(), librarydir)
-- install headers
_install_headers(target, opt)
end
+
+-- install headeronly
+function install_headeronly(target, opt)
+ _install_headers(target, opt)
+end
diff --git a/xmake/modules/target/action/uninstall/unix.lua b/xmake/modules/target/action/uninstall/unix.lua
index b582aecf6..e11446dd4 100644
--- a/xmake/modules/target/action/uninstall/unix.lua
+++ b/xmake/modules/target/action/uninstall/unix.lua
@@ -18,14 +18,8 @@
-- @file unix.lua
--
--- uninstall library
-function _uninstall_library(target, opt)
-
- -- remove the target file
- local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
- os.vrm(path.join(librarydir, path.filename(target:targetfile())))
-
- -- remove headers from the include directory
+-- uninstall headers
+function _uninstall_headers(target, opt)
local includedir = path.join(target:installdir(), opt and opt.includedir or "include")
local _, dstheaders = target:headerfiles(includedir)
for _, dstheader in ipairs(dstheaders) do
@@ -33,18 +27,76 @@ function _uninstall_library(target, opt)
end
end
+-- uninstall shared libraries for package
+function _uninstall_shared_for_package(target, pkg, outputdir)
+ for _, sopath in ipairs(table.wrap(pkg:get("libfiles"))) do
+ if sopath:endswith(".so") or sopath:endswith(".dylib") then
+ local soname = path.filename(sopath)
+ os.vrm(path.join(outputdir, soname))
+ end
+ end
+end
+
+-- uninstall shared libraries for packages
+function _uninstall_shared_for_packages(target, outputdir)
+ _g.uninstalled_packages = _g.uninstalled_packages or {}
+ for _, pkg in ipairs(target:orderpkgs()) do
+ if not _g.uninstalled_packages[pkg:name()] then
+ if pkg:enabled() and pkg:get("libfiles") then
+ _uninstall_shared_for_package(target, pkg, outputdir)
+ end
+ _g.uninstalled_packages[pkg:name()] = true
+ end
+ end
+end
+
-- uninstall binary
function uninstall_binary(target, opt)
+
+ -- remove the target file
local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin")
os.vrm(path.join(binarydir, path.filename(target:targetfile())))
+
+ -- remove the dependent shared (*.so) target
+ -- @see https://github.com/xmake-io/xmake/issues/961
+ local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
+ for _, dep in ipairs(target:orderdeps()) do
+ if dep:kind() == "shared" then
+ os.vrm(path.join(librarydir, path.filename(dep:targetfile())))
+ end
+ _uninstall_shared_for_packages(dep, librarydir)
+ end
+
+ -- uninstall shared libraries for packages
+ _uninstall_shared_for_packages(target, librarydir)
end
-- uninstall shared library
function uninstall_shared(target, opt)
- _uninstall_library(target, opt)
+
+ -- remove the target file
+ local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
+ os.vrm(path.join(librarydir, path.filename(target:targetfile())))
+
+ -- remove headers from the include directory
+ _uninstall_headers(target, opt)
+
+ -- uninstall shared libraries for packages
+ _uninstall_shared_for_packages(target, librarydir)
end
-- uninstall static library
function uninstall_static(target, opt)
- _uninstall_library(target, opt)
+
+ -- remove the target file
+ local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
+ os.vrm(path.join(librarydir, path.filename(target:targetfile())))
+
+ -- remove headers from the include directory
+ _uninstall_headers(target, opt)
+end
+
+-- uninstall headeronly library
+function uninstall_headeronly(target, opt)
+ _uninstall_headers(target, opt)
end
diff --git a/xmake/modules/target/action/uninstall/windows.lua b/xmake/modules/target/action/uninstall/windows.lua
index f45028303..ed6923567 100644
--- a/xmake/modules/target/action/uninstall/windows.lua
+++ b/xmake/modules/target/action/uninstall/windows.lua
@@ -31,6 +31,7 @@ end
function _uninstall_shared_for_package(target, pkg, outputdir)
for _, dllpath in ipairs(table.wrap(pkg:get("libfiles"))) do
if dllpath:endswith(".dll") then
+ local dllname = path.filename(dllpath)
os.vrm(path.join(outputdir, dllname))
end
end
@@ -55,6 +56,7 @@ function uninstall_binary(target, opt)
-- remove the target file
local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin")
os.vrm(path.join(binarydir, path.filename(target:targetfile())))
+ os.tryrm(path.join(binarydir, path.filename(target:symbolfile())))
-- remove the dependent shared/windows (*.dll) target
-- @see https://github.com/xmake-io/xmake/issues/961
@@ -75,12 +77,13 @@ function uninstall_shared(target, opt)
-- remove the target file
local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin")
os.vrm(path.join(binarydir, path.filename(target:targetfile())))
+ os.tryrm(path.join(binarydir, path.filename(target:symbolfile())))
-- remove *.lib for shared/windows (*.dll) target
-- @see https://github.com/xmake-io/xmake/issues/714
local targetfile = target:targetfile()
local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
- os.vrm(path.join(librarydir, path.basename(targetfile) .. ".lib"))
+ os.vrm(path.join(librarydir, path.basename(targetfile) .. (target:is_plat("mingw") and ".dll.a" or ".lib")))
-- remove headers from the include directory
_uninstall_headers(target, opt)
@@ -95,7 +98,13 @@ function uninstall_static(target, opt)
-- remove the target file
local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib")
os.vrm(path.join(librarydir, path.filename(target:targetfile())))
+ os.tryrm(path.join(librarydir, path.filename(target:symbolfile())))
-- remove headers from the include directory
_uninstall_headers(target, opt)
end
+
+-- uninstall headeronly library
+function uninstall_headeronly(target, opt)
+ _uninstall_headers(target, opt)
+end
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/private/utils/progress.lua b/xmake/modules/utils/progress.lua
index 5c08cbf8f..074046a69 100644
--- a/xmake/modules/private/utils/progress.lua
+++ b/xmake/modules/utils/progress.lua
@@ -75,6 +75,7 @@ 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, ...)
@@ -113,6 +114,7 @@ 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, ...)