summaryrefslogtreecommitdiff
path: root/xmake/actions/require
diff options
context:
space:
mode:
authorruki <[email protected]>2019-03-20 14:54:49 +0800
committerruki <[email protected]>2019-03-20 14:54:49 +0800
commit85deccc73a0278e01fa8580b68b38f16e0598bf7 (patch)
treea9a446a5be5ca662525df921e50ce66029bc3359 /xmake/actions/require
parent57506c7b8ba8941ebac3676a241f8444e0079a56 (diff)
parent8bb6ddf5c40f15fe6570f73dc5c4e5295ce95180 (diff)
Merge branch 'repo' into dev
Diffstat (limited to 'xmake/actions/require')
-rw-r--r--xmake/actions/require/clean.lua87
-rw-r--r--xmake/actions/require/clear.lua40
-rw-r--r--xmake/actions/require/impl/action/download.lua12
-rw-r--r--xmake/actions/require/impl/action/install.lua121
-rw-r--r--xmake/actions/require/impl/action/prefix/install.lua352
-rw-r--r--xmake/actions/require/impl/action/prefix/uninstall.lua53
-rw-r--r--xmake/actions/require/impl/environment.lua105
-rw-r--r--xmake/actions/require/impl/package.lua112
-rw-r--r--xmake/actions/require/info.lua113
-rw-r--r--xmake/actions/require/install.lua39
-rw-r--r--xmake/actions/require/list.lua14
-rw-r--r--xmake/actions/require/main.lua14
-rw-r--r--xmake/actions/require/unlink.lua77
-rw-r--r--xmake/actions/require/xmake.lua3
14 files changed, 494 insertions, 648 deletions
diff --git a/xmake/actions/require/clean.lua b/xmake/actions/require/clean.lua
new file mode 100644
index 000000000..cb69d85a4
--- /dev/null
+++ b/xmake/actions/require/clean.lua
@@ -0,0 +1,87 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you 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 - 2019, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file clean.lua
+--
+
+-- imports
+import("core.base.option")
+import("core.project.cache")
+import("core.package.package")
+
+-- clean all installed package caches
+function main()
+
+ -- trace
+ print("clear all package caches ..")
+
+ -- clear cache directory
+ os.rm(package.cachedir())
+
+ -- clear require cache
+ local require_cache = cache("local.require")
+ require_cache:clear()
+ require_cache:flush()
+
+ -- trace
+ print("clear all unused packages ..")
+
+ -- clear all unused packages
+ local installdir = package.installdir()
+ for _, references_file in ipairs(os.files(path.join(installdir, "*", "*", "*", "*", "references.txt"))) do
+ local references = io.load(references_file)
+ if references then
+ local found = false
+ for projectdir, refdate in pairs(references) do
+ if os.isdir(projectdir) then
+ found = true
+ break
+ end
+ end
+ if not found then
+
+ -- get package directory
+ local packagedir = path.directory(references_file)
+ print("remove %s ..", packagedir)
+
+ -- get confirm
+ local confirm = option.get("yes")
+ if confirm == nil then
+
+ -- show tips
+ cprint("${bright color.warning}note: ${clear}no projects are using this package, remove it (pass -y to skip confirm)?")
+ cprint("please input: y (y/n)")
+
+ -- get answer
+ io.flush()
+ local answer = io.read()
+ if answer == 'y' or answer == '' then
+ confirm = true
+ end
+ end
+ if confirm then
+ os.rm(packagedir)
+ end
+ end
+ end
+ end
+end
+
diff --git a/xmake/actions/require/clear.lua b/xmake/actions/require/clear.lua
deleted file mode 100644
index ffe73ed26..000000000
--- a/xmake/actions/require/clear.lua
+++ /dev/null
@@ -1,40 +0,0 @@
---!A cross-platform build utility based on Lua
---
--- Licensed to the Apache Software Foundation (ASF) under one
--- or more contributor license agreements. See the NOTICE file
--- distributed with this work for additional information
--- regarding copyright ownership. The ASF licenses this file
--- to you 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 - 2019, TBOOX Open Source Group.
---
--- @author ruki
--- @file clear.lua
---
-
--- imports
-import("core.project.cache")
-import("core.package.package")
-
--- clear all installed package caches
-function main()
-
- -- clear cache directory
- os.rm(package.cachedir())
-
- -- clear require cache
- local require_cache = cache("local.require")
- require_cache:clear()
- require_cache:flush()
-end
-
diff --git a/xmake/actions/require/impl/action/download.lua b/xmake/actions/require/impl/action/download.lua
index a01d9aef2..9eba21afd 100644
--- a/xmake/actions/require/impl/action/download.lua
+++ b/xmake/actions/require/impl/action/download.lua
@@ -91,13 +91,13 @@ function _download(package, url, sourcedir, url_alias, url_excludes)
-- get package file
local packagefile = path.filename(url)
- -- get sha256
- local sha256 = package:sha256(url_alias)
- assert(sha256, "cannot get sha256 of %s in package(%s)", url, package:name())
+ -- get sourcehash
+ local sourcehash = package:sourcehash(url_alias)
+ assert(sourcehash, "cannot get source hash of %s in package(%s)", url, package:name())
-- the package file have been downloaded?
local cached = true
- if option.get("force") or not os.isfile(packagefile) or sha256 ~= hash.sha256(packagefile) then
+ if option.get("force") or not os.isfile(packagefile) or sourcehash ~= hash.sha256(packagefile) then
-- no cached
cached = false
@@ -109,7 +109,7 @@ function _download(package, url, sourcedir, url_alias, url_excludes)
http.download(url, packagefile)
-- check hash
- if sha256 and sha256 ~= hash.sha256(packagefile) then
+ if sourcehash and sourcehash ~= hash.sha256(packagefile) then
raise("unmatched checksum!")
end
end
@@ -146,7 +146,7 @@ function _urls(package)
for _, url in ipairs(package:urls()) do
if git.checkurl(url) then
table.insert(urls[1], url)
- elseif package:sha256(package:url_alias(url)) then
+ elseif package:sourcehash(package:url_alias(url)) then
table.insert(urls[2], url)
end
end
diff --git a/xmake/actions/require/impl/action/install.lua b/xmake/actions/require/impl/action/install.lua
index 181bded44..6bb9d85ca 100644
--- a/xmake/actions/require/impl/action/install.lua
+++ b/xmake/actions/require/impl/action/install.lua
@@ -27,7 +27,62 @@ import("core.base.option")
import("core.project.target")
import("test")
import(".utils.filter")
-import("prefix")
+
+-- patch pkgconfig if not exists
+function _patch_pkgconfig(package)
+
+ -- get lib/pkgconfig/*.pc file
+ local pcfile = path.join(package:installdir(), "lib", "pkgconfig", package:name() .. ".pc")
+ if os.isfile(pcfile) then
+ return
+ end
+
+ -- trace
+ vprint("patching %s ..", pcfile)
+
+ -- fetch package
+ local fetchinfo = package:fetchdeps()
+ if not fetchinfo then
+ return
+ end
+
+ -- get libs
+ local libs = ""
+ for _, linkdir in ipairs(fetchinfo.linkdirs) do
+ libs = libs .. "-L" .. linkdir
+ end
+ libs = libs .. " -L${libdir}"
+ for _, link in ipairs(fetchinfo.links) do
+ libs = libs .. " -l" .. link
+ end
+ for _, link in ipairs(fetchinfo.syslinks) do
+ libs = libs .. " -l" .. link
+ end
+
+ -- cflags
+ local cflags = ""
+ for _, includedir in ipairs(fetchinfo.includedirs) do
+ cflags = cflags .. "-I" .. includedir
+ 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("exec_prefix=${prefix}")
+ file:print("libdir=${exec_prefix}/lib")
+ file:print("includedir=${prefix}/include")
+ file:print("")
+ file:print("Name: %s", package:name())
+ file:print("Description: %s", package:description())
+ file:print("Version: %s", package:version_str())
+ file:print("Libs: %s", libs)
+ file:print("Libs.private: ")
+ file:print("Cflags: %s", cflags)
+ file:close()
+ end
+end
-- install the given package
function main(package)
@@ -80,6 +135,7 @@ function main(package)
local installtask = function ()
-- install the third-party package directly, e.g. brew::pcre2/libpcre2-8, conan::OpenSSL/1.0.2n@conan/stable
+ local installed_now = false
if package:is3rd() then
local script = package:script("install")
if script ~= nil then
@@ -87,16 +143,17 @@ function main(package)
end
else
- -- uninstall it from the prefix directory first
- prefix.uninstall(package)
-
-- build and install package to the install directory
- local installedfile = path.join(package:installdir(), "installed.txt")
- if not os.isfile(installedfile) then
+ if option.get("force") or not package:manifest_load() then
-- clean install directory first
os.tryrm(package:installdir())
+ -- enter the environments of all package dependencies
+ for _, dep in ipairs(package:orderdeps()) do
+ dep:envs_enter()
+ end
+
-- do install
for i = 1, 3 do
local script = scripts[i]
@@ -105,16 +162,39 @@ function main(package)
end
end
- -- mark as installed
- io.writefile(installedfile, "")
+ -- leave the environments of all package dependencies
+ for _, dep in irpairs(package:orderdeps()) do
+ dep:envs_leave()
+ end
+
+ -- save the package info to the manifest file
+ package:manifest_save()
+ installed_now = true
end
+ end
+
+ -- enter the package environments
+ package:envs_enter()
+
+ -- fetch package and force to flush the cache
+ local fetchinfo = package:fetch({force = true})
+ if option.get("verbose") or option.get("diagnosis") then
+ print(fetchinfo)
+ end
+ assert(fetchinfo, "fetch %s failed!", tipname)
+
+ -- this package is installed now
+ if installed_now then
- -- install to the prefix directory
- prefix.install(package)
+ -- patch pkg-config files for package
+ _patch_pkgconfig(package)
-- test it
test(package)
end
+
+ -- leave the package environments
+ package:envs_leave()
end
-- install package
@@ -124,13 +204,6 @@ function main(package)
process.asyncrun(installtask)
end
- -- fetch package and force to flush the cache
- local fetchinfo = package:fetch({force = true})
- if option.get("verbose") or option.get("diagnosis") then
- print(fetchinfo)
- end
- assert(fetchinfo, "fetch %s failed!", tipname)
-
-- trace
cprint("${color.success}${text.success}")
end,
@@ -147,6 +220,20 @@ function main(package)
-- trace
cprint("${color.failure}${text.failure}")
+ -- leave the package environments
+ package:envs_leave()
+
+ -- copy the invalid package directory to cache
+ local installdir = package:installdir()
+ if os.isdir(installdir) then
+ local installdir_failed = path.join(package:cachedir(), "installdir.failed")
+ os.tryrm(installdir_failed)
+ if not os.isdir(installdir_failed) then
+ os.cp(installdir, installdir_failed)
+ end
+ end
+ os.tryrm(installdir)
+
-- failed
if not package:requireinfo().optional then
raise("install failed!")
diff --git a/xmake/actions/require/impl/action/prefix/install.lua b/xmake/actions/require/impl/action/prefix/install.lua
deleted file mode 100644
index 041c3c983..000000000
--- a/xmake/actions/require/impl/action/prefix/install.lua
+++ /dev/null
@@ -1,352 +0,0 @@
---!The Make-like install Utility based on Lua
---
--- Licensed to the Apache Software Foundation (ASF) under one
--- or more contributor license agreements. See the NOTICE file
--- distributed with this work for additional information
--- regarding copyright ownership. The ASF licenses this file
--- to you 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 - 2019, TBOOX Open Source Group.
---
--- @author ruki
--- @file install.lua
---
-
--- imports
-import("core.base.global")
-import("core.project.config")
-import("core.project.target")
-import("uninstall")
-
--- copy files to the prefix directory
-function _copy(mode, pattern)
-
- -- do install
- local prefixdir = _g.prefixdir
- local installdir = _g.installdir
- local relative_pathes = _g.relative_pathes
- for _, sourcepath in ipairs(os.match(path.join(installdir, pattern), mode)) do
-
- -- get relative path
- local relative_path = path.relative(sourcepath, installdir)
-
- -- trace
- vprint("copying %s ..", relative_path)
-
- -- copy file to the prefix directory
- os.vcp(sourcepath, path.absolute(relative_path, prefixdir))
-
- -- save this relative path
- table.insert(relative_pathes, relative_path)
- end
-end
-
--- copy directories to the prefix directory
-function _copy_dirs(pattern)
- _copy('d', pattern)
-end
-
--- copy files to the prefix directory
-function _copy_files(pattern)
- _copy('f', pattern)
-end
-
--- copy files and directories to the prefix directory
-function _copy_filedirs(pattern)
- _copy('a', pattern)
-end
-
--- find the prefix info file of the previous package
-function _find_prefixfile(originpath)
- local parentdir = path.directory(originpath)
- while parentdir and os.isdir(parentdir) and parentdir ~= "/" do
- local relative_path = path.relative(parentdir, path.join(global.directory(), "installed"))
- local prefixfile_local = path.join(config.directory(), "prefix", "info", relative_path, "info.txt")
- if os.isfile(prefixfile_local) then
- return prefixfile_local
- end
- local prefixfile_global = path.join(global.directory(), "prefix", "info", relative_path, "info.txt")
- if os.isfile(prefixfile_global) then
- return prefixfile_global
- end
- parentdir = path.directory(parentdir)
- end
-end
-
--- do link
-function _do_link(sourcepath, relativepath)
-
- -- link conflicts?
- local destpath = path.absolute(relativepath, _g.prefixdir)
- if os.islink(destpath) then
-
- -- get the original path of destpath
- local originpath = os.readlink(destpath)
-
- -- fix conflicts
- if os.isdir(sourcepath) and os.isdir(originpath) then
-
- -- trace
- vprint("unlinking %s ..", relativepath)
-
-
- -- find the prefix info file of the previous package
- local prefixfile = _find_prefixfile(originpath)
-
- -- get the prefix info
- local prefixinfo = nil
- if prefixfile and os.isfile(prefixfile) then
- prefixinfo = io.load(prefixfile)
- end
-
- -- remove the previous link
- os.rm(destpath)
- if prefixinfo then
- for idx, installfile in ipairs(prefixinfo.installed) do
- if installfile == relativepath then
- table.remove(prefixinfo.installed, idx)
- break
- end
- end
- end
-
- -- expand and relink the previous directories
- for _, filedir in ipairs(os.filedirs(path.join(originpath, "*"))) do
-
- -- get file or directory name
- local filename = path.filename(filedir)
-
- -- trace
- vprint("relinking %s ..", path.join(relativepath, filename))
-
- -- do link
- os.vln(filedir, path.join(destpath, filename))
-
- -- save this relative path
- table.insert(prefixinfo.installed, path.join(relativepath, filename))
- end
-
- -- update the previous prefix info file
- if prefixinfo then
- io.save(prefixfile, prefixinfo)
- end
-
- -- link the child pathes
- for _, filedir in ipairs(os.filedirs(path.join(sourcepath, "*"))) do
- _do_link(filedir, path.join(relativepath, path.filename(filedir)))
- end
-
- -- fix broken link path
- elseif os.isdir(sourcepath) and not os.exists(originpath) then
-
- -- remove the broken link path
- os.rm(destpath)
-
- -- trace
- vprint("linking %s ..", relativepath)
-
- -- do link
- os.vln(sourcepath, destpath)
-
- -- save this relative path
- table.insert(_g.relative_pathes, relativepath)
- else
- -- link conflicts
- os.raise("cannot link %s => %s", sourcepath, destpath)
- end
- elseif os.isdir(destpath) then
-
- -- link the child pathes
- for _, filedir in ipairs(os.filedirs(path.join(sourcepath, "*"))) do
- _do_link(filedir, path.join(relativepath, path.filename(filedir)))
- end
- else
-
- -- trace
- vprint("linking %s ..", relativepath)
-
- -- do link
- os.vln(sourcepath, destpath)
-
- -- save this relative path
- table.insert(_g.relative_pathes, relativepath)
- end
-end
-
--- link files to the prefix directory
-function _link(mode, pattern)
- local installdir = _g.installdir
- for _, sourcepath in ipairs(os.match(path.join(installdir, pattern), mode)) do
- _do_link(sourcepath, path.relative(sourcepath, installdir))
- end
-end
-
--- link directories to the prefix directory
-function _link_dirs(pattern)
- _link('d', pattern)
-end
-
--- link files to the prefix directory
-function _link_files(pattern)
- _link('f', pattern)
-end
-
--- link files and directories to the prefix directory
-function _link_filedirs(pattern)
- _link('a', pattern)
-end
-
--- patch pkgconfig if not exists
-function _patch_pkgconfig(package)
-
- -- get lib/pkgconfig/*.pc file
- local pcfile = path.join(package:installdir("lib", "pkgconfig"), package:name() .. ".pc")
- if os.isfile(pcfile) then
- return
- end
-
- -- trace
- vprint("patching %s ..", pcfile)
-
- -- get libs
- local libs = ""
- for _, linkdir in ipairs(package:getvar("linkdirs")) do
- libs = libs .. "-L" .. linkdir
- end
- libs = libs .. " -L${libdir}"
- local links = package:getvar("links")
- if links then
- for _, link in ipairs(links) do
- libs = libs .. " -l" .. link
- end
- else
- local found = false
- for _, libfile in ipairs(os.files(path.join(package:installdir("lib"), "*.a"))) do
- local link = target.linkname(path.filename(libfile))
- if link then
- libs = libs .. " -l" .. link
- found = true
- end
- end
- if not found then
- for _, libfile in ipairs(os.files(path.join(package:installdir("lib"), "*.so"))) do
- local link = target.linkname(path.filename(libfile))
- if link then
- libs = libs .. " -l" .. link
- end
- end
- end
- end
- for _, link in ipairs(package:getvar("syslinks")) do
- libs = libs .. " -l" .. link
- end
-
- -- cflags
- local cflags = ""
- for _, includedir in ipairs(package:getvar("includedirs")) do
- cflags = cflags .. "-I" .. includedir
- end
- cflags = cflags .. " -I${includedir}"
-
- -- patch a *.pc file
- local file = io.open(pcfile, 'w')
- if file then
- file:print("prefix=%s", package:prefixdir())
- file:print("exec_prefix=${prefix}")
- file:print("libdir=${exec_prefix}/lib")
- file:print("includedir=${prefix}/include")
- file:print("")
- file:print("Name: %s", package:name())
- file:print("Description: %s", package:description())
- file:print("Version: %s", package:version_str())
- file:print("Libs: %s", libs)
- file:print("Libs.private: ")
- file:print("Cflags: %s", cflags)
- file:close()
- end
-end
-
--- install package with link
-function _install_with_link(package)
- _link_files("bin/*")
- _link_files("sbin/*")
- _link_filedirs("include/*")
- _link_filedirs("lib/*")
- _link_filedirs("share/*|info")
- _link_filedirs("share/info/*|dir")
-end
-
--- install package without link (windows)
-function _install_without_link(package)
- if package:kind() == "binary" then
- _copy_filedirs("**")
- else
- _copy_filedirs("lib/**")
- _copy_filedirs("include/**")
- end
-end
-
--- install package
-function _install(package)
-
- -- patch pkgconfig if not exists
- if not is_plat("windows") then
- _patch_pkgconfig(package)
- end
-
- -- install package to the prefix directory
- if is_host("windows") then
- _install_without_link(package)
- else
- _install_with_link(package)
- end
-end
-
--- install package to the prefix directory
-function main(package)
-
- -- init some pathes
- _g.prefixdir = package:prefixdir()
- _g.installdir = package:installdir()
- _g.relative_pathes = {}
-
- -- trace
- vprint("installing %s to %s ..", _g.installdir, _g.prefixdir)
-
- -- install to the prefix directory
- local relative_pathes = {}
- try
- {
- function ()
- _install(package)
- end,
- finally
- {
- function (ok, errors)
- -- save the prefix info to file
- local prefixinfo = package:prefixinfo()
- prefixinfo.installed = _g.relative_pathes
- io.save(package:prefixfile(), prefixinfo)
-
- -- register this package
- package:register()
-
- -- continue to raise errors
- if not ok then
- raise(errors)
- end
- end
- }
- }
-end
-
diff --git a/xmake/actions/require/impl/action/prefix/uninstall.lua b/xmake/actions/require/impl/action/prefix/uninstall.lua
deleted file mode 100644
index 3e48695ed..000000000
--- a/xmake/actions/require/impl/action/prefix/uninstall.lua
+++ /dev/null
@@ -1,53 +0,0 @@
---!The Make-like install Utility based on Lua
---
--- Licensed to the Apache Software Foundation (ASF) under one
--- or more contributor license agreements. See the NOTICE file
--- distributed with this work for additional information
--- regarding copyright ownership. The ASF licenses this file
--- to you 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 - 2019, TBOOX Open Source Group.
---
--- @author ruki
--- @file uninstall.lua
---
-
--- uninstall package from the prefix directory
-function main(package)
-
- -- remove the previous installed files
- local prefixdir = package:prefixdir()
- for _, relativefile in ipairs(package:prefixinfo().installed) do
-
- -- trace
- vprint("removing %s ..", relativefile)
-
- -- remove file
- local prefixfile = path.absolute(relativefile, prefixdir)
- os.tryrm(prefixfile)
-
- -- remove it if the parent directory is empty
- local parentdir = path.directory(prefixfile)
- while parentdir and os.isdir(parentdir) and os.emptydir(parentdir) do
- os.tryrm(parentdir)
- parentdir = path.directory(parentdir)
- end
- end
-
- -- unregister this package
- package:unregister()
-
- -- remove the prefix file
- os.tryrm(package:prefixfile())
-end
-
diff --git a/xmake/actions/require/impl/environment.lua b/xmake/actions/require/impl/environment.lua
index e4cf1ff10..8fffddd7f 100644
--- a/xmake/actions/require/impl/environment.lua
+++ b/xmake/actions/require/impl/environment.lua
@@ -29,9 +29,69 @@ import("core.package.package", {alias = "core_package"})
import("lib.detect.find_tool")
import("package")
+-- enter the package environments
+function _enter_package(package_name, envs, installdir)
+
+ -- save the old environments
+ _g._OLDENVS = _g._OLDENVS or {}
+ local oldenvs = _g._OLDENVS[package_name]
+ if not oldenvs then
+ oldenvs = {}
+ _g._OLDENVS[package_name] = oldenvs
+ end
+
+ -- add the new environments
+ oldenvs.PATH = os.getenv("PATH")
+ for name, values in pairs(envs) do
+ oldenvs[name] = oldenvs[name] or os.getenv(name)
+ if name == "PATH" then
+ for _, value in ipairs(values) do
+ if path.is_absolute(value) then
+ os.addenv(name, value)
+ else
+ os.addenv(name, path.join(installdir, value))
+ end
+ end
+ else
+ os.addenv(name, unpack(table.wrap(values)))
+ end
+ end
+end
+
+-- leave the package environments
+function _leave_package(package_name)
+ _g._OLDENVS = _g._OLDENVS or {}
+ local oldenvs = _g._OLDENVS[package_name]
+ if oldenvs then
+ for name, values in pairs(oldenvs) do
+ os.setenv(name, values)
+ end
+ _g._OLDENVS[package_name] = nil
+ end
+end
+
+-- enter environment of the given binary packages, git, 7z, ..
+function _enter_packages(...)
+ for _, name in ipairs({...}) do
+ for _, manifest_file in ipairs(os.files(path.join(core_package.installdir(), name:sub(1, 1), name, "*", "*", "manifest.txt"))) do
+ local manifest = io.load(manifest_file)
+ if manifest and manifest.plat == os.host() and manifest.arch == os.arch() then
+ _enter_package(name, manifest.envs, path.directory(manifest_file))
+ end
+ end
+ end
+end
+
+-- leave environment of the given binary packages, git, 7z, ..
+function _leave_packages(...)
+ for _, name in ipairs({...}) do
+ _leave_package(name)
+ end
+end
+
-- enter environment
--
--- ensure that we can find some basic tools: git, make/nmake/cmake, msbuild ...
+-- ensure that we can find some basic tools: git, unzip, ...
--
-- If these tools not exist, we will install it first.
--
@@ -45,45 +105,38 @@ function enter()
raise("unzip not found! we need install it first")
end
+ -- enter the environments of git and 7z
+ _enter_packages("git", "7z")
+
-- git not found? install it first
+ local packages = {}
if not find_tool("git") then
- package.install_packages("git")
+ table.join2(packages, package.install_packages("git"))
end
-- missing the necessary unarchivers for *.gz, *.7z? install them first, e.g. gzip, 7z, tar ..
if not ((find_tool("gzip") and find_tool("tar")) or find_tool("7z")) then
- package.install_packages("7z")
+ table.join2(packages, package.install_packages("7z"))
end
- -- get prefix directories
- local plat = get_config("plat")
- local arch = get_config("arch")
- _g.prefixdirs = _g.prefixdirs or
- {
- core_package.prefixdir(false, "release", plat, arch),
- core_package.prefixdir(true, "release", plat, arch),
- }
-
- -- add search directories of pkgconfig, aclocal, cmake
- _g._ACLOCAL_PATH = os.getenv("ACLOCAL_PATH")
- _g._PKG_CONFIG_PATH = os.getenv("PKG_CONFIG_PATH")
- _g._CMAKE_PREFIX_PATH = os.getenv("CMAKE_PREFIX_PATH")
- for _, prefixdir in ipairs(_g.prefixdirs) do
- if not is_plat("windows") then
- os.addenv("ACLOCAL_PATH", path.join(prefixdir, "share", "aclocal"))
- os.addenv("PKG_CONFIG_PATH", path.join(prefixdir, "lib", "pkgconfig"))
- end
- os.addenv("CMAKE_PREFIX_PATH", prefixdir)
+ -- enter the environments of installed packages
+ for _, instance in ipairs(packages) do
+ instance:envs_enter()
end
+ _g._PACKAGES = packages
end
-- leave environment
function leave()
- -- restore search directories of pkgconfig, aclocal, cmake
- os.setenv("ACLOCAL_PATH", _g._ACLOCAL_PATH)
- os.setenv("PKG_CONFIG_PATH", _g._PKG_CONFIG_PATH)
- os.setenv("CMAKE_PREFIX_PATH", _g._CMAKE_PREFIX_PATH)
+ -- leave the environments of installed packages
+ for _, instance in irpairs(_g._PACKAGES) do
+ instance:envs_leave()
+ end
+ _g._PACKAGES = nil
+
+ -- leave the environments of git and 7z
+ _leave_packages("7z", "git")
-- restore search pathes of toolchains
environment.leave("toolchains")
diff --git a/xmake/actions/require/impl/package.lua b/xmake/actions/require/impl/package.lua
index 159497b60..f55b6a98a 100644
--- a/xmake/actions/require/impl/package.lua
+++ b/xmake/actions/require/impl/package.lua
@@ -114,6 +114,13 @@ function _parse_require(require_str, requires_extra, parentinfo)
require_extra = requires_extra[require_str] or {}
end
+ -- get required building configurations
+ local require_build_configs = require_extra.configs or require_extra.config
+ if require_extra.debug then
+ require_build_configs = require_build_configs or {}
+ require_build_configs.debug = true
+ end
+
-- init required item
local required = {}
parentinfo = parentinfo or {}
@@ -124,11 +131,10 @@ function _parse_require(require_str, requires_extra, parentinfo)
reponame = reponame,
version = version,
alias = require_extra.alias, -- set package alias name
- debug = require_extra.debug, -- uses the debug package, default: false
group = require_extra.group, -- only uses the first package in same group
system = require_extra.system, -- default: true, we can set it to disable system package manually
option = require_extra.option, -- set and attach option
- config = require_extra.config, -- the build configuration of package
+ configs = require_build_configs, -- the required building configurations
default = require_extra.default, -- default: true, we can set it to disable package manually
optional = parentinfo.optional or require_extra.optional -- default: false, inherit parentinfo.optional
}
@@ -240,6 +246,16 @@ function _sort_packagedeps(package)
return orderdeps
end
+-- add some builtin configs to package
+function _add_package_configs(package)
+ package:add("configs", "debug", {builtin = true, description = "Enable debug symbols.", default = false, type = "boolean"})
+ package:add("configs", "cflags", {builtin = true, description = "Set the C compiler flags."})
+ package:add("configs", "cxflags", {builtin = true, description = "Set the C/C++ compiler flags."})
+ package:add("configs", "cxxflags", {builtin = true, description = "Set the C++ compiler flags."})
+ package:add("configs", "asflags", {builtin = true, description = "Set the assembler flags."})
+ package:add("configs", "vs_runtime", {builtin = true, description = "Set vs compiler runtime.", default = "MT", values = {"MT", "MD"}})
+end
+
-- load all required packages
function _load_packages(requires, opt)
@@ -270,6 +286,9 @@ function _load_packages(requires, opt)
package._ORDERDEPS = table.unique(_sort_packagedeps(package))
end
+ -- add some builtin configs to package
+ _add_package_configs(package)
+
-- save this package package
table.insert(packages, package)
end
@@ -292,6 +311,50 @@ function _sort_packages_urls(packages)
package:urls_set(fasturl.sort(package:urls()))
end
end
+
+-- check the configurations of packages
+--
+-- package("pcre2")
+-- add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})
+-- add_configs("bitwidth", {type = "number", values = {8, 16, 32}})
+-- add_configs("bitwidth", {restrict = function(value) if tonumber(value) < 100 then return true end})
+--
+function _check_packages_configs(packages)
+ for _, package in ipairs(packages) do
+ local configs_defined = {}
+ for _, name in ipairs(package:get("configs")) do
+ configs_defined[name] = package:extraconf("configs", name) or {}
+ end
+ for name, value in pairs(package:configs()) do
+ local conf = configs_defined[name]
+ if conf then
+ local config_type = conf.type or "string"
+ if type(value) ~= config_type then
+ raise("package(%s %s): invalid type(%s) for config(%s), need type(%s)!", package:name(), package:version_str(), type(value), name, config_type)
+ end
+ if conf.values then
+ local found = false
+ for _, config_value in ipairs(conf.values) do
+ if tostring(value) == tostring(config_value) then
+ found = true
+ break
+ end
+ end
+ if not found then
+ raise("package(%s %s): invalid value(%s) for config(%s), please run `xmake require --info %s` to get all valid values!", package:name(), package:version_str(), value, name, package:name())
+ end
+ end
+ if conf.restrict then
+ if not conf.restrict(value) then
+ raise("package(%s %s): invalid value(%s) for config(%s)!", package:name(), package:version_str(), value, name)
+ end
+ end
+ else
+ raise("package(%s %s): invalid config(%s), please run `xmake require --info %s` to get all configurations!", package:name(), package:version_str(), name, package:name())
+ end
+ end
+ end
+end
-- select packages version
function _select_packages_version(packages)
@@ -344,7 +407,7 @@ function _get_confirm(packages)
-- get packages for each repositories
local packages_repo = {}
for _, package in ipairs(packages) do
- local reponame = package:repo() and package:repo():name() or package:fromkind()
+ local reponame = package:repo() and package:repo():name() or (package:isSys() and "system" or "")
if package:is3rd() then
reponame = package:name():lower():split("::")[1]
end
@@ -355,7 +418,9 @@ function _get_confirm(packages)
-- show tips
cprint("${bright color.warning}note: ${clear}try installing these packages (pass -y to skip confirm)?")
for reponame, packages in pairs(packages_repo) do
- print("in %s:", reponame)
+ if reponame ~= "" then
+ print("in %s:", reponame)
+ end
for _, package in ipairs(packages) do
print(" -> %s %s %s", package:name(), package:version_str() or "", package:debug() and "(debug)" or "")
end
@@ -409,6 +474,9 @@ function load_packages(requires, opt)
-- select packages version
_select_packages_version(packages)
+ -- check the configurations of packages
+ _check_packages_configs(packages)
+
-- remove repeat packages with same the package name and version
local unique = {}
local results = {}
@@ -551,48 +619,14 @@ function uninstall_packages(requires, opt)
-- remove all packages
local packages = {}
for _, instance in ipairs(load_packages(requires, opt)) do
- if os.isfile(instance:prefixfile()) then
-
- -- uninstall package from the prefix directory
- action.prefix.uninstall(instance)
-
- -- remove ok
+ if os.isfile(instance:manifest_file()) then
table.insert(packages, instance)
end
-
- -- remove the installed files
os.tryrm(instance:installdir())
end
return packages
end
--- only unlink packages from the prefix directory
-function unlink_packages(requires, opt)
-
- -- init options
- opt = opt or {}
-
- -- do not remove dependent packages
- opt.nodeps = true
-
- -- clear the detect cache
- detectcache.clear()
-
- -- unlink all packages
- local packages = {}
- for _, instance in ipairs(load_packages(requires, opt)) do
- if os.isfile(instance:prefixfile()) then
-
- -- uninstall package from the prefix directory
- action.prefix.uninstall(instance)
-
- -- remove ok
- table.insert(packages, instance)
- end
- end
- return packages
-end
-
-- search packages
function search_packages(names)
diff --git a/xmake/actions/require/info.lua b/xmake/actions/require/info.lua
index d0060e0f7..d35f503cf 100644
--- a/xmake/actions/require/info.lua
+++ b/xmake/actions/require/info.lua
@@ -31,14 +31,20 @@ import("impl.package")
import("impl.repository")
import("impl.environment")
--- from local/global/system/remote?
+-- from xmake/system/remote?
function _from(instance)
- local fetchinfo, fetchfrom = instance:fetch()
+ local fetchinfo = instance:fetch()
if fetchinfo then
- return ", ${green}" .. fetchfrom .. "${clear}"
+ if instance:is3rd() then
+ return ", ${green}3rd${clear}"
+ elseif instance:isSys() then
+ return ", ${green}system${clear}"
+ else
+ return ""
+ end
elseif #instance:urls() > 0 then
return instance:supported() and format(", ${yellow}remote${clear}(in %s)", instance:repo():name()) or format(", ${yellow}remote${clear}(${red}unsupported${clear} in %s)", instance:repo():name())
- elseif instance:from("system") then
+ elseif instance:isSys() then
return ", ${red}missing${clear}"
else
return ""
@@ -116,13 +122,19 @@ function main(package_names)
cprint(" -> ${magenta}urls${clear}:")
for _, url in ipairs(urls) do
print(" -> %s", filter.handle(url, instance))
- local sha256 = instance:sha256(instance:url_alias(url))
- if sha256 then
- cprint(" -> ${yellow}%s${clear}", sha256)
+ local sourcehash = instance:sourcehash(instance:url_alias(url))
+ if sourcehash then
+ cprint(" -> ${yellow}%s${clear}", sourcehash)
end
end
end
+ -- show repository
+ local repo = instance:repo()
+ if repo then
+ cprint(" -> ${magenta}repo${clear}: %s %s %s", repo:name(), repo:url(), repo:branch() or "")
+ end
+
-- show deps
local deps = instance:orderdeps()
if deps and #deps > 0 then
@@ -136,12 +148,6 @@ function main(package_names)
-- show cache directory
cprint(" -> ${magenta}cachedir${clear}: %s", instance:cachedir())
- -- show prefix directory
- cprint(" -> ${magenta}prefixdir${clear}: %s", instance:prefixdir())
-
- -- show prefix file
- cprint(" -> ${magenta}prefixfile${clear}: %s", instance:prefixfile())
-
-- show install directory
cprint(" -> ${magenta}installdir${clear}: %s", instance:installdir())
@@ -154,6 +160,87 @@ function main(package_names)
end
end
+ -- show supported platforms
+ local platforms = {}
+ local on_install = instance:get("install")
+ if type(on_install) == "table" then
+ for plat, _ in pairs(on_install) do
+ table.insert(platforms, plat)
+ end
+ else
+ table.insert(platforms, "all")
+ end
+ cprint(" -> ${magenta}platforms${clear}: %s", table.concat(platforms, ", "))
+
+ -- show requires
+ cprint(" -> ${magenta}requires${clear}:")
+ cprint(" -> ${cyan}plat${clear}: %s", instance:plat())
+ cprint(" -> ${cyan}arch${clear}: %s", instance:arch())
+ local configs_required = instance:configs()
+ if configs_required then
+ cprint(" -> ${cyan}configs${clear}:")
+ for name, value in pairs(configs_required) do
+ cprint(" -> %s: %s", name, value)
+ end
+ end
+
+ -- show user configs
+ local configs_defined = instance:get("configs")
+ if configs_defined then
+ cprint(" -> ${magenta}configs${clear}:")
+ for _, conf in ipairs(configs_defined) do
+ local configs_extra = instance:extraconf("configs", conf)
+ if configs_extra and not configs_extra.builtin then
+ cprintf(" -> ${cyan}%s${clear}: ", conf)
+ if configs_extra.description then
+ printf(configs_extra.description)
+ end
+ if configs_extra.default ~= nil then
+ printf(" (default: %s)", configs_extra.default)
+ elseif configs_extra.type ~= nil and configs_extra.type ~= "string" then
+ printf(" (type: %s)", configs_extra.type)
+ end
+ print("")
+ if configs_extra.values then
+ cprint(" -> values: %s", string.serialize(configs_extra.values, true))
+ end
+ end
+ end
+ end
+
+ -- show builtin configs
+ local configs_defined = instance:get("configs")
+ if configs_defined then
+ cprint(" -> ${magenta}configs (builtin)${clear}:")
+ for _, conf in ipairs(configs_defined) do
+ local configs_extra = instance:extraconf("configs", conf)
+ if configs_extra and configs_extra.builtin then
+ cprintf(" -> ${cyan}%s${clear}: ", conf)
+ if configs_extra.description then
+ printf(configs_extra.description)
+ end
+ if configs_extra.default ~= nil then
+ printf(" (default: %s)", configs_extra.default)
+ elseif configs_extra.type ~= nil and configs_extra.type ~= "string" then
+ printf(" (type: %s)", configs_extra.type)
+ end
+ print("")
+ if configs_extra.values then
+ cprint(" -> values: %s", string.serialize(configs_extra.values, true))
+ end
+ end
+ end
+ end
+
+ -- show references
+ local references = instance:references()
+ if references then
+ cprint(" -> ${magenta}references${clear}:")
+ for projectdir, refdate in pairs(references) do
+ cprint(" -> %s: %s%s", refdate, projectdir, os.isdir(projectdir) and "" or " ${red}(not found)${clear}")
+ end
+ end
+
-- end
print("")
end
diff --git a/xmake/actions/require/install.lua b/xmake/actions/require/install.lua
index 80df043ba..65c624d99 100644
--- a/xmake/actions/require/install.lua
+++ b/xmake/actions/require/install.lua
@@ -38,11 +38,11 @@ function _register_required_package(instance, requireinfo)
if _g.optional_missing[instance:name()] then
requireinfo:enable(false)
else
- -- add this package info
+ -- clear require info first
requireinfo:clear()
- requireinfo:add(instance:fetch())
- -- add all dependent packages info
+ -- add include and links info
+ requireinfo:add(instance:fetch())
local orderdeps = instance:orderdeps()
if orderdeps then
local total = #orderdeps
@@ -54,6 +54,29 @@ function _register_required_package(instance, requireinfo)
end
end
+ -- add environments
+ local envs = {}
+ local hasenvs = false
+ local installdir = instance:installdir()
+ for name, values in pairs(instance:envs()) do
+ if name == "PATH" then
+ for _, value in ipairs(values) do
+ envs[name] = envs[name] or {}
+ if path.is_absolute(value) then
+ table.insert(envs[name], value)
+ else
+ table.insert(envs[name], path.join(installdir, value))
+ end
+ end
+ else
+ envs[name] = values
+ end
+ hasenvs = true
+ end
+ if hasenvs then
+ requireinfo:add({envs = envs})
+ end
+
-- save this package version
requireinfo:version_set(instance:version_str())
@@ -75,11 +98,9 @@ function _register_required_packages(packages)
if not group or not registered_in_group[group] then
-- do not register binary package
- if instance:kind() ~= "binary" then
- local requireinfo = project.require(instance:alias() or instance:name())
- if requireinfo then
- _register_required_package(instance, requireinfo)
- end
+ local requireinfo = project.require(instance:alias() or instance:name())
+ if requireinfo then
+ _register_required_package(instance, requireinfo)
end
-- mark as registered in group
@@ -97,7 +118,7 @@ function _check_missing_packages(packages)
local packages_missing = {}
local optional_missing = {}
for _, instance in ipairs(packages) do
- if not instance:exists() and (#instance:urls() > 0 or instance:from("system")) then
+ if not instance:exists() and (#instance:urls() > 0 or instance:isSys()) then
if instance:optional() then
optional_missing[instance:name()] = instance
else
diff --git a/xmake/actions/require/list.lua b/xmake/actions/require/list.lua
index 71d50c18f..5fd282b26 100644
--- a/xmake/actions/require/list.lua
+++ b/xmake/actions/require/list.lua
@@ -29,14 +29,20 @@ import("impl.package")
import("impl.repository")
import("impl.environment")
--- from local/global/system/remote?
+-- from xmake/system/remote?
function _from(instance)
- local fetchinfo, fetchfrom = instance:fetch()
+ local fetchinfo = instance:fetch()
if fetchinfo then
- return ", ${green}" .. fetchfrom .. "${clear}"
+ if instance:is3rd() then
+ return ", ${green}3rd${clear}"
+ elseif instance:isSys() then
+ return ", ${green}system${clear}"
+ else
+ return ""
+ end
elseif #instance:urls() > 0 then
return instance:supported() and format(", ${yellow}remote${clear}(in %s)", instance:repo():name()) or format(", ${yellow}remote${clear}(${red}unsupported${clear} in %s)", instance:repo():name())
- elseif instance:from("system") then
+ elseif instance:isSys() then
return ", ${red}missing${clear}"
else
return ""
diff --git a/xmake/actions/require/main.lua b/xmake/actions/require/main.lua
index 5e5ccd830..6311434cc 100644
--- a/xmake/actions/require/main.lua
+++ b/xmake/actions/require/main.lua
@@ -30,11 +30,10 @@ import("core.project.project")
import("core.platform.platform")
import("list")
import("info")
-import("clear")
+import("clean")
import("search")
import("install")
import("uninstall")
-import("unlink")
--
-- the default repositories:
@@ -74,10 +73,10 @@ function main()
-- load project first
_load_project()
- -- clear all installed packages cache
- if option.get("clear") then
+ -- clean all installed packages cache
+ if option.get("clean") then
- clear(option.get("global"))
+ clean(option.get("global"))
-- search for the given packages from repositories
elseif option.get("search") then
@@ -89,11 +88,6 @@ function main()
uninstall(option.get("requires"))
- -- unlink the installed packages
- elseif option.get("unlink") then
-
- unlink(option.get("requires"))
-
-- show the given package info
elseif option.get("info") then
diff --git a/xmake/actions/require/unlink.lua b/xmake/actions/require/unlink.lua
deleted file mode 100644
index de1cd5f99..000000000
--- a/xmake/actions/require/unlink.lua
+++ /dev/null
@@ -1,77 +0,0 @@
---!A cross-platform build utility based on Lua
---
--- Licensed to the Apache Software Foundation (ASF) under one
--- or more contributor license agreements. See the NOTICE file
--- distributed with this work for additional information
--- regarding copyright ownership. The ASF licenses this file
--- to you 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 - 2019, TBOOX Open Source Group.
---
--- @author ruki
--- @file unlink.lua
---
-
--- imports
-import("core.base.task")
-import("core.base.option")
-import("core.project.project")
-import("impl.package")
-import("impl.repository")
-import("impl.environment")
-
--- unlink the given packages
-function main(package_names)
-
- -- no package names?
- if not package_names then
- return
- end
-
- -- enter environment
- environment.enter()
-
- -- pull all repositories first if not exists
- if not repository.pulled() then
- task.run("repo", {update = true})
- end
-
- -- get project requires
- local project_requires, requires_extra = project.requires_str()
- if not project_requires then
- raise("requires(%s) not found in project!", table.concat(requires, " "))
- end
-
- -- find required package in project
- local requires = {}
- for _, name in ipairs(package_names) do
- for _, require_str in ipairs(project_requires) do
- if require_str:split(' ')[1]:lower():find(name:lower()) then
- table.insert(requires, require_str)
- end
- end
- end
- if #requires == 0 then
- raise("%s not found in project!", table.concat(package_names, " "))
- end
-
- -- unlink packages
- local packages = package.unlink_packages(requires, {requires_extra = requires_extra})
- for _, instance in ipairs(packages) do
- print("unlink: %s%s ok!", instance:name(), instance:version_str() and ("-" .. instance:version_str()) or "")
- end
-
- -- leave environment
- environment.leave()
-end
-
diff --git a/xmake/actions/require/xmake.lua b/xmake/actions/require/xmake.lua
index 35d6e0853..06147576a 100644
--- a/xmake/actions/require/xmake.lua
+++ b/xmake/actions/require/xmake.lua
@@ -45,13 +45,12 @@ task("require")
-- options
, options =
{
- {'c', "clear", "k", nil, "Clear all installed package caches." }
+ {'c', "clean", "k", nil, "Clear all package caches and uninstall all not-referenced packages." }
, {'f', "force", "k", nil, "Force to reinstall all package dependencies." }
, {'l', "list", "k", nil, "List all package dependencies." }
, { }
, {nil, "info", "k", nil, "Show the given package info." }
, {'s', "search", "k", nil, "Search for the given packages from repositories." }
- , {nil, "unlink", "k", nil, "Only unlink the installed packages." }
, {nil, "uninstall", "k", nil, "Uninstall the installed packages." }
, {nil, "extra", "kv", nil, "Set the extra info of packages." }
, { }