new.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import("core.base.option")
  2. import("core.base.semver")
  3. import("core.base.json")
  4. import("lib.detect.find_tool")
  5. import("lib.detect.find_file")
  6. import("net.http")
  7. import("devel.git")
  8. import("utils.archive")
  9. local options = {
  10. {nil, "repo", "v", nil, "Set repository name.",
  11. "e.g. ",
  12. " - github:xmake-io/xmake",
  13. " - brew:zlib"}
  14. }
  15. function _generate_package_from_github(reponame)
  16. -- get repository info
  17. local gh = assert(find_tool("gh"), "gh not found!")
  18. local repoinfo = os.iorunv(gh.program, {"repo", "view", reponame, "--json",
  19. "description,homepageUrl,licenseInfo,url,sshUrl,name,latestRelease"})
  20. if repoinfo then
  21. repoinfo = json.decode(repoinfo)
  22. end
  23. vprint(repoinfo)
  24. -- generate package header
  25. local packagename = assert(repoinfo.name, "package name not found!"):lower()
  26. local packagefile = path.join("packages", packagename:sub(1, 1), packagename, "xmake.lua")
  27. local file = io.open(packagefile, "w")
  28. file:print('package("%s")', packagename)
  29. local homepage = repoinfo.homepageUrl
  30. if homepage == nil or homepage == "" then
  31. homepage = repoinfo.url
  32. end
  33. if homepage then
  34. file:print(' set_homepage("%s")', homepage)
  35. end
  36. local description = repoinfo.description or ("The " .. packagename .. " package")
  37. file:print(' set_description("%s")', description)
  38. local licensekey = type(repoinfo.licenseInfo) == "table" and repoinfo.licenseInfo.key
  39. if licensekey then
  40. local licenses = {
  41. ["apache-2.0"] = "Apache-2.0",
  42. ["lgpl-2.0"] = "LGPL-2.0",
  43. ["lgpl-2.1"] = "LGPL-2.1",
  44. zlib = "zlib",
  45. mit = "MIT"
  46. }
  47. local license = licenses[licensekey]
  48. if license then
  49. file:print(' set_license("%s")', license)
  50. end
  51. end
  52. file:print("")
  53. -- generate package urls and versions
  54. local repodir
  55. local has_xmake
  56. local has_cmake
  57. local has_meson
  58. local has_bazel
  59. local has_autoconf
  60. local need_autogen
  61. local latest_release = repoinfo.latestRelease
  62. if type(latest_release) == "table" then
  63. local url = ("https://github.com/%s/archive/refs/tags/%s.tar.gz"):format(reponame, latest_release.tagName)
  64. local giturl = ("https://github.com/%s.git"):format(reponame)
  65. file:write(' add_urls("https://github.com/' .. reponame .. '/archive/refs/tags/$(version).tar.gz",\n')
  66. file:print(' "%s")', giturl)
  67. local tmpfile = os.tmpfile({ramdisk = false}) .. ".tar.gz"
  68. repodir = tmpfile .. ".dir"
  69. print("downloading %s", url)
  70. http.download(url, tmpfile)
  71. file:print(' add_versions("%s", "%s")', latest_release.tagName, hash.sha256(tmpfile))
  72. archive.extract(tmpfile, repodir)
  73. os.rm(tmpfile)
  74. else
  75. local giturl = ("https://github.com/%s.git"):format(reponame)
  76. repodir = os.tmpfile({ramdisk = false})
  77. file:print(' add_urls("%s")', giturl)
  78. print("downloading %s", giturl)
  79. git.clone(giturl, {outputdir = repodir, depth = 1})
  80. local commit = git.lastcommit({repodir = repodir})
  81. local version = try{ function() return os.iorunv("git", {"log", "-1", "--date=format:%Y.%m.%d", "--format=%ad"}, {curdir = repodir}) end}
  82. if version then
  83. file:print(' add_versions("%s", "%s")', version:trim(), commit)
  84. end
  85. end
  86. -- detect build system
  87. if repodir then
  88. local files = os.files(path.join(repodir, "*")) or {}
  89. table.join2(files, os.files(path.join(repodir, "*", "*")))
  90. for _, file in ipairs(files) do
  91. local filename = path.filename(file)
  92. if filename == "xmake.lua" then
  93. has_xmake = true
  94. elseif filename == "CMakeLists.txt" then
  95. has_cmake = true
  96. elseif filename == "configure" then
  97. has_autoconf = true
  98. elseif filename == "autogen.sh" or filename == "configure.ac" then
  99. need_autogen = true
  100. has_autoconf = true
  101. elseif filename == "meson.build" then
  102. has_meson = true
  103. elseif filename == "BUILD" or filename == "BUILD.bazel" then
  104. has_bazel = true
  105. end
  106. end
  107. os.rm(repodir)
  108. end
  109. -- add dependencies
  110. if has_cmake then
  111. file:print("")
  112. file:print(' add_deps("cmake")')
  113. elseif has_meson then
  114. file:print("")
  115. file:print(' add_deps("meson", "ninja")')
  116. elseif need_autogen then
  117. file:print("")
  118. file:print(' add_deps("autoconf", "automake", "libtool")')
  119. elseif has_bazel then
  120. file:print("")
  121. file:print(' add_deps("bazel")')
  122. end
  123. -- generate install scripts
  124. file:print("")
  125. file:print(" on_install(function (package)")
  126. file:print(" local configs = {}")
  127. if has_cmake then
  128. file:print(' table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))')
  129. file:print(' table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))')
  130. file:print(' import("package.tools.cmake").install(package, configs)')
  131. elseif has_autoconf then
  132. file:print(' table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))')
  133. file:print(' if package:debug() then')
  134. file:print(' table.insert(configs, "--enable-debug")')
  135. file:print(' end')
  136. file:print(' import("package.tools.autoconf").install(package, configs)')
  137. elseif has_meson then
  138. file:print(' table.insert(configs, "-Ddefault_library=" .. (package:config("shared") and "shared" or "static"))')
  139. file:print(' import("package.tools.meson").install(package, configs)')
  140. elseif has_bazel then
  141. file:print(' import("package.tools.bazel").install(package, configs)')
  142. else
  143. file:print(' io.writefile("xmake.lua", [[')
  144. file:print(' add_rules("mode.release", "mode.debug")')
  145. file:print(' target("%s")', packagename)
  146. file:write(' set_kind("$(kind)")\n')
  147. file:print(' add_files("src/*.c")')
  148. file:print(' add_headerfiles("src/(*.h)")')
  149. file:print(' ]])')
  150. file:print(' if package:config("shared") then')
  151. file:print(' configs.kind = "shared"')
  152. file:print(' end')
  153. file:print(' import("package.tools.xmake").install(package, configs)')
  154. end
  155. file:print(" end)")
  156. -- generate test scripts
  157. file:print("")
  158. file:print(" on_test(function (package)")
  159. file:print(' assert(package:has_cfuncs("foo", {includes = "foo.h"}))')
  160. file:print(" end)")
  161. file:close()
  162. io.cat(packagefile)
  163. cprint("${bright}%s generated!", packagefile)
  164. end
  165. function main(...)
  166. local opt = option.parse(table.pack(...), options, "New a package.", "",
  167. "Usage: xmake l scripts/new.lua [options]")
  168. local repo = opt.repo
  169. if repo and repo:startswith("github:") then
  170. _generate_package_from_github(repo:sub(8))
  171. else
  172. raise("we need set repository name first!")
  173. end
  174. end