From 91ecb5c9596db8f176932244a49d940d594380cf Mon Sep 17 00:00:00 2001 From: ruki Date: Wed, 30 Sep 2020 22:57:09 +0800 Subject: rename package/action to actions --- xmake/actions/require/impl/action/download.lua | 275 --------------------- .../require/impl/action/download_resources.lua | 96 ------- xmake/actions/require/impl/action/install.lua | 267 -------------------- .../actions/require/impl/action/patch_sources.lua | 112 --------- xmake/actions/require/impl/action/test.lua | 59 ----- xmake/actions/require/impl/actions/download.lua | 275 +++++++++++++++++++++ .../require/impl/actions/download_resources.lua | 96 +++++++ xmake/actions/require/impl/actions/install.lua | 267 ++++++++++++++++++++ .../actions/require/impl/actions/patch_sources.lua | 112 +++++++++ xmake/actions/require/impl/actions/test.lua | 59 +++++ xmake/actions/require/impl/package.lua | 7 +- xmake/modules/action/install/main.lua | 4 +- xmake/modules/action/install/unix.lua | 18 +- xmake/modules/action/install/windows.lua | 22 +- xmake/modules/action/uninstall/main.lua | 4 +- xmake/modules/action/uninstall/unix.lua | 18 +- xmake/modules/action/uninstall/windows.lua | 22 +- 17 files changed, 857 insertions(+), 856 deletions(-) delete mode 100644 xmake/actions/require/impl/action/download.lua delete mode 100644 xmake/actions/require/impl/action/download_resources.lua delete mode 100644 xmake/actions/require/impl/action/install.lua delete mode 100644 xmake/actions/require/impl/action/patch_sources.lua delete mode 100644 xmake/actions/require/impl/action/test.lua create mode 100644 xmake/actions/require/impl/actions/download.lua create mode 100644 xmake/actions/require/impl/actions/download_resources.lua create mode 100644 xmake/actions/require/impl/actions/install.lua create mode 100644 xmake/actions/require/impl/actions/patch_sources.lua create mode 100644 xmake/actions/require/impl/actions/test.lua diff --git a/xmake/actions/require/impl/action/download.lua b/xmake/actions/require/impl/action/download.lua deleted file mode 100644 index 57f28989f..000000000 --- a/xmake/actions/require/impl/action/download.lua +++ /dev/null @@ -1,275 +0,0 @@ ---!The Make-like download 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-2020, TBOOX Open Source Group. --- --- @author ruki --- @file download.lua --- - --- imports -import("core.base.option") -import("core.base.tty") -import("core.base.hashset") -import("core.project.config") -import("core.package.package", {alias = "core_package"}) -import("lib.detect.find_file") -import("lib.detect.find_directory") -import(".utils.filter") -import("net.http") -import("devel.git") -import("utils.archive") - --- checkout codes from git -function _checkout(package, url, sourcedir, url_alias) - - -- use previous source directory if exists - local packagedir = path.join(sourcedir, package:name()) - if os.isdir(packagedir) and - not (option.get("force") and package:branch()) then -- we need disable cache if we force to clone from the given branch - - -- clean the previous build files - git.clean({repodir = packagedir, force = true}) - -- reset the previous modified files - git.reset({repodir = packagedir, hard = true}) - tty.erase_line_to_start().cr() - return - end - - -- we can use local package from the search directories directly if network is too slow - local localdir = find_directory(package:name() .. archive.extension(url), core_package.searchdirs()) - if localdir and os.isdir(localdir) then - git.clean({repodir = localdir, force = true}) - tty.erase_line_to_start().cr() - return - end - - -- remove temporary directory - os.rm(sourcedir .. ".tmp") - - -- download package from branches? - packagedir = path.join(sourcedir .. ".tmp", package:name()) - if package:branch() then - - -- only shadow clone this branch - git.clone(url, {depth = 1, recursive = true, branch = package:branch(), outputdir = packagedir}) - - -- download package from revision or tag? - else - - -- clone whole history and tags - git.clone(url, {outputdir = packagedir, recursive = true}) - - -- attempt to checkout the given version - git.checkout(package:revision(url_alias) or package:tag(), {repodir = packagedir}) - end - - -- move to source directory - os.rm(sourcedir) - os.mv(sourcedir .. ".tmp", sourcedir) - - -- trace - tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}clone %s %s .. ${color.success}${text.success}", url, package:version_str()) -end - --- download codes from ftp/http/https -function _download(package, url, sourcedir, url_alias, url_excludes) - - -- get package file - local packagefile = package:name() .. "-" .. package:version_str() .. archive.extension(url) - - -- get sourcehash from the given url - -- - -- we need not sourcehash and skip checksum to try download it directly if no version list in package() - -- @see https://github.com/xmake-io/xmake/issues/930 - -- - local sourcehash = package:sourcehash(url_alias) - if sourcehash then - sourcehash = sourcehash:lower() - end - assert(not package:get("versions") or sourcehash, "cannot get source hash of %s in package(%s)", url, package:name()) - - -- the package file have been downloaded? - local cached = true - if not os.isfile(packagefile) or sourcehash ~= hash.sha256(packagefile) then - - -- no cached - cached = false - - -- attempt to remove package file first - os.tryrm(packagefile) - - -- download or copy package file - local localfile = find_file(path.filename(packagefile), core_package.searchdirs()) - if os.isfile(url) then - os.cp(url, packagefile) - elseif localfile and os.isfile(localfile) then - -- we can use local package from the search directories directly if network is too slow - os.cp(localfile, packagefile) - else - http.download(url, packagefile) - end - - -- check hash - if sourcehash and sourcehash ~= hash.sha256(packagefile) then - raise("unmatched checksum!") - end - end - - -- extract package file - os.rm(sourcedir .. ".tmp") - if archive.extract(packagefile, sourcedir .. ".tmp", {excludes = url_excludes}) then - -- move to source directory - os.rm(sourcedir) - os.mv(sourcedir .. ".tmp", sourcedir) - else - -- create an empty source directory if do not extract package file - os.tryrm(sourcedir) - os.mkdir(sourcedir) - end - - -- save original file path - package:originfile_set(path.absolute(packagefile)) - - -- trace - tty.erase_line_to_start().cr() - if not cached then - cprint("${yellow} => ${clear}download %s .. ${color.success}${text.success}", url) - end -end - --- get sorted urls -function _urls(package) - - -- sort urls from the version source - local urls = {{}, {}} - for _, url in ipairs(package:urls()) do - if git.checkurl(url) then - table.insert(urls[1], url) - elseif not package:get("versions") or package:sourcehash(package:url_alias(url)) then - table.insert(urls[2], url) - end - end - if package:gitref() then - return table.join(urls[1], urls[2]) - else - return table.join(urls[2], urls[1]) - end -end - --- download the given package -function main(package) - - -- get working directory of this package - local workdir = package:cachedir() - - -- ensure the working directory first - os.mkdir(workdir) - - -- enter the working directory - local oldir = os.cd(workdir) - - -- lock this package - package:lock() - - -- get urls - local urls = _urls(package) - assert(#urls > 0, "cannot get url of package(%s)", package:name()) - - -- download package from urls - local ok = false - local urls_failed = {} - for idx, url in ipairs(urls) do - - -- get url alias - local url_alias = package:url_alias(url) - - -- get url excludes - local url_excludes = package:url_excludes(url) - - -- filter url - url = filter.handle(url, package) - - -- download url - ok = try - { - function () - - -- download package - local sourcedir = "source" - if git.checkurl(url) then - _checkout(package, url, sourcedir, url_alias) - else - _download(package, url, sourcedir, url_alias, url_excludes) - end - - -- ok - return true - end, - catch - { - 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) - end - - -- trace - tty.erase_line_to_start().cr() - if git.checkurl(url) then - cprint("${yellow} => ${clear}clone %s %s .. ${color.failure}${text.failure}", url, package:version_str()) - else - cprint("${yellow} => ${clear}download %s .. ${color.failure}${text.failure}", url) - end - table.insert(urls_failed, url) - - -- failed? break it - if idx == #urls and not package:optional() then - if #urls_failed > 0 then - print("") - print("we can also download these packages manually:") - local searchnames = hashset.new() - for _, url_failed in ipairs(urls_failed) do - cprint(" ${yellow}- %s", url_failed) - if git.checkurl(url_failed) then - searchnames:insert(package:name() .. archive.extension(url_failed)) - else - searchnames:insert(package:name() .. "-" .. package:version_str() .. archive.extension(url_failed)) - end - end - cprint("to the local search directories: ${bright}%s", table.concat(table.wrap(core_package.searchdirs()), path.envsep())) - 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!") - end - end - } - } - - -- ok? break it - if ok then break end - end - - -- unlock this package - package:unlock() - - -- leave working directory - os.cd(oldir) - return ok -end - - diff --git a/xmake/actions/require/impl/action/download_resources.lua b/xmake/actions/require/impl/action/download_resources.lua deleted file mode 100644 index 310a6732a..000000000 --- a/xmake/actions/require/impl/action/download_resources.lua +++ /dev/null @@ -1,96 +0,0 @@ ---!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-2020, TBOOX Open Source Group. --- --- @author ruki --- @file download_resources.lua --- - --- imports -import("core.base.option") -import("core.package.package", {alias = "core_package"}) -import("lib.detect.find_file") -import("net.http") -import("utils.archive") - --- download resources -function _download(package, resource_name, resource_url, resource_hash) - - -- trace - vprint("downloading resource(%s: %s) to %s-%s ..", resource_name, resource_url, package:name(), package:version_str()) - - -- get the resource file - local resource_file = assert(package:resourcefile(resource_name), "invalid resource file!") - - -- ensure lower hash - if resource_hash then - resource_hash = resource_hash:lower() - end - - -- the package file have been downloaded? - local cached = true - if option.get("force") or not os.isfile(resource_file) or resource_hash ~= hash.sha256(resource_file) then - - -- no cached - cached = false - - -- attempt to remove the previous file first - os.tryrm(resource_file) - - -- download or copy the resource file - local localfile = find_file(path.filename(resource_file), core_package.searchdirs()) - if localfile and os.isfile(localfile) then - -- 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(resource_url, resource_file) - else - raise("invalid resource url(%s)", resource_url) - end - - -- check hash - if resource_hash and resource_hash ~= hash.sha256(resource_file) then - raise("resource(%s): unmatched checksum!", resource_url) - end - end - - -- extract the resource file - local resourcedir = package:resourcedir(resource_name) - local resourcedir_tmp = resourcedir .. ".tmp" - os.tryrm(resourcedir_tmp) - if archive.extract(resource_file, resourcedir_tmp) then - os.tryrm(resourcedir) - os.mv(resourcedir_tmp, resourcedir) - else - os.tryrm(resourcedir_tmp) - end -end - --- download all resources of the given package -function main(package) - - -- no resources? - local resources = package:resources() - if not resources then - return - end - - -- download all resources - for name, resourceinfo in pairs(resources) do - -- we use wrap to support urls table and only get the first url now - -- TODO maybe we will download resource from the multiple urls in the future - _download(package, name, table.wrap(resourceinfo.url)[1], resourceinfo.sha256) - end -end diff --git a/xmake/actions/require/impl/action/install.lua b/xmake/actions/require/impl/action/install.lua deleted file mode 100644 index 01079bb8b..000000000 --- a/xmake/actions/require/impl/action/install.lua +++ /dev/null @@ -1,267 +0,0 @@ ---!The Make-like install 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-2020, TBOOX Open Source Group. --- --- @author ruki --- @file install.lua --- - --- imports -import("core.base.option") -import("core.base.tty") -import("core.project.target") -import("lib.detect.find_file") -import("test") -import("patch_sources") -import("download_resources") -import(".utils.filter") - --- patch pkgconfig if not exists -function _patch_pkgconfig(package) - - -- only binary? need not pkgconfig - if package:kind() == "binary" then - return - end - - -- get lib/pkgconfig/*.pc file - local pkgconfigdir = path.join(package:installdir(), "lib", "pkgconfig") - local pcfile = os.isdir(pkgconfigdir) and find_file("*.pc", pkgconfigdir) or nil - if pcfile then - return - end - - -- trace - pcfile = path.join(pkgconfigdir, package:name() .. ".pc") - 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) - - -- get working directory of this package - local workdir = package:cachedir() - - -- lock this package - package:lock() - - -- enter the working directory - local oldir = nil - if #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 - oldir = os.cd(filedirs[1]) - else - oldir = os.cd(path.join(workdir, "source")) - end - end - if not oldir then - os.mkdir(workdir) - oldir = os.cd(workdir) - end - - -- init tipname - local tipname = package:name() - if package:version_str() then - tipname = tipname .. "-" .. package:version_str() - end - - -- install it - try - { - function () - - -- the package scripts - local scripts = - { - package:script("install_before") - , package:script("install") - , package:script("install_after") - } - - -- install the third-party package directly, e.g. brew::pcre2/libpcre2-8, conan::OpenSSL/1.0.2n@conan/stable - local installed_now = false - if package:is3rd() then - local script = package:script("install") - if script ~= nil then - filter.call(script, package) - end - else - - -- build and install package to the install directory - if option.get("force") or not package:manifest_load() then - - -- 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 - - -- download package resources - download_resources(package) - - -- patch source codes of package - patch_sources(package) - - -- do install - for i = 1, 3 do - local script = scripts[i] - if script ~= nil then - filter.call(script, package) - end - end - - -- 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 - - -- patch pkg-config files for package - _patch_pkgconfig(package) - - -- test it - test(package) - end - - -- leave the package environments - package:envs_leave() - - -- trace - tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}install %s %s .. ${color.success}${text.success}", package:name(), package:version_str() or "") - end, - - catch - { - function (errors) - - -- show or save the last errors - local errorfile = path.join(package:installdir("logs"), "install.txt") - if errors then - if (option.get("verbose") or option.get("diagnosis")) then - cprint("${dim color.error}error: ${clear}%s", errors) - else - io.writefile(errorfile, errors .. "\n") - end - end - - -- trace - tty.erase_line_to_start().cr() - cprint("${yellow} => ${clear}install %s %s .. ${color.failure}${text.failure}", package:name(), package:version_str() or "") - - -- 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 - errorfile = path.join(installdir_failed, "logs", "install.txt") - end - os.tryrm(installdir) - - -- failed - if not package:requireinfo().optional then - if os.isfile(errorfile) then - print("if you want to get verbose errors, please see:") - cprint(" -> ${bright}%s", errorfile) - end - raise("install failed!") - end - end - } - } - - -- clean the empty package directory - local installdir = package:installdir() - if os.emptydir(installdir) then - os.tryrm(installdir) - end - - -- unlock this package - package:unlock() - - -- leave source codes directory - os.cd(oldir) -end diff --git a/xmake/actions/require/impl/action/patch_sources.lua b/xmake/actions/require/impl/action/patch_sources.lua deleted file mode 100644 index e7e5aa467..000000000 --- a/xmake/actions/require/impl/action/patch_sources.lua +++ /dev/null @@ -1,112 +0,0 @@ ---!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-2020, TBOOX Open Source Group. --- --- @author ruki --- @file patch_sources.lua --- - --- imports -import("core.base.option") -import("net.http") -import("devel.git") - --- check sha256 -function _check_sha256(patch_hash, patch_file) - local ok = (patch_hash == hash.sha256(patch_file)) - if not ok and is_host("windows") then - -- `git pull` maybe will replace lf to crlf in the patch text automatically on windows. - -- so we need attempt to fix this sha256 - -- - -- @see - -- https://github.com/xmake-io/xmake-repo/pull/67 - -- https://stackoverflow.com/questions/1967370/git-replacing-lf-with-crlf - -- - local tmpfile = os.tmpfile(patch_file) - os.cp(patch_file, tmpfile) - local content = io.readfile(tmpfile, {encoding = "binary"}) - content = content:gsub('\r\n', '\n') - io.writefile(tmpfile, content, {encoding = "binary"}) - ok = (patch_hash == hash.sha256(tmpfile)) - os.rm(tmpfile) - end - return ok -end - --- do patch -function _patch(package, patch_url, patch_hash) - - -- trace - vprint("patching %s to %s-%s ..", patch_url, package:name(), package:version_str()) - - -- get the patch file - local patch_file = path.join(os.tmpdir(), "patches", package:name(), package:version_str(), (path.filename(patch_url):gsub("%?.+$", ""))) - - -- ensure lower hash - if patch_hash then - patch_hash = patch_hash:lower() - end - - -- the package file have been downloaded? - local cached = true - if option.get("force") or not os.isfile(patch_file) or not _check_sha256(patch_hash, patch_file) then - - -- no cached - cached = false - - -- attempt to remove the previous file first - os.tryrm(patch_file) - - -- download the patch file - if patch_url:find(string.ipattern("https-://")) or patch_url:find(string.ipattern("ftps-://")) then - http.download(patch_url, patch_file) - else - -- copy the patch file - if os.isfile(patch_url) then - os.cp(patch_url, patch_file) - else - local scriptdir = package:scriptdir() - if scriptdir and os.isfile(path.join(scriptdir, patch_url)) then - os.cp(path.join(scriptdir, patch_url), patch_file) - else - raise("patch(%s): not found!", patch_url) - end - end - end - - -- check hash - if patch_hash and not _check_sha256(patch_hash, patch_file) then - raise("patch(%s): unmatched checksum!", patch_url) - end - end - - -- apply the patch file - git.apply(patch_file) -end - --- patch the given package -function main(package) - - -- no patches? - local patches = package:patches() - if not patches then - return - end - - -- do all patches - for _, patchinfo in ipairs(patches) do - _patch(package, patchinfo.url, patchinfo.sha256) - end -end diff --git a/xmake/actions/require/impl/action/test.lua b/xmake/actions/require/impl/action/test.lua deleted file mode 100644 index 0e1fe32b5..000000000 --- a/xmake/actions/require/impl/action/test.lua +++ /dev/null @@ -1,59 +0,0 @@ ---!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-2020, TBOOX Open Source Group. --- --- @author ruki --- @file test.lua --- - --- imports -import("core.base.option") -import(".utils.filter") - --- test the given package -function main(package) - - -- the package scripts - local scripts = - { - package:script("test_before") - , package:script("test") - , package:script("test_after") - } - - -- enter the test directory - local testdir = path.join(os.tmpdir(), "pkgtest", package:name(), package:version_str() or "latest") - if os.isdir(testdir) then - os.tryrm(testdir) - end - if not os.isdir(testdir) then - os.mkdir(testdir) - end - local oldir = os.cd(testdir) - - -- test it - for i = 1, 3 do - local script = scripts[i] - if script ~= nil then - filter.call(script, package) - end - end - - -- restore the current directory - os.cd(oldir) - - -- remove the test directory - os.tryrm(testdir) -end diff --git a/xmake/actions/require/impl/actions/download.lua b/xmake/actions/require/impl/actions/download.lua new file mode 100644 index 000000000..57f28989f --- /dev/null +++ b/xmake/actions/require/impl/actions/download.lua @@ -0,0 +1,275 @@ +--!The Make-like download 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-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file download.lua +-- + +-- imports +import("core.base.option") +import("core.base.tty") +import("core.base.hashset") +import("core.project.config") +import("core.package.package", {alias = "core_package"}) +import("lib.detect.find_file") +import("lib.detect.find_directory") +import(".utils.filter") +import("net.http") +import("devel.git") +import("utils.archive") + +-- checkout codes from git +function _checkout(package, url, sourcedir, url_alias) + + -- use previous source directory if exists + local packagedir = path.join(sourcedir, package:name()) + if os.isdir(packagedir) and + not (option.get("force") and package:branch()) then -- we need disable cache if we force to clone from the given branch + + -- clean the previous build files + git.clean({repodir = packagedir, force = true}) + -- reset the previous modified files + git.reset({repodir = packagedir, hard = true}) + tty.erase_line_to_start().cr() + return + end + + -- we can use local package from the search directories directly if network is too slow + local localdir = find_directory(package:name() .. archive.extension(url), core_package.searchdirs()) + if localdir and os.isdir(localdir) then + git.clean({repodir = localdir, force = true}) + tty.erase_line_to_start().cr() + return + end + + -- remove temporary directory + os.rm(sourcedir .. ".tmp") + + -- download package from branches? + packagedir = path.join(sourcedir .. ".tmp", package:name()) + if package:branch() then + + -- only shadow clone this branch + git.clone(url, {depth = 1, recursive = true, branch = package:branch(), outputdir = packagedir}) + + -- download package from revision or tag? + else + + -- clone whole history and tags + git.clone(url, {outputdir = packagedir, recursive = true}) + + -- attempt to checkout the given version + git.checkout(package:revision(url_alias) or package:tag(), {repodir = packagedir}) + end + + -- move to source directory + os.rm(sourcedir) + os.mv(sourcedir .. ".tmp", sourcedir) + + -- trace + tty.erase_line_to_start().cr() + cprint("${yellow} => ${clear}clone %s %s .. ${color.success}${text.success}", url, package:version_str()) +end + +-- download codes from ftp/http/https +function _download(package, url, sourcedir, url_alias, url_excludes) + + -- get package file + local packagefile = package:name() .. "-" .. package:version_str() .. archive.extension(url) + + -- get sourcehash from the given url + -- + -- we need not sourcehash and skip checksum to try download it directly if no version list in package() + -- @see https://github.com/xmake-io/xmake/issues/930 + -- + local sourcehash = package:sourcehash(url_alias) + if sourcehash then + sourcehash = sourcehash:lower() + end + assert(not package:get("versions") or sourcehash, "cannot get source hash of %s in package(%s)", url, package:name()) + + -- the package file have been downloaded? + local cached = true + if not os.isfile(packagefile) or sourcehash ~= hash.sha256(packagefile) then + + -- no cached + cached = false + + -- attempt to remove package file first + os.tryrm(packagefile) + + -- download or copy package file + local localfile = find_file(path.filename(packagefile), core_package.searchdirs()) + if os.isfile(url) then + os.cp(url, packagefile) + elseif localfile and os.isfile(localfile) then + -- we can use local package from the search directories directly if network is too slow + os.cp(localfile, packagefile) + else + http.download(url, packagefile) + end + + -- check hash + if sourcehash and sourcehash ~= hash.sha256(packagefile) then + raise("unmatched checksum!") + end + end + + -- extract package file + os.rm(sourcedir .. ".tmp") + if archive.extract(packagefile, sourcedir .. ".tmp", {excludes = url_excludes}) then + -- move to source directory + os.rm(sourcedir) + os.mv(sourcedir .. ".tmp", sourcedir) + else + -- create an empty source directory if do not extract package file + os.tryrm(sourcedir) + os.mkdir(sourcedir) + end + + -- save original file path + package:originfile_set(path.absolute(packagefile)) + + -- trace + tty.erase_line_to_start().cr() + if not cached then + cprint("${yellow} => ${clear}download %s .. ${color.success}${text.success}", url) + end +end + +-- get sorted urls +function _urls(package) + + -- sort urls from the version source + local urls = {{}, {}} + for _, url in ipairs(package:urls()) do + if git.checkurl(url) then + table.insert(urls[1], url) + elseif not package:get("versions") or package:sourcehash(package:url_alias(url)) then + table.insert(urls[2], url) + end + end + if package:gitref() then + return table.join(urls[1], urls[2]) + else + return table.join(urls[2], urls[1]) + end +end + +-- download the given package +function main(package) + + -- get working directory of this package + local workdir = package:cachedir() + + -- ensure the working directory first + os.mkdir(workdir) + + -- enter the working directory + local oldir = os.cd(workdir) + + -- lock this package + package:lock() + + -- get urls + local urls = _urls(package) + assert(#urls > 0, "cannot get url of package(%s)", package:name()) + + -- download package from urls + local ok = false + local urls_failed = {} + for idx, url in ipairs(urls) do + + -- get url alias + local url_alias = package:url_alias(url) + + -- get url excludes + local url_excludes = package:url_excludes(url) + + -- filter url + url = filter.handle(url, package) + + -- download url + ok = try + { + function () + + -- download package + local sourcedir = "source" + if git.checkurl(url) then + _checkout(package, url, sourcedir, url_alias) + else + _download(package, url, sourcedir, url_alias, url_excludes) + end + + -- ok + return true + end, + catch + { + 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) + end + + -- trace + tty.erase_line_to_start().cr() + if git.checkurl(url) then + cprint("${yellow} => ${clear}clone %s %s .. ${color.failure}${text.failure}", url, package:version_str()) + else + cprint("${yellow} => ${clear}download %s .. ${color.failure}${text.failure}", url) + end + table.insert(urls_failed, url) + + -- failed? break it + if idx == #urls and not package:optional() then + if #urls_failed > 0 then + print("") + print("we can also download these packages manually:") + local searchnames = hashset.new() + for _, url_failed in ipairs(urls_failed) do + cprint(" ${yellow}- %s", url_failed) + if git.checkurl(url_failed) then + searchnames:insert(package:name() .. archive.extension(url_failed)) + else + searchnames:insert(package:name() .. "-" .. package:version_str() .. archive.extension(url_failed)) + end + end + cprint("to the local search directories: ${bright}%s", table.concat(table.wrap(core_package.searchdirs()), path.envsep())) + 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!") + end + end + } + } + + -- ok? break it + if ok then break end + end + + -- unlock this package + package:unlock() + + -- leave working directory + os.cd(oldir) + return ok +end + + diff --git a/xmake/actions/require/impl/actions/download_resources.lua b/xmake/actions/require/impl/actions/download_resources.lua new file mode 100644 index 000000000..310a6732a --- /dev/null +++ b/xmake/actions/require/impl/actions/download_resources.lua @@ -0,0 +1,96 @@ +--!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-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file download_resources.lua +-- + +-- imports +import("core.base.option") +import("core.package.package", {alias = "core_package"}) +import("lib.detect.find_file") +import("net.http") +import("utils.archive") + +-- download resources +function _download(package, resource_name, resource_url, resource_hash) + + -- trace + vprint("downloading resource(%s: %s) to %s-%s ..", resource_name, resource_url, package:name(), package:version_str()) + + -- get the resource file + local resource_file = assert(package:resourcefile(resource_name), "invalid resource file!") + + -- ensure lower hash + if resource_hash then + resource_hash = resource_hash:lower() + end + + -- the package file have been downloaded? + local cached = true + if option.get("force") or not os.isfile(resource_file) or resource_hash ~= hash.sha256(resource_file) then + + -- no cached + cached = false + + -- attempt to remove the previous file first + os.tryrm(resource_file) + + -- download or copy the resource file + local localfile = find_file(path.filename(resource_file), core_package.searchdirs()) + if localfile and os.isfile(localfile) then + -- 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(resource_url, resource_file) + else + raise("invalid resource url(%s)", resource_url) + end + + -- check hash + if resource_hash and resource_hash ~= hash.sha256(resource_file) then + raise("resource(%s): unmatched checksum!", resource_url) + end + end + + -- extract the resource file + local resourcedir = package:resourcedir(resource_name) + local resourcedir_tmp = resourcedir .. ".tmp" + os.tryrm(resourcedir_tmp) + if archive.extract(resource_file, resourcedir_tmp) then + os.tryrm(resourcedir) + os.mv(resourcedir_tmp, resourcedir) + else + os.tryrm(resourcedir_tmp) + end +end + +-- download all resources of the given package +function main(package) + + -- no resources? + local resources = package:resources() + if not resources then + return + end + + -- download all resources + for name, resourceinfo in pairs(resources) do + -- we use wrap to support urls table and only get the first url now + -- TODO maybe we will download resource from the multiple urls in the future + _download(package, name, table.wrap(resourceinfo.url)[1], resourceinfo.sha256) + end +end diff --git a/xmake/actions/require/impl/actions/install.lua b/xmake/actions/require/impl/actions/install.lua new file mode 100644 index 000000000..01079bb8b --- /dev/null +++ b/xmake/actions/require/impl/actions/install.lua @@ -0,0 +1,267 @@ +--!The Make-like install 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-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file install.lua +-- + +-- imports +import("core.base.option") +import("core.base.tty") +import("core.project.target") +import("lib.detect.find_file") +import("test") +import("patch_sources") +import("download_resources") +import(".utils.filter") + +-- patch pkgconfig if not exists +function _patch_pkgconfig(package) + + -- only binary? need not pkgconfig + if package:kind() == "binary" then + return + end + + -- get lib/pkgconfig/*.pc file + local pkgconfigdir = path.join(package:installdir(), "lib", "pkgconfig") + local pcfile = os.isdir(pkgconfigdir) and find_file("*.pc", pkgconfigdir) or nil + if pcfile then + return + end + + -- trace + pcfile = path.join(pkgconfigdir, package:name() .. ".pc") + 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) + + -- get working directory of this package + local workdir = package:cachedir() + + -- lock this package + package:lock() + + -- enter the working directory + local oldir = nil + if #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 + oldir = os.cd(filedirs[1]) + else + oldir = os.cd(path.join(workdir, "source")) + end + end + if not oldir then + os.mkdir(workdir) + oldir = os.cd(workdir) + end + + -- init tipname + local tipname = package:name() + if package:version_str() then + tipname = tipname .. "-" .. package:version_str() + end + + -- install it + try + { + function () + + -- the package scripts + local scripts = + { + package:script("install_before") + , package:script("install") + , package:script("install_after") + } + + -- install the third-party package directly, e.g. brew::pcre2/libpcre2-8, conan::OpenSSL/1.0.2n@conan/stable + local installed_now = false + if package:is3rd() then + local script = package:script("install") + if script ~= nil then + filter.call(script, package) + end + else + + -- build and install package to the install directory + if option.get("force") or not package:manifest_load() then + + -- 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 + + -- download package resources + download_resources(package) + + -- patch source codes of package + patch_sources(package) + + -- do install + for i = 1, 3 do + local script = scripts[i] + if script ~= nil then + filter.call(script, package) + end + end + + -- 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 + + -- patch pkg-config files for package + _patch_pkgconfig(package) + + -- test it + test(package) + end + + -- leave the package environments + package:envs_leave() + + -- trace + tty.erase_line_to_start().cr() + cprint("${yellow} => ${clear}install %s %s .. ${color.success}${text.success}", package:name(), package:version_str() or "") + end, + + catch + { + function (errors) + + -- show or save the last errors + local errorfile = path.join(package:installdir("logs"), "install.txt") + if errors then + if (option.get("verbose") or option.get("diagnosis")) then + cprint("${dim color.error}error: ${clear}%s", errors) + else + io.writefile(errorfile, errors .. "\n") + end + end + + -- trace + tty.erase_line_to_start().cr() + cprint("${yellow} => ${clear}install %s %s .. ${color.failure}${text.failure}", package:name(), package:version_str() or "") + + -- 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 + errorfile = path.join(installdir_failed, "logs", "install.txt") + end + os.tryrm(installdir) + + -- failed + if not package:requireinfo().optional then + if os.isfile(errorfile) then + print("if you want to get verbose errors, please see:") + cprint(" -> ${bright}%s", errorfile) + end + raise("install failed!") + end + end + } + } + + -- clean the empty package directory + local installdir = package:installdir() + if os.emptydir(installdir) then + os.tryrm(installdir) + end + + -- unlock this package + package:unlock() + + -- leave source codes directory + os.cd(oldir) +end diff --git a/xmake/actions/require/impl/actions/patch_sources.lua b/xmake/actions/require/impl/actions/patch_sources.lua new file mode 100644 index 000000000..e7e5aa467 --- /dev/null +++ b/xmake/actions/require/impl/actions/patch_sources.lua @@ -0,0 +1,112 @@ +--!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-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file patch_sources.lua +-- + +-- imports +import("core.base.option") +import("net.http") +import("devel.git") + +-- check sha256 +function _check_sha256(patch_hash, patch_file) + local ok = (patch_hash == hash.sha256(patch_file)) + if not ok and is_host("windows") then + -- `git pull` maybe will replace lf to crlf in the patch text automatically on windows. + -- so we need attempt to fix this sha256 + -- + -- @see + -- https://github.com/xmake-io/xmake-repo/pull/67 + -- https://stackoverflow.com/questions/1967370/git-replacing-lf-with-crlf + -- + local tmpfile = os.tmpfile(patch_file) + os.cp(patch_file, tmpfile) + local content = io.readfile(tmpfile, {encoding = "binary"}) + content = content:gsub('\r\n', '\n') + io.writefile(tmpfile, content, {encoding = "binary"}) + ok = (patch_hash == hash.sha256(tmpfile)) + os.rm(tmpfile) + end + return ok +end + +-- do patch +function _patch(package, patch_url, patch_hash) + + -- trace + vprint("patching %s to %s-%s ..", patch_url, package:name(), package:version_str()) + + -- get the patch file + local patch_file = path.join(os.tmpdir(), "patches", package:name(), package:version_str(), (path.filename(patch_url):gsub("%?.+$", ""))) + + -- ensure lower hash + if patch_hash then + patch_hash = patch_hash:lower() + end + + -- the package file have been downloaded? + local cached = true + if option.get("force") or not os.isfile(patch_file) or not _check_sha256(patch_hash, patch_file) then + + -- no cached + cached = false + + -- attempt to remove the previous file first + os.tryrm(patch_file) + + -- download the patch file + if patch_url:find(string.ipattern("https-://")) or patch_url:find(string.ipattern("ftps-://")) then + http.download(patch_url, patch_file) + else + -- copy the patch file + if os.isfile(patch_url) then + os.cp(patch_url, patch_file) + else + local scriptdir = package:scriptdir() + if scriptdir and os.isfile(path.join(scriptdir, patch_url)) then + os.cp(path.join(scriptdir, patch_url), patch_file) + else + raise("patch(%s): not found!", patch_url) + end + end + end + + -- check hash + if patch_hash and not _check_sha256(patch_hash, patch_file) then + raise("patch(%s): unmatched checksum!", patch_url) + end + end + + -- apply the patch file + git.apply(patch_file) +end + +-- patch the given package +function main(package) + + -- no patches? + local patches = package:patches() + if not patches then + return + end + + -- do all patches + for _, patchinfo in ipairs(patches) do + _patch(package, patchinfo.url, patchinfo.sha256) + end +end diff --git a/xmake/actions/require/impl/actions/test.lua b/xmake/actions/require/impl/actions/test.lua new file mode 100644 index 000000000..0e1fe32b5 --- /dev/null +++ b/xmake/actions/require/impl/actions/test.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-2020, TBOOX Open Source Group. +-- +-- @author ruki +-- @file test.lua +-- + +-- imports +import("core.base.option") +import(".utils.filter") + +-- test the given package +function main(package) + + -- the package scripts + local scripts = + { + package:script("test_before") + , package:script("test") + , package:script("test_after") + } + + -- enter the test directory + local testdir = path.join(os.tmpdir(), "pkgtest", package:name(), package:version_str() or "latest") + if os.isdir(testdir) then + os.tryrm(testdir) + end + if not os.isdir(testdir) then + os.mkdir(testdir) + end + local oldir = os.cd(testdir) + + -- test it + for i = 1, 3 do + local script = scripts[i] + if script ~= nil then + filter.call(script, package) + end + end + + -- restore the current directory + os.cd(oldir) + + -- remove the test directory + os.tryrm(testdir) +end diff --git a/xmake/actions/require/impl/package.lua b/xmake/actions/require/impl/package.lua index eb36b1467..b1177fb8a 100644 --- a/xmake/actions/require/impl/package.lua +++ b/xmake/actions/require/impl/package.lua @@ -30,7 +30,8 @@ import("private.utils.progress") import("lib.detect.cache", {alias = "detectcache"}) import("core.project.project") import("core.package.package", {alias = "core_package"}) -import("action") +import("actions.install", {alias = "action_install"}) +import("actions.download", {alias = "action_download"}) import("devel.git") import("net.fasturl") import("repository") @@ -628,14 +629,14 @@ function _install_packages(packages_install, packages_download) local downloaded = true if packages_download[tostring(package)] then packages_downloading[index] = package - downloaded = action.download(package) + downloaded = action_download(package) packages_downloading[index] = nil end -- install this package packages_installing[index] = package if downloaded then - action.install(package) + action_install(package) end packages_installing[index] = nil diff --git a/xmake/modules/action/install/main.lua b/xmake/modules/action/install/main.lua index 51ced360f..f518abdd6 100644 --- a/xmake/modules/action/install/main.lua +++ b/xmake/modules/action/install/main.lua @@ -35,7 +35,7 @@ function _install_files(target) end -- the builtin install main entry -function main(target) +function main(target, opt) -- get install directory local installdir = target:installdir() @@ -51,7 +51,7 @@ function main(target) local install_style = target:is_plat("windows", "mingw") and "windows" or "unix" local script = import(install_style, {anonymous = true})["install_" .. target:targetkind()] if script then - script(target) + script(target, opt) end end diff --git a/xmake/modules/action/install/unix.lua b/xmake/modules/action/install/unix.lua index 634dd2e3a..e52b091b1 100644 --- a/xmake/modules/action/install/unix.lua +++ b/xmake/modules/action/install/unix.lua @@ -19,15 +19,15 @@ -- -- install library -function _install_library(target) +function _install_library(target, opt) -- install libraries - local librarydir = path.join(target:installdir(), "lib") + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") os.mkdir(librarydir) os.vcp(target:targetfile(), librarydir) -- install headers - local includedir = path.join(target:installdir(), "include") + local includedir = path.join(target:installdir(), opt and opt.includedir or "include") os.mkdir(includedir) local srcheaders, dstheaders = target:headerfiles(includedir) if srcheaders and dstheaders then @@ -43,18 +43,18 @@ function _install_library(target) end -- install binary -function install_binary(target) - local binarydir = path.join(target:installdir(), "bin") +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) end -- install shared library -function install_shared(target) - _install_library(target) +function install_shared(target, opt) + _install_library(target, opt) end -- install static library -function install_static(target) - _install_library(target) +function install_static(target, opt) + _install_library(target, opt) end diff --git a/xmake/modules/action/install/windows.lua b/xmake/modules/action/install/windows.lua index 3019152d1..7e9f6ab0b 100644 --- a/xmake/modules/action/install/windows.lua +++ b/xmake/modules/action/install/windows.lua @@ -22,8 +22,8 @@ import("lib.detect.find_file") -- install headers -function _install_headers(target) - local includedir = path.join(target:installdir(), "include") +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) if srcheaders and dstheaders then @@ -66,10 +66,10 @@ function _install_shared_for_packages(target, outputdir) end -- install binary -function install_binary(target) +function install_binary(target, opt) -- install binary - local binarydir = path.join(target:installdir(), "bin") + local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.mkdir(binarydir) os.vcp(target:targetfile(), binarydir) @@ -89,17 +89,17 @@ function install_binary(target) end -- install shared library -function install_shared(target) +function install_shared(target, opt) -- install dll library to the binary directory - local binarydir = path.join(target:installdir(), "bin") + local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.mkdir(binarydir) os.vcp(target:targetfile(), 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(), "lib") + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") local targetfile_lib = path.join(path.directory(targetfile), path.basename(targetfile) .. ".lib") if os.isfile(targetfile_lib) then os.mkdir(librarydir) @@ -110,17 +110,17 @@ function install_shared(target) _install_shared_for_packages(target, binarydir) -- install headers - _install_headers(target) + _install_headers(target, opt) end -- install static library -function install_static(target) +function install_static(target, opt) -- install library - local librarydir = path.join(target:installdir(), "lib") + 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) + _install_headers(target, opt) end diff --git a/xmake/modules/action/uninstall/main.lua b/xmake/modules/action/uninstall/main.lua index fe9b7e2db..440752725 100644 --- a/xmake/modules/action/uninstall/main.lua +++ b/xmake/modules/action/uninstall/main.lua @@ -27,7 +27,7 @@ function _uninstall_files(target) end -- the builtin uninstall main entry -function main(target) +function main(target, opt) -- get install directory local installdir = target:installdir() @@ -43,7 +43,7 @@ function main(target) local install_style = target:is_plat("windows", "mingw") and "windows" or "unix" local script = import(install_style, {anonymous = true})["uninstall_" .. target:targetkind()] if script then - script(target) + script(target, opt) end end diff --git a/xmake/modules/action/uninstall/unix.lua b/xmake/modules/action/uninstall/unix.lua index 90f07d364..f7423da0a 100644 --- a/xmake/modules/action/uninstall/unix.lua +++ b/xmake/modules/action/uninstall/unix.lua @@ -19,14 +19,14 @@ -- -- uninstall library -function _uninstall_library(target) +function _uninstall_library(target, opt) -- remove the target file - local librarydir = path.join(target:installdir(), "lib") + 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 - local includedir = path.join(target:installdir(), "include") + local includedir = path.join(target:installdir(), opt and opt.includedir or "include") local _, dstheaders = target:headerfiles(includedir) for _, dstheader in ipairs(dstheaders) do os.vrm(dstheader) @@ -34,17 +34,17 @@ function _uninstall_library(target) end -- uninstall binary -function uninstall_binary(target) - local binarydir = path.join(target:installdir(), "bin") +function uninstall_binary(target, opt) + local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.vrm(path.join(binarydir, path.filename(target:targetfile()))) end -- uninstall shared library -function uninstall_shared(target) - _uninstall_library(target) +function uninstall_shared(target, opt) + _uninstall_library(target, opt) end -- uninstall static library -function uninstall_static(target) - _uninstall_library(target) +function uninstall_static(target, opt) + _uninstall_library(target, opt) end diff --git a/xmake/modules/action/uninstall/windows.lua b/xmake/modules/action/uninstall/windows.lua index 865e80c7e..d4ddf88a2 100644 --- a/xmake/modules/action/uninstall/windows.lua +++ b/xmake/modules/action/uninstall/windows.lua @@ -19,8 +19,8 @@ -- -- uninstall headers -function _uninstall_headers(target) - local includedir = path.join(target:installdir(), "include") +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 os.vrm(dstheader) @@ -52,10 +52,10 @@ function _uninstall_shared_for_packages(target, outputdir) end -- uninstall binary -function uninstall_binary(target) +function uninstall_binary(target, opt) -- remove the target file - local binarydir = path.join(target:installdir(), "bin") + 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/windows (*.dll) target @@ -71,32 +71,32 @@ function uninstall_binary(target) end -- uninstall shared library -function uninstall_shared(target) +function uninstall_shared(target, opt) -- remove the target file - local binarydir = path.join(target:installdir(), "bin") + local binarydir = path.join(target:installdir(), opt and opt.bindir or "bin") os.vrm(path.join(binarydir, path.filename(target:targetfile()))) -- 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(), "lib") + local librarydir = path.join(target:installdir(), opt and opt.libdir or "lib") os.vrm(path.join(librarydir, path.basename(targetfile) .. ".lib")) -- remove headers from the include directory - _uninstall_headers(target) + _uninstall_headers(target, opt) -- uninstall shared libraries for packages _uninstall_shared_for_packages(target, binarydir) end -- uninstall static library -function uninstall_static(target) +function uninstall_static(target, opt) -- remove the target file - local librarydir = path.join(target:installdir(), "lib") + 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) + _uninstall_headers(target, opt) end -- cgit v1.3.1