xmake.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package("gmp")
  2. set_homepage("https://gmplib.org/")
  3. set_description("GMP is a free library for arbitrary precision arithmetic, operating on signed integers, rational numbers, and floating-point numbers.")
  4. set_license("LGPL-3.0")
  5. add_urls("https://ftpmirror.gnu.org/gmp/gmp-$(version).tar.xz")
  6. add_urls("https://ftp.gnu.org/gnu/gmp/gmp-$(version).tar.xz")
  7. add_urls("https://gmplib.org/download/gmp/gmp-$(version).tar.xz")
  8. add_versions("6.3.0", "a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898")
  9. add_patches("6.3.0", "patches/6.3.0/c23.patch", "24eb6ad75fb2552db247d3c5c522d30f221cca23a0fdc925b2684af44d51b7b3")
  10. add_configs("cpp_api", {description = "Enable C++ support", default = false, type = "boolean"})
  11. if is_plat("windows") and is_arch("arm64") then
  12. add_configs("assembly", {description = "Enable the use of assembly loops", default = false, type = "boolean"})
  13. else
  14. add_configs("assembly", {description = "Enable the use of assembly loops", default = true, type = "boolean"})
  15. end
  16. add_configs("fat", {description = "Build fat libraries on systems that support it", default = false, type = "boolean"})
  17. if is_plat("windows") then
  18. add_configs("shared", {description = "Build shared library.", default = false, type = "boolean", readonly = true})
  19. end
  20. if is_plat("mingw") and is_subhost("msys") then
  21. add_extsources("pacman::gmp")
  22. elseif is_plat("linux") then
  23. add_extsources("pacman::gmp", "apt::libgmp-dev")
  24. elseif is_plat("macosx") then
  25. add_extsources("brew::gmp")
  26. end
  27. if not is_subhost("windows") then
  28. add_deps("m4")
  29. end
  30. add_links("gmpxx", "gmp")
  31. if on_check then
  32. on_check(function (package)
  33. if package:is_plat("windows") then
  34. if package:has_tool("cxx", "clang_cl") then
  35. raise("package(gmp) unsupported clang-cl toolchain now, you can use clang toolchain\nadd_requires(\"gmp\", {configs = {toolchains = \"clang\"}}))")
  36. end
  37. end
  38. end)
  39. end
  40. on_fetch(function (package, opt)
  41. if opt.system then
  42. return package:find_package("system::gmp", {includes = "gmp.h"})
  43. end
  44. end)
  45. on_load(function (package)
  46. if is_subhost("windows") and os.arch() == "x64" then
  47. local msystem = "MINGW" .. (package:is_arch64() and "64" or "32")
  48. package:add("deps", "msys2", {configs = {msystem = msystem, base_devel = true}})
  49. end
  50. if package:is_plat("windows") then
  51. -- msvc toolchain require other tool to build asm
  52. -- x86, x64 -> yasm, arm64 -> clang
  53. if package:is_arch("x64", "x86") then
  54. package:add("deps", "yasm")
  55. end
  56. package:add("defines", "__GMP_WITHIN_CONFIGURE")
  57. if package:is_arch("x64", "arm64") then
  58. package:add("defines", "_LONG_LONG_LIMB") -- mp_limb_t type
  59. end
  60. -- if package:config("shared") then
  61. -- package:add("defines", "__GMP_LIBGMP_DLL")
  62. -- end
  63. end
  64. end)
  65. on_install("!wasm and (!android or android@!windows)", function (package)
  66. import("package.tools.autoconf")
  67. import("lib.detect.find_tool")
  68. -- ref https://github.com/microsoft/vcpkg/blob/4ed84798137bcf664989fa432d41d278d7ad3b25/ports/gmp/subdirs.patch
  69. io.replace("Makefile.am",
  70. "SUBDIRS = tests mpn mpz mpq mpf printf scanf rand cxx demos tune doc",
  71. "SUBDIRS = mpn mpz mpq mpf printf scanf rand cxx tune", {plain = true})
  72. if is_host("windows") then
  73. io.replace("configure", "LIBTOOL='$(SHELL) $(top_builddir)/libtool'", "LIBTOOL='\"$(SHELL)\" $(top_builddir)/libtool'", {plain = true})
  74. end
  75. if package:is_plat("windows") then
  76. -- Let asm code use windows abi
  77. io.replace("configure", "*-*-mingw* | *-*-msys | *-*-cygwin)", "*-*-msvc)", {plain = true})
  78. local obj_file_suffix = package:has_tool("cxx", "cl") and ".obj" or ".o"
  79. io.replace("configure", "$CCAS $CFLAGS $CPPFLAGS", "$CCAS $CCASFLAGS -o conftest" .. obj_file_suffix, {plain = true})
  80. -- Remove error flags for asm build
  81. io.replace("mpn/Makefile.in", "$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(ASMFLAGS)", "$(AM_CFLAGS) ${CCASFLAGS}", {plain = true})
  82. if package:has_tool("ld", "link") then
  83. -- `lib /out: xxx` -> `lib /out:xxx`
  84. io.replace("configure", "$AR $AR_FLAGS ", "$AR $AR_FLAGS", {plain = true})
  85. end
  86. if package:config("shared") then
  87. -- error: duplicate symbol: __gmpn_add
  88. io.replace("gmp-h.in", "#define __GMP_EXTERN_INLINE __inline", "#define __GMP_EXTERN_INLINE static __inline", {plain = true})
  89. -- export symbol macro
  90. io.replace("gmp-h.in", "#define __GMP_LIBGMP_DLL @LIBGMP_DLL@", "#define __GMP_LIBGMP_DLL 1", {plain = true})
  91. end
  92. end
  93. local configs = {}
  94. table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))
  95. table.insert(configs, "--enable-static=" .. (package:config("shared") and "no" or "yes"))
  96. table.insert(configs, "--enable-cxx=" .. (package:config("cpp_api") and "yes" or "no"))
  97. table.insert(configs, "--enable-assembly=" .. (package:config("assembly") and "yes" or "no"))
  98. table.insert(configs, "--enable-fat=" .. (package:config("fat") and "yes" or "no"))
  99. if package:is_debug() then
  100. table.insert(configs, "--enable-debug")
  101. end
  102. if not package:is_plat("windows") and package:config("pic") ~= false then
  103. table.insert(configs, "--with-pic")
  104. end
  105. local opt = {}
  106. if package:is_plat("macosx") and package:is_arch("arm64") and os.arch() == "x86_64" then
  107. table.insert(configs, "--build=x86_64-apple-darwin")
  108. table.insert(configs, "--host=arm64-apple-darwin")
  109. opt.envs = autoconf.buildenvs(package, {cflags = "--target=arm64-apple-darwin"})
  110. opt.envs.CC = package:build_getenv("cc") .. " -arch arm64" -- for linker flags
  111. elseif package:is_plat("windows") then
  112. local msvc = package:toolchain("msvc") or package:toolchain("clang") or package:toolchain("clang-cl")
  113. assert(msvc:check(), "msvs not found!")
  114. -- buildenvs maybe missing deps bin dir
  115. opt.envs = os.joinenvs(os.joinenvs(msvc:runenvs()), autoconf.buildenvs(package))
  116. if package:has_tool("cxx", "cl") then
  117. opt.envs.CC = "cl -nologo"
  118. opt.envs.CXX = "cl -nologo"
  119. opt.envs.AR = "lib -nologo"
  120. opt.envs.LD = "link -nologo"
  121. opt.envs.NM = "dumpbin -nologo -symbols"
  122. opt.envs.AR_FLAGS = "-out:" -- override `cq` flag
  123. table.insert(configs, "gmp_cv_asm_w32=.word") -- fix detect
  124. elseif package:has_tool("cxx", "clang") then
  125. local clang_fname = path.filename(opt.envs.CC)
  126. local suffix = clang_fname:split("-")
  127. if #suffix > 1 then
  128. suffix = "-" .. suffix[#suffix]
  129. else
  130. suffix = ""
  131. end
  132. opt.envs.NM = "llvm-nm" .. suffix
  133. opt.envs.LDFLAGS = opt.envs.LDFLAGS:gsub("-nostdlib", "")
  134. if package:is_cross() then
  135. -- require -fuse-ld=lld-link
  136. opt.envs.CFLAGS = opt.envs.CFLAGS .. " " .. opt.envs.LDFLAGS
  137. opt.envs.CXXFLAGS = opt.envs.CXXFLAGS .. " " .. opt.envs.LDFLAGS
  138. end
  139. end
  140. -- Maybe missing ucrt flags
  141. opt.envs.CFLAGS = opt.envs.CFLAGS .. " " .. opt.envs.CXXFLAGS
  142. -- Fix mp_limb_t
  143. -- msvc sizeof long == 4 unmatch gcc sizeof long == 8
  144. if package:is_arch("x64", "arm64") then
  145. opt.envs.CFLAGS = opt.envs.CFLAGS .. " -D_LONG_LONG_LIMB"
  146. opt.envs.CXXFLAGS = opt.envs.CXXFLAGS .. " -D_LONG_LONG_LIMB"
  147. end
  148. local clang_archs = {
  149. ["x86"] = "i686",
  150. ["x64"] = "x86_64",
  151. ["arm64"] = "aarch64",
  152. }
  153. local target = clang_archs[package:arch()] .. "-windows-msvc"
  154. if package:is_arch("x64", "x86") then
  155. local yasm_machine = {
  156. ["x86"] = "x86",
  157. ["x64"] = "amd64",
  158. }
  159. local yasm_format = {
  160. ["x86"] = "win32",
  161. ["x64"] = "win64",
  162. }
  163. opt.envs.CCAS = "yasm"
  164. opt.envs.CCASFLAGS = format("-a x86 -m %s -p gas -r raw -f %s -g null -X gnu", yasm_machine[package:arch()], yasm_format[package:arch()])
  165. elseif package:is_arch("arm64") then
  166. if package:has_tool("cxx", "clang") then
  167. opt.envs.CCAS = opt.envs.CC
  168. else
  169. local llvm_nm = assert(find_tool("llvm-nm"), "windows arm64 require llvm-nm to detect")
  170. local clang = assert(find_tool("clang"), "windows arm64 require clang to build asm")
  171. opt.envs.CCAS = path.unix(clang.program)
  172. opt.envs.NM = path.unix(llvm_nm.program)
  173. end
  174. opt.envs.CCASFLAGS = table.concat({"--target=" .. target, "-c"}, " ")
  175. end
  176. table.insert(configs, "--host=" .. target)
  177. end
  178. -- Can't generate correct gmp.lib with lib.exe
  179. if package:is_plat("windows") then
  180. autoconf.build(package, configs, opt)
  181. -- I don't know why, it only happen on ci
  182. os.trymv("dummy.obj", "cxx/")
  183. io.writefile("xmake.lua", [[
  184. option("cpp_api", {default = false})
  185. add_rules("mode.debug", "mode.release")
  186. target("gmp")
  187. set_kind("$(kind)")
  188. add_rules("c++")
  189. add_files("**.obj|gen-*.obj|cxx/*.obj", "**.o|gen-*.o|cxx/*.o")
  190. add_headerfiles("gmp.h")
  191. target("gmpxx")
  192. set_default(has_config("cpp_api"))
  193. set_kind("$(kind)")
  194. add_rules("c++")
  195. add_files("cxx/*.obj", "cxx/*.o")
  196. add_headerfiles("gmpxx.h")
  197. add_deps("gmp")
  198. ]])
  199. import("package.tools.xmake").install(package, {cpp_api = package:config("cpp_api")})
  200. else
  201. autoconf.install(package, configs, opt)
  202. end
  203. end)
  204. on_test(function (package)
  205. assert(package:has_cfuncs("gmp_version", {includes = "gmp.h"}))
  206. end)