From a6c95c916e566de85a5620904d0db5728d781a7d Mon Sep 17 00:00:00 2001 From: Lingfeng Fu <2871618714@qq.com> Date: Fri, 9 Jun 2023 23:17:41 +0800 Subject: [PATCH 1/4] add zypper support --- xmake/modules/detect/tools/find_rpm.lua | 54 +++++++ xmake/modules/detect/tools/find_zypper.lua | 54 +++++++ .../package/manager/zypper/find_package.lua | 152 ++++++++++++++++++ .../manager/zypper/install_package.lua | 62 +++++++ .../package/manager/zypper/search_package.lua | 59 +++++++ 5 files changed, 381 insertions(+) create mode 100644 xmake/modules/detect/tools/find_rpm.lua create mode 100644 xmake/modules/detect/tools/find_zypper.lua create mode 100644 xmake/modules/package/manager/zypper/find_package.lua create mode 100644 xmake/modules/package/manager/zypper/install_package.lua create mode 100644 xmake/modules/package/manager/zypper/search_package.lua diff --git a/xmake/modules/detect/tools/find_rpm.lua b/xmake/modules/detect/tools/find_rpm.lua new file mode 100644 index 00000000000..02c59b5e3da --- /dev/null +++ b/xmake/modules/detect/tools/find_rpm.lua @@ -0,0 +1,54 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Lingfeng Fu +-- @file find_rpm.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find rpm +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local rpm = find_rpm() +-- local rpm, version = find_rpm({version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "rpm", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + + -- ok? + return program, version +end diff --git a/xmake/modules/detect/tools/find_zypper.lua b/xmake/modules/detect/tools/find_zypper.lua new file mode 100644 index 00000000000..cc0fb0445d8 --- /dev/null +++ b/xmake/modules/detect/tools/find_zypper.lua @@ -0,0 +1,54 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Lingfeng Fu +-- @file find_zypper.lua +-- + +-- imports +import("lib.detect.find_program") +import("lib.detect.find_programver") + +-- find zypper +-- +-- @param opt the argument options, e.g. {version = true} +-- +-- @return program, version +-- +-- @code +-- +-- local zypper = find_zypper() +-- local zypper, version = find_zypper({version = true}) +-- +-- @endcode +-- +function main(opt) + + -- init options + opt = opt or {} + + -- find program + local program = find_program(opt.program or "zypper", opt) + + -- find program version + local version = nil + if program and opt and opt.version then + version = find_programver(program, opt) + end + + -- ok? + return program, version +end \ No newline at end of file diff --git a/xmake/modules/package/manager/zypper/find_package.lua b/xmake/modules/package/manager/zypper/find_package.lua new file mode 100644 index 00000000000..53db5467ea1 --- /dev/null +++ b/xmake/modules/package/manager/zypper/find_package.lua @@ -0,0 +1,152 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Lingfeng Fu +-- @file find_package.lua +-- + +-- imports +import("core.base.option") +import("core.project.config") +import("core.project.target") +import("lib.detect.find_tool") +import("package.manager.pkgconfig.find_package", { alias = "find_package_from_pkgconfig" }) + +-- find package +function _find_package(rpm, zypper, name, opt) + local result = nil + local pkgconfig_files = {} + local listinfo = try { function() + return os.iorunv(rpm.program, { "-ql", name }) + end } + if listinfo then + for _, line in ipairs(listinfo:split('\n', { plain = true })) do + line = line:trim() + + -- get includedirs + local pos = line:find("include/", 1, true) + if pos then + -- we need not add includedirs, gcc/clang will use /usr/ as default sysroot + result = result or {} + end + + -- get pc files + if line:find("/pkgconfig/", 1, true) and line:endswith(".pc") then + table.insert(pkgconfig_files, line) + end + + -- get linkdirs and links + if line:endswith(".a") or line:endswith(".so") then + result = result or {} + result.links = result.links or {} + result.linkdirs = result.linkdirs or {} + result.libfiles = result.libfiles or {} + table.insert(result.linkdirs, path.directory(line)) + table.insert(result.links, target.linkname(path.filename(line), { plat = opt.plat })) + table.insert(result.libfiles, path.join(path.directory(line), path.filename(line))) + end + end + end + + -- we iterate over each pkgconfig file to extract the required data + local foundpc = false + local pcresult = { includedirs = {}, linkdirs = {}, links = {} } + for _, pkgconfig_file in ipairs(pkgconfig_files) do + local pkgconfig_dir = path.directory(pkgconfig_file) + local pkgconfig_name = path.basename(pkgconfig_file) + local pcinfo = find_package_from_pkgconfig(pkgconfig_name, { configdirs = pkgconfig_dir, linkdirs = linkdirs }) + + -- the pkgconfig file has been parse successfully + if pcinfo then + for _, includedir in ipairs(pcinfo.includedirs) do + table.insert(pcresult.includedirs, includedir) + end + for _, linkdir in ipairs(pcinfo.linkdirs) do + table.insert(pcresult.linkdirs, linkdir) + end + for _, link in ipairs(pcinfo.links) do + table.insert(pcresult.links, link) + end + -- version should be the same if a pacman package contains multiples .pc + pcresult.version = pcinfo.version + foundpc = true + end + end + if foundpc == true then + pcresult.includedirs = table.unique(pcresult.includedirs) + pcresult.linkdirs = table.unique(pcresult.linkdirs) + pcresult.links = table.reverse_unique(pcresult.links) + result = pcresult + end + + -- meta/alias package? e.g. libboost_headers-devel -> libboost_headers1_82_0-devel + -- @see https://github.com/xmake-io/xmake/issues/1786 + if not result then + local statusinfo = try { function() + return os.iorunv(zypper.program, { "info", "--requires", name }) + end } + if statusinfo then + for _, line in ipairs(statusinfo:split("\n", { plain = true })) do + -- parse depends, e.g. Depends: libboost1.74-dev + if line:startswith("Requires") then + local depends = line:split("^Requires%s+:%s+") + if #depends == 1 then + return _find_package(rpm, zypper, depends[1], opt) + end + break + end + end + end + end + + -- remove repeat + if result then + if result.links then + result.links = table.unique(result.links) + end + if result.linkdirs then + result.linkdirs = table.unique(result.linkdirs) + end + if result.includedirs then + result.includedirs = table.unique(result.includedirs) + end + end + return result +end + +-- find package using the rpm package manager +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true, version = "1.12.0") +-- +function main(name, opt) + + -- check + opt = opt or {} + if not is_host(opt.plat) or os.arch() ~= opt.arch then + return + end + + -- find rpm and zypper + local rpm = find_tool("rpm") + local zypper = find_tool("zypper") + if not (rpm and zypper) then + return + end + + -- find package + return _find_package(rpm, zypper, name, opt) +end diff --git a/xmake/modules/package/manager/zypper/install_package.lua b/xmake/modules/package/manager/zypper/install_package.lua new file mode 100644 index 00000000000..8beb45ff1ce --- /dev/null +++ b/xmake/modules/package/manager/zypper/install_package.lua @@ -0,0 +1,62 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Lingfeng Fu +-- @file install_package.lua +-- + +-- imports +import("core.base.option") +import("lib.detect.find_tool") +import("privilege.sudo") + +-- install package +-- +-- @param name the package name +-- @param opt the options, e.g. {verbose = true, apt = "the package name"} +-- +-- @return true or false +-- +function main(name, opt) + + -- init options + opt = opt or {} + + -- find apt + local zypper = find_tool("zypper") + if not zypper then + raise("apt not found!") + end + + -- init argv + local argv = { "install", "-y", opt.zypper or name } + + -- install package directly if the current user is root + if os.isroot() then + os.vrunv(zypper.program, argv) + -- install with administrator permission? + elseif sudo.has() then + + -- install it if be confirmed + local description = format("try installing %s with administrator permission", name) + local confirm = utils.confirm({ default = true, description = description }) + if confirm then + sudo.vrunv(zypper.program, argv) + end + else + raise("cannot get administrator permission!") + end +end diff --git a/xmake/modules/package/manager/zypper/search_package.lua b/xmake/modules/package/manager/zypper/search_package.lua new file mode 100644 index 00000000000..daa8714d504 --- /dev/null +++ b/xmake/modules/package/manager/zypper/search_package.lua @@ -0,0 +1,59 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Lingfeng Fu +-- @file search_package.lua +-- + +-- imports +import("core.base.option") +import("lib.detect.find_tool") + +-- search package using the zypper package manager +-- +-- @param name the package name with pattern +-- +function main(name) + + -- find zypper + local zypper = find_tool("zypper") + if not zypper then + raise("zypper not found!") + end + + -- search packages + -- + -- | libboost_wave-devel | Development headers for Boost.Wave library | package + -- + -- i | libboost_wave-devel | Development headers for Boost.Wave library | package + -- + -- i+ | libboost_headers-devel | Development headers for Boost | package + -- + local results = {} + local searchdata = os.iorunv(zypper.program, { "search", name }) + for _, line in ipairs(searchdata:split("\n", { plain = true })) do + if line:endswith("package") then + local splitinfo = line:split("%s+|%s+", { limit = 4 }) + if not line:startswith(" ") then + table.remove(splitinfo, 1) + end + local packagename = splitinfo[1] + local description = splitinfo[2] + table.insert(results, { name = "zypper::" .. packagename, version = version, description = description }) + end + end + return results +end From 02c2e064b27b6041a9f75890154a731d064b8618 Mon Sep 17 00:00:00 2001 From: Lingfeng Fu <2871618714@qq.com> Date: Fri, 9 Jun 2023 23:32:08 +0800 Subject: [PATCH 2/4] update README to show zypper support --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cbc727dcaf7..73918f83d38 100644 --- a/README.md +++ b/README.md @@ -326,6 +326,7 @@ Xmake can automatically fetch and install dependencies! * Portage on Gentoo/Linux (portage::libhandy) * Nimble for nimlang (nimble::zip >1.3) * Cargo for rust (cargo::base64 0.13.0) +* Zypper on openSUSE (zypper::libsfml2-2_5) ### Package management features From b4194846cb1cb140c93897aa07d70a3b5013c6c5 Mon Sep 17 00:00:00 2001 From: Lingfeng Fu <2871618714@qq.com> Date: Sun, 11 Jun 2023 21:22:28 +0800 Subject: [PATCH 3/4] support version opt for zypper --- README.md | 2 +- xmake/modules/package/manager/install_package.lua | 1 + xmake/modules/package/manager/zypper/find_package.lua | 3 +++ xmake/modules/package/manager/zypper/install_package.lua | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73918f83d38..082f415fca2 100644 --- a/README.md +++ b/README.md @@ -326,7 +326,7 @@ Xmake can automatically fetch and install dependencies! * Portage on Gentoo/Linux (portage::libhandy) * Nimble for nimlang (nimble::zip >1.3) * Cargo for rust (cargo::base64 0.13.0) -* Zypper on openSUSE (zypper::libsfml2-2_5) +* Zypper on openSUSE (zypper::libsfml2 2.5) ### Package management features diff --git a/xmake/modules/package/manager/install_package.lua b/xmake/modules/package/manager/install_package.lua index 05e13ed2745..71664aefe7a 100644 --- a/xmake/modules/package/manager/install_package.lua +++ b/xmake/modules/package/manager/install_package.lua @@ -40,6 +40,7 @@ function _install_package(manager_name, package_name, opt) table.insert(managers, "pacman") table.insert(managers, "portage") table.insert(managers, "brew") + table.insert(managers, "zypper") elseif is_host("macosx") then table.insert(managers, "vcpkg") table.insert(managers, "brew") diff --git a/xmake/modules/package/manager/zypper/find_package.lua b/xmake/modules/package/manager/zypper/find_package.lua index 53db5467ea1..d26f566ded3 100644 --- a/xmake/modules/package/manager/zypper/find_package.lua +++ b/xmake/modules/package/manager/zypper/find_package.lua @@ -27,6 +27,9 @@ import("package.manager.pkgconfig.find_package", { alias = "find_package_from_pk -- find package function _find_package(rpm, zypper, name, opt) + if opt.require_version and opt.require_version ~= "latest" then + name = name .. '-' .. opt.require_version:gsub('%.', '_') + end local result = nil local pkgconfig_files = {} local listinfo = try { function() diff --git a/xmake/modules/package/manager/zypper/install_package.lua b/xmake/modules/package/manager/zypper/install_package.lua index 8beb45ff1ce..8f2f60febdf 100644 --- a/xmake/modules/package/manager/zypper/install_package.lua +++ b/xmake/modules/package/manager/zypper/install_package.lua @@ -34,6 +34,9 @@ function main(name, opt) -- init options opt = opt or {} + if opt.require_version and opt.require_version ~= "latest" then + name = name .. '-' .. opt.require_version:gsub('%.', '_') + end -- find apt local zypper = find_tool("zypper") From 4551722902ed70c1f8c44b0f671d257cca72d7a8 Mon Sep 17 00:00:00 2001 From: Lingfeng Fu <2871618714@qq.com> Date: Sun, 11 Jun 2023 21:26:09 +0800 Subject: [PATCH 4/4] improve zypper find_package --- .../package/manager/zypper/find_package.lua | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/xmake/modules/package/manager/zypper/find_package.lua b/xmake/modules/package/manager/zypper/find_package.lua index d26f566ded3..20e14b1370f 100644 --- a/xmake/modules/package/manager/zypper/find_package.lua +++ b/xmake/modules/package/manager/zypper/find_package.lua @@ -26,7 +26,7 @@ import("lib.detect.find_tool") import("package.manager.pkgconfig.find_package", { alias = "find_package_from_pkgconfig" }) -- find package -function _find_package(rpm, zypper, name, opt) +function _find_package(rpm, name, opt) if opt.require_version and opt.require_version ~= "latest" then name = name .. '-' .. opt.require_version:gsub('%.', '_') end @@ -99,17 +99,17 @@ function _find_package(rpm, zypper, name, opt) -- @see https://github.com/xmake-io/xmake/issues/1786 if not result then local statusinfo = try { function() - return os.iorunv(zypper.program, { "info", "--requires", name }) + return os.iorunv(rpm.program, { "-qR", name }) end } if statusinfo then for _, line in ipairs(statusinfo:split("\n", { plain = true })) do -- parse depends, e.g. Depends: libboost1.74-dev - if line:startswith("Requires") then - local depends = line:split("^Requires%s+:%s+") - if #depends == 1 then - return _find_package(rpm, zypper, depends[1], opt) + if not line:startswith("rpmlib(") then + local depends = line + result = _find_package(rpm, depends, opt) + if result then + return result end - break end end end @@ -143,13 +143,12 @@ function main(name, opt) return end - -- find rpm and zypper + -- find rpm local rpm = find_tool("rpm") - local zypper = find_tool("zypper") - if not (rpm and zypper) then + if not rpm then return end -- find package - return _find_package(rpm, zypper, name, opt) + return _find_package(rpm, name, opt) end