|
@@ -1,6 +1,7 @@
|
|
|
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")
|
|
@@ -11,174 +12,251 @@ local options = {
|
|
|
{nil, "repo", "v", nil, "Set repository name.",
|
|
|
"e.g. ",
|
|
|
" - github:xmake-io/xmake",
|
|
|
- " - brew:zlib"}
|
|
|
+ " - gitlab:xmake-io/xmake"}
|
|
|
}
|
|
|
|
|
|
-function _generate_package_from_github(reponame)
|
|
|
- -- get repository info
|
|
|
- local gh = assert(find_tool("gh"), "gh not found!")
|
|
|
- local repoinfo = os.iorunv(gh.program, {"repo", "view", reponame, "--json",
|
|
|
- "description,homepageUrl,licenseInfo,url,sshUrl,name,latestRelease"})
|
|
|
+-- 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
|
|
|
- vprint(repoinfo)
|
|
|
+ return {data = data, host = host}
|
|
|
+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(repoinfo.name, "package name not found!"):lower()
|
|
|
- local packagefile = path.join("packages", packagename:sub(1, 1), packagename, "xmake.lua")
|
|
|
+ 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 = repoinfo.homepageUrl
|
|
|
- if homepage == nil or homepage == "" then
|
|
|
- homepage = repoinfo.url
|
|
|
- end
|
|
|
+ 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 = repoinfo.description or ("The " .. packagename .. " package")
|
|
|
+
|
|
|
+ local description = data.description or ("The " .. packagename .. " package")
|
|
|
file:print(' set_description("%s")', description)
|
|
|
- local licensekey = type(repoinfo.licenseInfo) == "table" and repoinfo.licenseInfo.key
|
|
|
- if licensekey then
|
|
|
+
|
|
|
+ -- define license if available
|
|
|
+ if type(data.licenseInfo) == "table" and data.licenseInfo.key then
|
|
|
local licenses = {
|
|
|
["apache-2.0"] = "Apache-2.0",
|
|
|
["lgpl-2.0"] = "LGPL-2.0",
|
|
|
["lgpl-2.1"] = "LGPL-2.1",
|
|
|
zlib = "zlib",
|
|
|
- mit = "MIT"
|
|
|
+ mit = "MIT",
|
|
|
}
|
|
|
- local license = licenses[licensekey]
|
|
|
+ local license = licenses[data.licenseInfo.key]
|
|
|
if license then
|
|
|
file:print(' set_license("%s")', license)
|
|
|
end
|
|
|
end
|
|
|
file:print("")
|
|
|
|
|
|
- -- generate package urls and versions
|
|
|
+ -- define package URLs and versions
|
|
|
local repodir
|
|
|
- local has_xmake
|
|
|
- local has_cmake
|
|
|
- local has_meson
|
|
|
- local has_bazel
|
|
|
- local has_autoconf
|
|
|
- local need_autogen
|
|
|
- local latest_release = repoinfo.latestRelease
|
|
|
+ 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 = ("https://github.com/%s/archive/refs/tags/%s.tar.gz"):format(reponame, latest_release.tagName)
|
|
|
- local giturl = ("https://github.com/%s.git"):format(reponame)
|
|
|
- file:write(' add_urls("https://github.com/' .. reponame .. '/archive/refs/tags/$(version).tar.gz",\n')
|
|
|
- file:print(' "%s")', giturl)
|
|
|
+ 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/$(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 = ("https://github.com/%s.git"):format(reponame)
|
|
|
- repodir = os.tmpfile({ramdisk = false})
|
|
|
+ local giturl = string.format("git@%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}
|
|
|
+ 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 = {},
|
|
|
+ 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"},
|
|
|
+ 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"},
|
|
|
+ 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"},
|
|
|
+ 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"},
|
|
|
+ install = function(configs, package)
|
|
|
+ return 'import("package.tools.bazel").install(package, configs)'
|
|
|
+ end,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
-- detect build system
|
|
|
+ local build_system = nil
|
|
|
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)
|
|
|
- if filename == "xmake.lua" then
|
|
|
- has_xmake = true
|
|
|
- elseif filename == "CMakeLists.txt" then
|
|
|
- has_cmake = true
|
|
|
- elseif filename == "configure" then
|
|
|
- has_autoconf = true
|
|
|
- elseif filename == "autogen.sh" or filename == "configure.ac" then
|
|
|
- need_autogen = true
|
|
|
- has_autoconf = true
|
|
|
- elseif filename == "meson.build" then
|
|
|
- has_meson = true
|
|
|
- elseif filename == "BUILD" or filename == "BUILD.bazel" then
|
|
|
- has_bazel = true
|
|
|
+ for k, v in pairs(build_systems) do
|
|
|
+ local filenames = hashset.from(k:split(","))
|
|
|
+ if filenames:has(filename) then
|
|
|
+ build_system = v
|
|
|
+ break
|
|
|
+ end
|
|
|
end
|
|
|
end
|
|
|
os.rm(repodir)
|
|
|
end
|
|
|
+ if not build_system then
|
|
|
+ build_system = build_systems["xmake.lua"]
|
|
|
+ end
|
|
|
|
|
|
-- add dependencies
|
|
|
- if has_cmake then
|
|
|
- file:print("")
|
|
|
- file:print(' add_deps("cmake")')
|
|
|
- elseif has_meson then
|
|
|
- file:print("")
|
|
|
- file:print(' add_deps("meson", "ninja")')
|
|
|
- elseif need_autogen then
|
|
|
- file:print("")
|
|
|
- file:print(' add_deps("autoconf", "automake", "libtool")')
|
|
|
- elseif has_bazel then
|
|
|
- file:print("")
|
|
|
- file:print(' add_deps("bazel")')
|
|
|
+ if build_system then
|
|
|
+ file:print('')
|
|
|
+ local deps = table.wrap(build_system.deps)
|
|
|
+ if deps and #deps > 0 then
|
|
|
+ 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 has_cmake then
|
|
|
- file:print(' table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))')
|
|
|
- file:print(' table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))')
|
|
|
- file:print(' import("package.tools.cmake").install(package, configs)')
|
|
|
- elseif has_autoconf then
|
|
|
- file:print(' table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))')
|
|
|
- file:print(' if package:debug() then')
|
|
|
- file:print(' table.insert(configs, "--enable-debug")')
|
|
|
- file:print(' end')
|
|
|
- file:print(' import("package.tools.autoconf").install(package, configs)')
|
|
|
- elseif has_meson then
|
|
|
- file:print(' table.insert(configs, "-Ddefault_library=" .. (package:config("shared") and "shared" or "static"))')
|
|
|
- file:print(' import("package.tools.meson").install(package, configs)')
|
|
|
- elseif has_bazel then
|
|
|
- file:print(' import("package.tools.bazel").install(package, configs)')
|
|
|
- else
|
|
|
- file:print(' io.writefile("xmake.lua", [[')
|
|
|
- file:print(' add_rules("mode.release", "mode.debug")')
|
|
|
- file:print(' target("%s")', packagename)
|
|
|
- file:write(' set_kind("$(kind)")\n')
|
|
|
- file:print(' add_files("src/*.c")')
|
|
|
- file:print(' add_headerfiles("src/(*.h)")')
|
|
|
- file:print(' ]])')
|
|
|
- file:print(' if package:config("shared") then')
|
|
|
- file:print(' configs.kind = "shared"')
|
|
|
- file:print(' end')
|
|
|
- file:print(' import("package.tools.xmake").install(package, configs)')
|
|
|
+ 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)")
|
|
|
+ file:print(' end)')
|
|
|
|
|
|
-- generate test scripts
|
|
|
- file:print("")
|
|
|
- file:print(" on_test(function (package)")
|
|
|
+ file:print('')
|
|
|
+ file:print(' on_test(function (package)')
|
|
|
file:print(' assert(package:has_cfuncs("foo", {includes = "foo.h"}))')
|
|
|
- file:print(" end)")
|
|
|
-
|
|
|
+ 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 = opt.repo
|
|
|
- if repo and repo:startswith("github:") then
|
|
|
- _generate_package_from_github(repo:sub(8))
|
|
|
- else
|
|
|
- raise("we need set repository name first!")
|
|
|
+ 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
|