Skip to content

Commit

Permalink
Merge pull request #3828 from iphelf/dev
Browse files Browse the repository at this point in the history
Add support for zypper package manager
  • Loading branch information
waruqi authored Jun 11, 2023
2 parents e13615b + 4551722 commit 9c64218
Show file tree
Hide file tree
Showing 7 changed files with 388 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
54 changes: 54 additions & 0 deletions xmake/modules/detect/tools/find_rpm.lua
Original file line number Diff line number Diff line change
@@ -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
54 changes: 54 additions & 0 deletions xmake/modules/detect/tools/find_zypper.lua
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions xmake/modules/package/manager/install_package.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
154 changes: 154 additions & 0 deletions xmake/modules/package/manager/zypper/find_package.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
--!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, 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()
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(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 not line:startswith("rpmlib(") then
local depends = line
result = _find_package(rpm, depends, opt)
if result then
return result
end
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
local rpm = find_tool("rpm")
if not rpm then
return
end

-- find package
return _find_package(rpm, name, opt)
end
65 changes: 65 additions & 0 deletions xmake/modules/package/manager/zypper/install_package.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--!A cross-platform build utility based on Lua
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- Copyright (C) 2015-present, TBOOX Open Source Group.
--
-- @author ruki, 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 {}
if opt.require_version and opt.require_version ~= "latest" then
name = name .. '-' .. opt.require_version:gsub('%.', '_')
end

-- 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
Loading

0 comments on commit 9c64218

Please sign in to comment.