package An official xmake package repository https://xrepo.xmake.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

300 lines
10 KiB

import("core.base.option")
import("core.base.semver")
import("core.base.json")
import("core.base.hashset")
import("lib.detect.find_tool")
import("lib.detect.find_file")
import("net.http")
import("devel.git")
import("utils.archive")
local options = {
{nil, "repo", "v", nil, "Set repository name.",
"e.g. ",
" - github:xmake-io/xmake",
" - gitlab:xmake-io/xmake"}
}
-- function to get Gitlab data
function get_gitlab_data(reponame)
local glab = assert(find_tool("glab"), "glab not found!")
local host = os.iorunv(glab.program, {"config", "get", "host"}):trim()
local graphql_query = 'query={ project(fullPath: "' .. reponame .. '") { description webUrl sshUrlToRepo name } }'
local repoinfo = os.iorunv(glab.program, {"api", "graphql", "-f", graphql_query})
local data = {}
if repoinfo then
repoinfo = json.decode(repoinfo)
if repoinfo.data and repoinfo.data.project then
-- extract required data and restructure it
local project_data = repoinfo.data.project
data = {
description = project_data.description,
homepageUrl = project_data.webUrl,
licenseInfo = "MIT", -- NOTE: Find a way to get the project license in gitlab
url = project_data.webUrl,
sshUrl = project_data.sshUrlToRepo,
name = project_data.name,
}
repoinfo.data.project = data
end
end
return {host = host, data = data}
end
local function get_github_data(reponame)
local gh = assert(find_tool("gh"), "gh not found!")
local host = "github.com"
local data = os.iorunv(gh.program, {
"repo",
"view",
reponame,
"--json",
"description,homepageUrl,licenseInfo,url,sshUrl,name,latestRelease",
})
if data then
data = json.decode(data)
end
return {data = data, host = host}
end
local function get_license_spdx_id(key)
local licenses = {
["apache-2.0"] = "Apache-2.0",
["lgpl-2.0"] = "LGPL-2.0",
["lgpl-2.1"] = "LGPL-2.1",
["agpl-3.0"] = "AGPL-3.0",
["bsd-2-clause"] = "BSD-2-Clause",
["bsd-3-clause"] = "BSD-3-Clause",
["bsl-1.0"] = "BSL-1.0",
["cc0-1.0"] = "CC0-1.0",
["epl-2.0"] = "EPL-2.0",
["gpl-2.0"] = "GPL-2.0",
["gpl-3.0"] = "GPL-3.0",
["mpl-2.0"] = "MPL-2.0",
zlib = "zlib",
mit = "MIT",
}
local license = licenses[key]
if license then
return license
end
local url = string.format("https://api.github.com/licenses/%s", key)
local tmpfile = os.tmpfile({ramdisk = false})
local ok = try { function () http.download(url, tmpfile); return true end }
if not ok then
os.tryrm(tmpfile)
return nil
end
local license_detail = json.loadfile(tmpfile)
license = license_detail["spdx_id"]
os.tryrm(tmpfile)
return license
end
function generate_package(reponame, get_data)
local repo_data = get_data(reponame)
local data = repo_data.data
local host = repo_data.host
-- generate package header
local packagename = assert(data.name, "package name not found!"):lower()
local packagefile = path.join("packages", string.sub(packagename, 1, 1), packagename, "xmake.lua")
local file = io.open(packagefile, "w")
-- define package and homepage
file:print('package("%s")', packagename)
local homepage = data.homepageUrl and data.homepageUrl ~= "" and data.homepageUrl or data.url
if homepage then
file:print(' set_homepage("%s")', homepage)
end
local description = data.description or ("The " .. packagename .. " package")
file:print(' set_description("%s")', description)
-- define license if available
if type(data.licenseInfo) == "table" and data.licenseInfo.key then
local license = get_license_spdx_id(data.licenseInfo.key)
if license then
file:print(' set_license("%s")', license)
end
end
file:print("")
-- define package URLs and versions
local repodir
local has_xmake, has_cmake, has_meson, has_bazel, has_autoconf, need_autogen
local latest_release = data.latestRelease
if type(latest_release) == "table" then
local url = string.format("https://%s/%s/archive/refs/tags/%s.tar.gz", host, reponame, latest_release.tagName)
local giturl = string.format("https://%s/%s.git", host, reponame)
local tmpfile = os.tmpfile({ramdisk = false}) .. ".tar.gz"
repodir = tmpfile .. ".dir"
file:write(' add_urls("https://' .. host .. '/' .. reponame .. '/archive/refs/tags/$(version).tar.gz",\n')
file:print(' "%s")\n', giturl)
print("downloading %s", url)
http.download(url, tmpfile)
file:print(' add_versions("%s", "%s")', latest_release.tagName, hash.sha256(tmpfile))
archive.extract(tmpfile, repodir)
os.rm(tmpfile)
else
local giturl = string.format("https://%s/%s.git", host, reponame)
repodir = os.tmpfile({ ramdisk = false })
file:print(' add_urls("%s")', giturl)
print("downloading %s", giturl)
git.clone(giturl, { outputdir = repodir, depth = 1 })
local commit = git.lastcommit({ repodir = repodir })
local version = try {
function()
return os.iorunv("git", {
"log",
"-1",
"--date=format:%Y.%m.%d",
"--format=%ad",
}, { curdir = repodir })
end
}
if version then
file:print(' add_versions("%s", "%s")', version:trim(), commit)
end
end
local build_systems = {
["xmake.lua"] = {
deps = {},
priority = 1,
install = function(configs, package)
return [=[
io.writefile("xmake.lua", [[
add_rules("mode.release", "mode.debug")
target("%s")
set_kind("$(kind)")
add_files("src/*.c")
add_headerfiles("src/(*.h)")
]])
if package:config("shared") then
configs.kind = "shared"
end
import("package.tools.xmake").install(package, configs)]=]
end,
},
["CMakeLists.txt"] = {
deps = {"cmake"},
priority = 2,
install = function(configs, package)
return [[
table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:is_debug() and "Debug" or "Release"))
table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
import("package.tools.cmake").install(package, configs)]]
end,
},
["configure,configure.ac,autogen.sh"] = {
deps = {"autoconf", "automake", "libtool"},
priority = 3,
install = function(configs, package)
return [[
table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))
if package:is_debug() then
table.insert(configs, "--enable-debug")
end
import("package.tools.autoconf").install(package, configs)]]
end,
},
["meson.build"] = {
deps = {"meson", "ninja"},
priority = 4,
install = function(configs, package)
return [[
table.insert(configs, "-Ddefault_library=" .. (package:config("shared") and "shared" or "static"))
import("package.tools.meson").install(package, configs)]]
end,
},
["BUILD,BUILD.bazel"] = {
deps = {"bazel"},
priority = 5,
install = function(configs, package)
return [[
import("package.tools.bazel").install(package, configs)]]
end,
}
}
-- detect build system
local build_system_detected = {}
if repodir then
local files = os.files(path.join(repodir, "*")) or {}
table.join2(files, os.files(path.join(repodir, "*", "*")))
for _, file in ipairs(files) do
local filename = path.filename(file)
for k, v in pairs(build_systems) do
local filenames = hashset.from(k:split(","))
if filenames:has(filename) then
table.insert(build_system_detected, v)
end
end
end
os.rm(repodir)
end
local build_system
if #build_system_detected > 0 then
table.sort(build_system_detected, function (a, b) return a.priority < b.priority end)
build_system = build_system_detected[1]
end
if not build_system then
build_system = build_systems["xmake.lua"]
end
-- add dependencies
if build_system then
local deps = table.wrap(build_system.deps)
if deps and #deps > 0 then
file:print('')
file:print(' add_deps("' .. table.concat(deps, '", "') .. '")')
end
end
-- generate install scripts
file:print('')
file:print(' on_install(function (package)')
file:print(' local configs = {}')
if build_system then
file:print(build_system.install(configs, package))
end
file:print(' end)')
-- generate test scripts
file:print('')
file:print(' on_test(function (package)')
file:print(' assert(package:has_cfuncs("foo", {includes = "foo.h"}))')
file:print(' end)')
file:close()
io.cat(packagefile)
cprint("${bright}%s generated!", packagefile)
end
function main(...)
local opt = option.parse(table.pack(...), options, "New a package.", "", "Usage: xmake l scripts/new.lua [options]")
local repo = assert(opt.repo, "repository name must be set!")
local reponame = repo:sub(8)
if repo:startswith("github:") then
generate_package(reponame, get_github_data)
return
end
if repo:startswith("gitlab:") then
generate_package(reponame, get_gitlab_data)
return
end
raise("unsupported repository source. only 'github' and 'gitlab' are supported.")
end