summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-08-19 22:21:53 +0800
committerGitHub <[email protected]>2021-08-19 22:21:53 +0800
commit9c096fc45a4fb8ac817eb48ab8e762e2b41ab259 (patch)
treebebf40a98ed31b8b7b94231976a26637614b80a1
parent69da74c43e934650eb797ec51f6b7c91fd419642 (diff)
parent0eac4a64692796d99a1a30f206a2d21463e0acf6 (diff)
Merge pull request #1587 from xmake-io/requireslock
Support xmake-requires.lock to lock all required packages
-rw-r--r--core/src/xmake/semver/select.c8
-rwxr-xr-xtests/modules/semver/test.lua8
-rw-r--r--tests/projects/package/multiconfig/xmake-requires.lock41
-rw-r--r--tests/projects/package/multiconfig/xmake.lua1
-rw-r--r--tests/projects/package/toolchain_muslcc/xmake-requires.lock149
-rw-r--r--tests/projects/package/toolchain_muslcc/xmake.lua3
-rw-r--r--xmake/actions/require/main.lua2
-rw-r--r--xmake/actions/require/xmake.lua1
-rw-r--r--xmake/core/base/serialize.lua3
-rw-r--r--xmake/core/base/table.lua15
-rw-r--r--xmake/core/package/package.lua49
-rw-r--r--xmake/core/project/policy.lua4
-rw-r--r--xmake/core/project/project.lua10
-rw-r--r--xmake/core/sandbox/modules/import/core/base/semver.lua2
-rw-r--r--xmake/core/sandbox/modules/import/core/package/repository.lua19
-rw-r--r--xmake/core/sandbox/modules/import/core/project/project.lua64
-rw-r--r--xmake/modules/devel/git/lastcommit.lua77
-rw-r--r--xmake/modules/private/action/require/impl/install_packages.lua6
-rw-r--r--xmake/modules/private/action/require/impl/lock_packages.lua64
-rw-r--r--xmake/modules/private/action/require/impl/package.lua101
-rw-r--r--xmake/modules/private/action/require/impl/repository.lua109
-rw-r--r--xmake/modules/private/action/require/impl/utils/requirekey.lua57
-rw-r--r--xmake/modules/private/action/require/install.lua2
23 files changed, 667 insertions, 128 deletions
diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c
index 221baf46d..395dc6f37 100644
--- a/core/src/xmake/semver/select.c
+++ b/core/src/xmake/semver/select.c
@@ -68,7 +68,7 @@ static tb_bool_t xm_semver_select_from_versions_tags1(lua_State* lua, tb_int_t f
lua_pushstring(lua, top.raw);
lua_setfield(lua, -2, "version");
- lua_pushstring(lua, fromidx == 2? "versions" : "tags");
+ lua_pushstring(lua, fromidx == 2? "version" : "tag");
lua_setfield(lua, -2, "source");
// exit the popped semver
@@ -92,7 +92,7 @@ static tb_bool_t xm_semver_select_from_versions_tags2(lua_State* lua, tb_int_t f
lua_createtable(lua, 0, 2);
lua_pushstring(lua, source_str);
lua_setfield(lua, -2, "version");
- lua_pushstring(lua, fromidx == 2? "versions" : "tags");
+ lua_pushstring(lua, fromidx == 2? "version" : "tag");
lua_setfield(lua, -2, "source");
return tb_true;
}
@@ -119,7 +119,7 @@ static tb_bool_t xm_semver_select_from_branches(lua_State* lua, tb_int_t fromidx
lua_pushlstring(lua, source_str, source_len);
lua_setfield(lua, -2, "version");
- lua_pushstring(lua, "branches");
+ lua_pushstring(lua, "branch");
lua_setfield(lua, -2, "source");
// ok
@@ -162,7 +162,7 @@ static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State* lua, tb_i
lua_pushstring(lua, top.raw);
lua_setfield(lua, -2, "version");
- lua_pushstring(lua, fromidx == 2? "versions" : "tags");
+ lua_pushstring(lua, fromidx == 2? "version" : "tag");
lua_setfield(lua, -2, "source");
// exit the popped semver
diff --git a/tests/modules/semver/test.lua b/tests/modules/semver/test.lua
index f39f3acde..5141f099c 100755
--- a/tests/modules/semver/test.lua
+++ b/tests/modules/semver/test.lua
@@ -10,21 +10,21 @@ end
-- test select version
function test_semver_select(t)
- _check_semver_select(t, {"1.5.1", "versions"}
+ _check_semver_select(t, {"1.5.1", "version"}
, ">=1.5.0 <1.6.0"
, {"1.4.0", "1.5.0", "1.5.1"})
- _check_semver_select(t, {"1.5.1", "versions"}
+ _check_semver_select(t, {"1.5.1", "version"}
, "^1.5.0"
,{"1.4.0", "1.5.0", "1.5.1"})
- _check_semver_select(t, {"master", "branches"}
+ _check_semver_select(t, {"master", "branch"}
, "master"
, {"1.4.0", "1.5.0", "1.5.1"}
, {"v1.2.0", "v1.6.0"}
, {"master", "dev"})
- _check_semver_select(t, {"1.5.1", "versions"}
+ _check_semver_select(t, {"1.5.1", "version"}
, "latest"
, {"1.4.0", "1.5.0", "1.5.1"})
end
diff --git a/tests/projects/package/multiconfig/xmake-requires.lock b/tests/projects/package/multiconfig/xmake-requires.lock
new file mode 100644
index 000000000..e8621f5b3
--- /dev/null
+++ b/tests/projects/package/multiconfig/xmake-requires.lock
@@ -0,0 +1,41 @@
+{
+ __meta__ = {
+ version = "1.0"
+ },
+ ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "b76a297309d14c09b42cfe3927260a51",
+ name = "zlib",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "1.2.11"
+ },
+ ["zlib~debug#d72a8a937b694e449bce540c8eb65a8a"] = {
+ arch = "x86_64",
+ buildhash = "e6a6fa6a86ad4fc7ae3c2cf7c60cc084",
+ name = "zlib",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "1.2.11"
+ },
+ ["zlib~shared#b286744a1898416faad2e5cab0104b2f"] = {
+ arch = "x86_64",
+ buildhash = "8e5b898b0f344715bac89cc6a1577506",
+ name = "zlib",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "df6cad5cf5701de3705c7afce54d732e1f5b14b9",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "1.2.11"
+ }
+} \ No newline at end of file
diff --git a/tests/projects/package/multiconfig/xmake.lua b/tests/projects/package/multiconfig/xmake.lua
index 09121e8d2..7aa2bdffb 100644
--- a/tests/projects/package/multiconfig/xmake.lua
+++ b/tests/projects/package/multiconfig/xmake.lua
@@ -2,6 +2,7 @@ add_requires("zlib", {system = false})
add_requires("zlib", {system = false}) -- test repeat requires
add_requires("zlib~debug", {system = false, debug = true})
add_requires("zlib~shared", {system = false, configs = {shared = true}, alias = "zlib_shared"})
+set_policy("package.requires_lock", true)
target("test1")
set_kind("binary")
diff --git a/tests/projects/package/toolchain_muslcc/xmake-requires.lock b/tests/projects/package/toolchain_muslcc/xmake-requires.lock
new file mode 100644
index 000000000..9509b8501
--- /dev/null
+++ b/tests/projects/package/toolchain_muslcc/xmake-requires.lock
@@ -0,0 +1,149 @@
+{
+ __meta__ = {
+ version = "1.0"
+ },
+ ["autoconf#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "01974c48f52d4d658f58852351743754",
+ name = "autoconf",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "2.69"
+ },
+ ["automake#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "7a090c93706241f983f0d821a162e8a5",
+ name = "automake",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "1.16.1"
+ },
+ ["cmake#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "a6d18f8c0bf347d980f8bb762583c91a",
+ name = "cmake",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "3.21.0"
+ },
+ ["gmp#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "7dd9c224447e46698ac73d29f58b1d73",
+ name = "gmp",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "6.2.1"
+ },
+ ["libisl 0.22#3dd996fa365042e39791030c4e1cad52"] = {
+ arch = "x86_64",
+ buildhash = "f649e1fb365e442e8f79f372fd91483b",
+ name = "libisl",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "0.22"
+ },
+ ["libogg#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "arm",
+ buildhash = "d894fc29f2fb4c45a0f48bc2c6ece273",
+ name = "libogg",
+ plat = "cross",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "v1.3.4"
+ },
+ ["libplist#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "arm",
+ buildhash = "0c01b22920be4876b1de74629194eb8f",
+ name = "libplist",
+ plat = "cross",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "2.2.0"
+ },
+ ["libtool#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "64584ec84a4743ecb740b598b263ffa6",
+ name = "libtool",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "2.4.6"
+ },
+ ["m4#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "fd0e83e5759b442a970327ebb1c89793",
+ name = "m4",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "1.4.19"
+ },
+ ["muslcc#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "11062c09ebeb484594488ad73ddbcd1f",
+ name = "muslcc",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "20210202"
+ },
+ ["pkg-config#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "x86_64",
+ buildhash = "84fd7f9b9f7a47709512cfc85cd9e5f7",
+ name = "pkg-config",
+ plat = "macosx",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "0.29.2"
+ },
+ ["zlib#ddbdd8b8f76d455a8c0ef45fffe37160"] = {
+ arch = "arm",
+ buildhash = "be90a245b8bb48e6b08a1a15bdcad467",
+ name = "zlib",
+ plat = "cross",
+ repo = {
+ branch = "master",
+ commit = "e87effa464611cecf28dfced70cbe491a08fe99d",
+ url = "https://gitee.com/tboox/xmake-repo.git"
+ },
+ version = "1.2.11"
+ }
+} \ No newline at end of file
diff --git a/tests/projects/package/toolchain_muslcc/xmake.lua b/tests/projects/package/toolchain_muslcc/xmake.lua
index bf5e98e8c..b111d5976 100644
--- a/tests/projects/package/toolchain_muslcc/xmake.lua
+++ b/tests/projects/package/toolchain_muslcc/xmake.lua
@@ -4,6 +4,9 @@ add_rules("mode.debug", "mode.release")
set_plat("cross")
set_arch("arm")
+-- lock requires
+set_policy("package.requires_lock", true)
+
-- add library packages
-- for testing zlib/xmake, libplist/autoconf, libogg/cmake
add_requires("zlib", "libogg", {system = false})
diff --git a/xmake/actions/require/main.lua b/xmake/actions/require/main.lua
index eb0e2014e..41b9a7eac 100644
--- a/xmake/actions/require/main.lua
+++ b/xmake/actions/require/main.lua
@@ -118,7 +118,7 @@ function main()
scan(option.get("requires"))
- -- install and update all outdated package dependencies by default if no arguments
+ -- install and upgrade all outdated package dependencies by default if no arguments
else
install(option.get("requires"))
end
diff --git a/xmake/actions/require/xmake.lua b/xmake/actions/require/xmake.lua
index a9d4db32c..f33188f77 100644
--- a/xmake/actions/require/xmake.lua
+++ b/xmake/actions/require/xmake.lua
@@ -72,6 +72,7 @@ task("require")
, {'s', "search", "k", nil, "Search for the given packages from repositories.",
"e.g.",
" $ xmake require --search tbox" }
+ , {nil, "upgrade", "k", nil, "Upgrade the installed packages." }
, {nil, "uninstall", "k", nil, "Uninstall the installed packages.",
"e.g.",
" $ xmake require --uninstall",
diff --git a/xmake/core/base/serialize.lua b/xmake/core/base/serialize.lua
index 99486bf8c..a2d7b9ff9 100644
--- a/xmake/core/base/serialize.lua
+++ b/xmake/core/base/serialize.lua
@@ -123,7 +123,8 @@ function serialize._maketable(obj, opt, level, pathsegs, reftab)
local sformat = opt.indentstr and "[%q] = %s" or "[%q]=%s"
local nformat = opt.indentstr and "[%s] = %s" or "[%s]=%s"
local keywords = serialize._keywords()
- for k, v in pairs(serialized) do
+ local makepairs = opt.orderkeys and table.orderpairs or pairs
+ for k, v in makepairs(serialized) do
local format
-- serialize key
if type(k) == "string" then
diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua
index c86a90988..01a6a4692 100644
--- a/xmake/core/base/table.lua
+++ b/xmake/core/base/table.lua
@@ -317,6 +317,21 @@ function table.orderkeys(tab)
return keys
end
+-- order key/value iterator
+--
+-- for k, v in table.orderpairs(t) do
+-- TODO
+-- end
+function table.orderpairs(t)
+ local orderkeys = table.orderkeys(t)
+ local i = 1
+ return function (t, k)
+ k = orderkeys[i]
+ i = i + 1
+ return k, t[k]
+ end, t, nil
+end
+
-- get values of a table
function table.values(tab)
diff --git a/xmake/core/package/package.lua b/xmake/core/package/package.lua
index fefa4eb17..f7b2b7884 100644
--- a/xmake/core/package/package.lua
+++ b/xmake/core/package/package.lua
@@ -115,10 +115,10 @@ function _instance:plat()
return os.subhost()
end
local requireinfo = self:requireinfo()
- if not plat and requireinfo and requireinfo.plat then
+ if requireinfo and requireinfo.plat then
return requireinfo.plat
end
- return self:get("plat") or package._target_plat()
+ return package._target_plat()
end
-- get the architecture of package
@@ -145,7 +145,7 @@ function _instance:targetarch()
if requireinfo and requireinfo.arch then
return requireinfo.arch
end
- return self:get("arch") or package._target_arch()
+ return package._target_arch()
end
-- get the build mode
@@ -855,22 +855,7 @@ function _instance:version_str()
return self._VERSION_STR
end
--- get branch version
-function _instance:branch()
- return self._BRANCH
-end
-
--- get tag version
-function _instance:tag()
- return self._TAG
-end
-
--- is git ref?
-function _instance:gitref()
- return self:branch() or self:tag()
-end
-
--- set the version, source: branches, tags, versions
+-- set the version, source: branch, tag, version
function _instance:version_set(version, source)
-- save the semver version
@@ -880,17 +865,31 @@ function _instance:version_set(version, source)
end
-- save branch and tag
- if source == "branches" then
+ if source == "branch" then
self._BRANCH = version
- elseif source == "tags" then
+ elseif source == "tag" then
self._TAG = version
end
- -- save source and version string
- self._SOURCE = source
+ -- save version string
self._VERSION_STR = version
end
+-- get branch version
+function _instance:branch()
+ return self._BRANCH
+end
+
+-- get tag version
+function _instance:tag()
+ return self._TAG
+end
+
+-- is git ref?
+function _instance:gitref()
+ return self:branch() or self:tag()
+end
+
-- get the require info
function _instance:requireinfo()
return self._REQUIREINFO
@@ -1703,8 +1702,8 @@ function package.apis()
-- package.set_xxx
"package.set_urls"
, "package.set_kind"
- , "package.set_plat"
- , "package.set_arch"
+ , "package.set_plat" -- deprecated
+ , "package.set_arch" -- deprecated
, "package.set_license"
, "package.set_homepage"
, "package.set_description"
diff --git a/xmake/core/project/policy.lua b/xmake/core/project/policy.lua
index 7040182a2..c624aed96 100644
--- a/xmake/core/project/policy.lua
+++ b/xmake/core/project/policy.lua
@@ -44,7 +44,9 @@ function policy.policies()
-- we can compile the source files for each target in parallel
["build.across_targets_in_parallel"] = {description = "Enable compile the source files for each target in parallel.", default = true, type = "boolean"},
-- we need enable longpaths when building target or installing package
- ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"}
+ ["platform.longpaths"] = {description = "Enable long paths when building target or installing package on windows.", default = false, type = "boolean"},
+ -- lock required packages
+ ["package.requires_lock"] = {description = "Enable xmake-requires.lock to lock required packages.", default = false, type = "boolean"}
}
policy._POLICIES = policies
end
diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua
index fafc254bf..91982e64a 100644
--- a/xmake/core/project/project.lua
+++ b/xmake/core/project/project.lua
@@ -1023,6 +1023,16 @@ function project.requireconfs_str()
return requireconfs_str, requireconfs_extra
end
+-- get requires lockfile
+function project.requireslock()
+ return path.join(project.directory(), "xmake-requires.lock")
+end
+
+-- get the format version of requires lockfile
+function project.requireslock_version()
+ return "1.0"
+end
+
-- get the given rule
function project.rule(name)
return project.rules()[name]
diff --git a/xmake/core/sandbox/modules/import/core/base/semver.lua b/xmake/core/sandbox/modules/import/core/base/semver.lua
index edaf61470..eadcfb702 100644
--- a/xmake/core/sandbox/modules/import/core/base/semver.lua
+++ b/xmake/core/sandbox/modules/import/core/base/semver.lua
@@ -80,7 +80,7 @@ end
-- local version, source = semver.select(">=1.5.0 <1.6", {"1.5.0", "1.5.1"}, {"v1.5.0", ..}, {"master", "dev"})
--
-- @version the selected version number
--- @source the version source, e.g. versions, tags, branchs
+-- @source the version source, e.g. version, tag, branch
--
function sandbox_core_base_semver.select(range, versions, tags, branches)
local verinfo, errors = semver.select(range, table.wrap(versions), table.wrap(tags), table.wrap(branches))
diff --git a/xmake/core/sandbox/modules/import/core/package/repository.lua b/xmake/core/sandbox/modules/import/core/package/repository.lua
index 4dc00a0ed..5d8406094 100644
--- a/xmake/core/sandbox/modules/import/core/package/repository.lua
+++ b/xmake/core/sandbox/modules/import/core/package/repository.lua
@@ -29,20 +29,13 @@ local repository = require("package/repository")
local raise = require("sandbox/modules/raise")
local import = require("sandbox/modules/import")
--- get repository directory
-function sandbox_core_package_repository.directory(is_global)
- return repository.directory(is_global)
-end
-
--- get repository url from the given name
-function sandbox_core_package_repository.get(name, is_global)
- return repository.get(name, is_global)
-end
+-- inherit some builtin interfaces
+sandbox_core_package_repository.directory = repository.directory
+sandbox_core_package_repository.get = repository.get
+sandbox_core_package_repository.load = repository.load
-- add repository url to the given name
function sandbox_core_package_repository.add(name, url, branch, is_global)
-
- -- add it
local ok, errors = repository.add(name, url, branch, is_global)
if not ok then
raise(errors)
@@ -51,8 +44,6 @@ end
-- remove repository from gobal or local directory
function sandbox_core_package_repository.remove(name, is_global)
-
- -- remove it
local ok, errors = repository.remove(name, is_global)
if not ok then
raise(errors)
@@ -61,8 +52,6 @@ end
-- clear all repositories from global or local directory
function sandbox_core_package_repository.clear(is_global)
-
- -- clear all repositories
local ok, errors = repository.clear(is_global)
if not ok then
raise(errors)
diff --git a/xmake/core/sandbox/modules/import/core/project/project.lua b/xmake/core/sandbox/modules/import/core/project/project.lua
index 694532527..34b5fa7ac 100644
--- a/xmake/core/sandbox/modules/import/core/project/project.lua
+++ b/xmake/core/sandbox/modules/import/core/project/project.lua
@@ -36,37 +36,39 @@ local package = require("package/package")
local import = require("sandbox/modules/import")
-- export some readonly interfaces
-sandbox_core_project.get = project.get
-sandbox_core_project.extraconf = project.extraconf
-sandbox_core_project.rule = project.rule
-sandbox_core_project.rules = project.rules
-sandbox_core_project.toolchain = project.toolchain
-sandbox_core_project.toolchains = project.toolchains
-sandbox_core_project.target = project.target
-sandbox_core_project.targets = project.targets
-sandbox_core_project.ordertargets = project.ordertargets
-sandbox_core_project.option = project.option
-sandbox_core_project.options = project.options
-sandbox_core_project.rootfile = project.rootfile
-sandbox_core_project.allfiles = project.allfiles
-sandbox_core_project.rcfiles = project.rcfiles
-sandbox_core_project.directory = project.directory
-sandbox_core_project.name = project.name
-sandbox_core_project.modes = project.modes
-sandbox_core_project.default_arch = project.default_arch
-sandbox_core_project.allowed_modes = project.allowed_modes
-sandbox_core_project.allowed_plats = project.allowed_plats
-sandbox_core_project.allowed_archs = project.allowed_archs
-sandbox_core_project.mtimes = project.mtimes
-sandbox_core_project.version = project.version
-sandbox_core_project.required_package = project.required_package
-sandbox_core_project.required_packages = project.required_packages
-sandbox_core_project.requires_str = project.requires_str
-sandbox_core_project.requireconfs_str = project.requireconfs_str
-sandbox_core_project.policy = project.policy
-sandbox_core_project.tmpdir = project.tmpdir
-sandbox_core_project.tmpfile = project.tmpfile
-sandbox_core_project.is_loaded = project.is_loaded
+sandbox_core_project.get = project.get
+sandbox_core_project.extraconf = project.extraconf
+sandbox_core_project.rule = project.rule
+sandbox_core_project.rules = project.rules
+sandbox_core_project.toolchain = project.toolchain
+sandbox_core_project.toolchains = project.toolchains
+sandbox_core_project.target = project.target
+sandbox_core_project.targets = project.targets
+sandbox_core_project.ordertargets = project.ordertargets
+sandbox_core_project.option = project.option
+sandbox_core_project.options = project.options
+sandbox_core_project.rootfile = project.rootfile
+sandbox_core_project.allfiles = project.allfiles
+sandbox_core_project.rcfiles = project.rcfiles
+sandbox_core_project.directory = project.directory
+sandbox_core_project.name = project.name
+sandbox_core_project.modes = project.modes
+sandbox_core_project.default_arch = project.default_arch
+sandbox_core_project.allowed_modes = project.allowed_modes
+sandbox_core_project.allowed_plats = project.allowed_plats
+sandbox_core_project.allowed_archs = project.allowed_archs
+sandbox_core_project.mtimes = project.mtimes
+sandbox_core_project.version = project.version
+sandbox_core_project.required_package = project.required_package
+sandbox_core_project.required_packages = project.required_packages
+sandbox_core_project.requires_str = project.requires_str
+sandbox_core_project.requireconfs_str = project.requireconfs_str
+sandbox_core_project.requireslock = project.requireslock
+sandbox_core_project.requireslock_version = project.requireslock_version
+sandbox_core_project.policy = project.policy
+sandbox_core_project.tmpdir = project.tmpdir
+sandbox_core_project.tmpfile = project.tmpfile
+sandbox_core_project.is_loaded = project.is_loaded
-- check project options
function sandbox_core_project.check()
diff --git a/xmake/modules/devel/git/lastcommit.lua b/xmake/modules/devel/git/lastcommit.lua
new file mode 100644
index 000000000..876812f86
--- /dev/null
+++ b/xmake/modules/devel/git/lastcommit.lua
@@ -0,0 +1,77 @@
+--!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
+
+ -- enter repository directory
+ local oldir = nil
+ if opt.repodir then
+ oldir = os.cd(opt.repodir)
+ end
+
+ -- get last commit
+ local lastcommit = os.iorunv(git.program, argv, {envs = envs})
+ if lastcommit then
+ lastcommit = lastcommit:trim()
+ end
+
+ -- leave repository directory
+ if oldir then
+ os.cd(oldir)
+ end
+ return lastcommit
+end
diff --git a/xmake/modules/private/action/require/impl/install_packages.lua b/xmake/modules/private/action/require/impl/install_packages.lua
index 7e83ae939..75ca4414e 100644
--- a/xmake/modules/private/action/require/impl/install_packages.lua
+++ b/xmake/modules/private/action/require/impl/install_packages.lua
@@ -30,6 +30,7 @@ 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
@@ -600,6 +601,11 @@ 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)
+
+ -- lock packages
+ if #packages_install > 0 then
+ lock_packages(packages)
+ end
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..18dabcac4
--- /dev/null
+++ b/xmake/modules/private/action/require/impl/lock_packages.lua
@@ -0,0 +1,64 @@
+--!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.name = instance:name()
+ result.plat = instance:plat()
+ result.arch = instance:arch()
+ result.version = instance:version_str()
+ result.buildhash = instance:buildhash()
+ result.branch = instance:branch()
+ result.tag = instance:tag()
+ if repo then
+ local lastcommit = git.lastcommit({repodir = repo:directory()})
+ 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 results = {__meta__ = {}}
+ results.__meta__.version = project.requireslock_version()
+ for _, instance in ipairs(packages) do
+ local packagelock_key = _get_packagelock_key(instance)
+ results[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..5084d2d29 100644
--- a/xmake/modules/private/action/require/impl/package.lua
+++ b/xmake/modules/private/action/require/impl/package.lua
@@ -26,10 +26,12 @@ import("core.base.hashset")
import("private.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()
@@ -193,13 +195,34 @@ 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()
+ if not option.get("upgrade") then
+ return project.policy("package.requires_lock") and os.isfile(project.requireslock())
+ end
+end
+
+-- get locked requires
+function _get_locked_requires(requirekey)
+ local requireslock = _memcache():get("requireslock")
+ if requireslock == nil then
+ if _has_locked_requires() then
+ requireslock = io.load(project.requireslock())
+ end
+ _memcache():set("requireslock", requireslock or false)
+ end
+ if requireslock then
+ return requireslock[requirekey], requireslock.__meta__.version
+ end
+end
+
-- sort package deps
--
-- e.g.
@@ -246,7 +269,19 @@ function _add_package_configurations(package)
end
-- select package version
-function _select_package_version(package, requireinfo)
+function _select_package_version(package, requireinfo, locked_requireinfo)
+
+ -- 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
-- exists urls? otherwise be phony package (only as package group)
if #package:urls() > 0 then
@@ -270,12 +305,12 @@ 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"
+ version, source = require_version ~= "latest" and require_version or "master", "branch"
end
if not version then
raise("package(%s): version(%s) not found!", package:name(), require_version)
@@ -477,26 +512,19 @@ 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 plat = config.plat() or os.subhost()
+ local arch = config.arch() or os.subarch()
+ local requirestr = requireinfo.originstr
+ local key = _get_requirekey(requireinfo, {hash = true, plat = plat, arch = arch})
+ return string.format("%s#%s", requirestr, key)
end
-- inherit some builtin configs of parent package if these config values are not default value
@@ -610,6 +638,19 @@ function _load_package(packagename, requireinfo, opt)
requireinfo.label = splitinfo[2]
end
+ -- sve requirekey
+ local requirekey = _get_packagelock_key(requireinfo)
+ requireinfo.requirekey = requirekey
+
+ -- get locked requireinfo
+ local locked_requireinfo, requireslock_version
+ if _has_locked_requires() then
+ locked_requireinfo, requireslock_version = _get_locked_requires(requirekey)
+ if requireslock_version and semver.compare(project.requireslock_version(), requireslock_version) < 0 then
+ locked_requireinfo = nil
+ end
+ end
+
-- load package from project first
local package
if os.isfile(os.projectfile()) then
@@ -619,7 +660,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 +694,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
@@ -712,6 +754,11 @@ function _load_package(packagename, requireinfo, opt)
on_load(package)
end
+ -- check build hash
+ if locked_requireinfo and locked_requireinfo.buildhash ~= package:buildhash() then
+ wprint("package(%s): buildhash is not matched in xmake-requires.lock", package:displayname(), locked_requireinfo.buildhash, package:buildhash())
+ end
+
-- load environments from the manifest to enable the environments of on_install()
package:envs_load()
diff --git a/xmake/modules/private/action/require/impl/repository.lua b/xmake/modules/private/action/require/impl/repository.lua
index 4dbf44e52..528aebc54 100644
--- a/xmake/modules/private/action/require/impl/repository.lua
+++ b/xmake/modules/private/action/require/impl/repository.lua
@@ -19,8 +19,64 @@
--
-- imports
+import("core.base.option")
import("core.base.global")
+import("core.project.config")
import("core.package.repository")
+import("devel.git")
+
+-- get package directory from the locked repository
+function _get_packagedir_from_locked_repo(packagename, locked_repo)
+
+ -- find global repository directory
+ local repodir_global
+ for _, repo in ipairs(repositories()) do
+ if locked_repo.url == repo:url() and locked_repo.branch == repo:branch() then
+ repodir_global = repo:directory()
+ break
+ end
+ end
+ local reponame = hash.uuid(locked_repo.url):gsub("%-", ""):lower() .. ".lock"
+
+ -- clone repository to local
+ local repodir_local = path.join(config.directory(), "repositories", reponame)
+ if not os.isdir(repodir_local) then
+ if repodir_global then
+ git.clone(repodir_global, {verbose = option.get("verbose"), outputdir = repodir_local})
+ elseif global.get("network") ~= "private" then
+ git.clone(locked_repo.url, {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
+
+ -- 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
+ git.pull({verbose = option.get("verbose"), remote = locked_repo.url, 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
+
+ -- 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 +104,53 @@ 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 .. (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
+ packagedirs[cachekey] = foundir or {}
end
- if foundir then
- packagedirs[packagename] = foundir
- _g._PACKAGEDIRS = packagedirs
- return foundir[1], foundir[2]
- end
+ return foundir[1], foundir[2]
end
-- get artifacts manifest from repositories
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..b07e4d50d
--- /dev/null
+++ b/xmake/modules/private/action/require/impl/utils/requirekey.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 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
+ return hash.uuid(key):gsub("%-", ""):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