xmake.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package("libllvm")
  2. set_kind("library")
  3. set_homepage("https://llvm.org/")
  4. set_description("The LLVM Compiler Infrastructure.")
  5. add_configs("exception", {description = "Enable C++ exception support for LLVM.", default = true, type = "boolean"})
  6. add_configs("rtti", {description = "Enable C++ RTTI support for LLVM.", default = true, type = "boolean"})
  7. add_configs("ms_dia", {description = "Enable DIA SDK to support non-native PDB parsing. (msvc only)", default = true, type = "boolean"})
  8. add_configs("libffi", {description = "Enable libffi to support the LLVM interpreter to call external functions.", default = false, type = "boolean"})
  9. add_configs("httplib", {description = "Enable cpp-httplib to support llvm-debuginfod serve debug information over HTTP.", default = false, type = "boolean"})
  10. add_configs("libcxx", {description = "Use libc++ as C++ standard library instead of libstdc++", default = false, type = "boolean"})
  11. includes(path.join(os.scriptdir(), "constants.lua"))
  12. for _, project in ipairs(get_llvm_known_projects()) do
  13. add_configs(project:gsub("-", "_"), {description = "Build " .. project .. " project.", default = (project == "clang"), type = "boolean"})
  14. end
  15. for _, runtime in ipairs(get_llvm_all_runtimes()) do
  16. add_configs(runtime:gsub("-", "_"), {description = "Build " .. runtime .. " runtime.", default = false, type = "boolean"})
  17. end
  18. if is_plat("windows") then
  19. -- pre-built
  20. if is_arch("x64") then
  21. add_urls("https://github.com/xmake-mirror/llvm-windows/releases/download/$(version)/clang+llvm-$(version)-win64.zip")
  22. add_versions("19.1.7", "c6e058c6012f499811caa1ec037cc1b5c2fd2f8c20cc3315cae602cbd6c81a5e")
  23. end
  24. -- The LLVM shared library cannot be built under windows.
  25. add_configs("shared", {description = "Build shared library.", default = false, type = "boolean", readonly = true})
  26. add_configs("runtimes", {description = "Set vs compiler runtime.", default = "MT", readonly = true})
  27. add_configs("vs_runtime", {description = "Set vs compiler runtime.", default = "MT", readonly = true})
  28. add_syslinks("psapi", "shell32", "ole32", "uuid", "advapi32", "ws2_32", "ntdll", "version")
  29. else
  30. -- self-built
  31. add_urls("https://github.com/llvm/llvm-project/releases/download/llvmorg-$(version)/llvm-project-$(version).src.tar.xz", {alias = "tarball"})
  32. add_urls("https://github.com/llvm/llvm-project.git", {alias = "git"})
  33. add_versions("tarball:19.1.7", "82401fea7b79d0078043f7598b835284d6650a75b93e64b6f761ea7b63097501")
  34. add_versions("git:19.1.7", "llvmorg-19.1.7")
  35. add_deps("ninja")
  36. add_deps("zlib", "zstd", {optional = true})
  37. set_policy("package.cmake_generator.ninja", true)
  38. end
  39. -- workaround to fix "error: undefined symbol: __mulodi4" (armeabi-v7a, r22, windows)
  40. if is_plat("android") then
  41. add_syslinks("compiler_rt-extras")
  42. end
  43. -- error: undefined symbol: backtrace
  44. if is_plat("bsd") then
  45. add_syslinks("execinfo")
  46. end
  47. add_deps("cmake")
  48. on_load(function (package)
  49. local constants = import('constants')
  50. -- add deps.
  51. if not package:is_plat("windows") then -- not prebuilt
  52. package:add("deps", "python 3.x", {kind = "binary", host = true})
  53. if package:config("libffi") then
  54. package:add("deps", "libffi")
  55. end
  56. if package:config("httplib") then
  57. package:add("deps", "cpp-httplib")
  58. end
  59. if package:config("libcxx") then
  60. package:add("deps", "libc++")
  61. end
  62. end
  63. if package:is_plat("windows") and package:config("ms_dia") then
  64. package:add("deps", "diasdk")
  65. end
  66. -- add links
  67. local linkable_projects = {"lldb", "lld", "clang", "polly", "bolt"}
  68. table.insert(linkable_projects, "llvm") -- make sure that the base library is last.
  69. for _, name in ipairs(linkable_projects) do
  70. local cname = name:gsub("-", "_")
  71. local ptype = package:config("shared") and "shared" or "static"
  72. if cname == "llvm" or package:config(cname) then
  73. package:add("links", constants[("get_%s_%s_libraries"):format(cname, ptype)]())
  74. end
  75. end
  76. if package:is_plat("windows") then
  77. package:add("links", "LLVM-C")
  78. end
  79. end)
  80. on_install("windows|x64", function (package)
  81. os.cp("*", package:installdir())
  82. end)
  83. on_install("linux", "macosx", "bsd", "android", "iphoneos", "cross", function (package)
  84. local constants = import('constants')
  85. local projects_enabled = {}
  86. local runtimes_enabled = {}
  87. for _, project in ipairs(constants.get_llvm_known_projects()) do
  88. if package:config(project:gsub("-", "_")) then
  89. table.insert(projects_enabled, project)
  90. end
  91. end
  92. for _, runtime in ipairs(constants.get_llvm_all_runtimes()) do
  93. if package:config(runtime:gsub("-", "_")) then
  94. table.insert(runtimes_enabled, runtime)
  95. end
  96. end
  97. local configs = {
  98. "-DBUILD_SHARED_LIBS=OFF",
  99. -- llvm
  100. "-DLLVM_BUILD_UTILS=OFF",
  101. "-DLLVM_INCLUDE_DOCS=OFF",
  102. "-DLLVM_INCLUDE_EXAMPLES=OFF",
  103. "-DLLVM_INCLUDE_TESTS=OFF",
  104. "-DLLVM_INCLUDE_BENCHMARKS=OFF",
  105. "-DLLVM_OPTIMIZED_TABLEGEN=ON",
  106. "-DLLVM_ENABLE_PROJECTS=" .. table.concat(projects_enabled, ";"),
  107. "-DLLVM_ENABLE_RUNTIMES=" .. table.concat(runtimes_enabled, ";"),
  108. -- disable tools build - to save link time
  109. "-DLLVM_BUILD_TOOLS=OFF",
  110. "-DCLANG_BUILD_TOOLS=OFF",
  111. "-DCLANG_ENABLE_CLANGD=OFF",
  112. "-DBOLT_BUILD_TOOLS=OFF",
  113. "-DFLANG_BUILD_TOOLS=OFF",
  114. "-DLLD_BUILD_TOOLS=OFF"
  115. }
  116. table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:is_debug() and "Debug" or "Release"))
  117. table.insert(configs, "-DLLVM_BUILD_LLVM_DYLIB=" .. (package:config("shared") and "ON" or "OFF"))
  118. table.insert(configs, "-DLLVM_ENABLE_EH=" .. (package:config("exception") and "ON" or "OFF"))
  119. table.insert(configs, "-DLLVM_ENABLE_RTTI=" .. (package:config("rtti") and "ON" or "OFF"))
  120. table.insert(configs, "-DLLVM_ENABLE_DIA_SDK=" .. (package:config("ms_dia") and "ON" or "OFF"))
  121. table.insert(configs, "-DLLVM_ENABLE_LIBCXX=" .. (package:config("libcxx") and "ON" or "OFF"))
  122. table.insert(configs, "-DLLVM_ENABLE_LTO=" .. (package:config("lto") and "ON" or "OFF"))
  123. table.insert(configs, "-DLLVM_ENABLE_ZSTD=" .. (package:dep("zstd") and "ON" or "OFF"))
  124. table.insert(configs, "-DLLVM_ENABLE_ZLIB=" .. (package:dep("zlib") and "ON" or "OFF"))
  125. if package:config("libffi") then
  126. table.insert(configs, "-DLLVM_ENABLE_FFI=ON")
  127. table.insert(configs, "-DFFI_INCLUDE_DIR=" .. package:dep("libffi"):installdir("include"))
  128. table.insert(configs, "-DFFI_LIBRARY_DIR=" .. package:dep("libffi"):installdir("lib"))
  129. else
  130. table.insert(configs, "-DLLVM_ENABLE_FFI=OFF")
  131. end
  132. if package:config("httplib") then
  133. table.insert(configs, "-DLLVM_ENABLE_HTTPLIB=ON")
  134. table.insert(configs, "-Dhttplib_ROOT=" .. package:dep("cpp-httplib"):installdir())
  135. else
  136. table.insert(configs, "-DLLVM_ENABLE_HTTPLIB=OFF")
  137. end
  138. for tooldir in string.gmatch(io.readfile("clang/tools/CMakeLists.txt"), "add_clang_subdirectory%((.-)%)") do
  139. if tooldir ~= "libclang" and (tooldir ~= "clang-shlib" or not package:config("shared")) then
  140. local tool = tooldir:upper():gsub("-", "_")
  141. table.insert(configs, "-DCLANG_TOOL_" .. tool .. "_BUILD=OFF")
  142. end
  143. end
  144. if package:is_plat("android") then
  145. local triple
  146. if package:is_arch("arm64-v8a") then
  147. triple = "aarch64-linux-android"
  148. elseif package:arch():startswith("armeabi") then
  149. triple = "armv7a-linux-androideabi"
  150. elseif package:is_arch("x86") then
  151. triple = "i686-linux-android"
  152. elseif package:is_arch("x86_64") then
  153. triple = "x86_64-linux-android"
  154. else
  155. raise("unsupported arch(%s) for android!", package:arch())
  156. end
  157. table.insert(configs, "-DLLVM_HOST_TRIPLE=" .. triple)
  158. end
  159. if package:is_plat("iphoneos") then
  160. local triple
  161. if package:is_arch("arm64") then
  162. triple = "aarch64-apple-ios"
  163. else
  164. raise("unsupported arch(%s) for iphoneos!", package:arch())
  165. end
  166. table.insert(configs, "-DLLVM_HOST_TRIPLE=" .. triple)
  167. -- LLVM build systems mostly use "Darwin", not if(APPLE)
  168. table.insert(configs, "-DCMAKE_SYSTEM_NAME=Darwin")
  169. end
  170. function tryadd_dep(depname, varname)
  171. varname = varname or depname
  172. local dep = package:dep(depname)
  173. if dep and not dep:is_system() then
  174. local fetchinfo = dep:fetch({external = false})
  175. if fetchinfo then
  176. local includedirs = fetchinfo.includedirs or fetchinfo.sysincludedirs
  177. if includedirs and #includedirs > 0 then
  178. table.insert(configs, "-D" .. varname .. "_INCLUDE_DIR=" .. table.concat(includedirs, " "):gsub("\\", "/"))
  179. end
  180. local libfiles = fetchinfo.libfiles
  181. if libfiles then
  182. table.insert(configs, "-D" .. varname .. "_LIBRARY=" .. table.concat(libfiles, " "):gsub("\\", "/"))
  183. end
  184. end
  185. end
  186. end
  187. tryadd_dep("zlib", "ZLIB")
  188. tryadd_dep("zstd")
  189. os.cd("llvm")
  190. import("package.tools.cmake").install(package, configs)
  191. end)
  192. on_test(function (package)
  193. assert(package:check_cxxsnippets({test = [[
  194. #include <llvm/IR/LLVMContext.h>
  195. #include <llvm/IR/Module.h>
  196. void test() {
  197. llvm::LLVMContext context;
  198. llvm::Module module("test", context);
  199. }
  200. ]]}, {configs = {languages = 'c++17'}}))
  201. if package:config("clang") then
  202. assert(package:check_cxxsnippets({test = [[
  203. #include <clang/Frontend/CompilerInstance.h>
  204. void test() {
  205. clang::CompilerInstance instance;
  206. }
  207. ]]}, {configs = {languages = 'c++17'}}))
  208. end
  209. end)