xmake.lua 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package("qtbase")
  2. set_kind("template")
  3. set_homepage("https://www.qt.io")
  4. set_description("Qt is the faster, smarter way to create innovative devices, modern UIs & applications for multiple screens. Cross-platform software development at its best.")
  5. set_license("LGPL-3")
  6. add_configs("shared", {description = "Download shared binaries.", default = true, type = "boolean", readonly = true})
  7. add_configs("runtimes", {description = "Set compiler runtimes.", default = "MD", readonly = true})
  8. add_deps("aqt")
  9. on_load(function (package)
  10. package:addenv("PATH", "bin")
  11. end)
  12. on_fetch(function (package, opt)
  13. import("core.base.semver")
  14. import("detect.sdks.find_qt")
  15. local qt = package:data("qt")
  16. if qt then
  17. return qt
  18. end
  19. local sdkdir
  20. if not opt.system then
  21. sdkdir = package:installdir()
  22. end
  23. local qt = find_qt(sdkdir, {force = opt.force})
  24. if not qt then
  25. return
  26. end
  27. local qtversion = semver.new(qt.sdkver)
  28. if not qtversion:ge(package:version()) then
  29. return
  30. end
  31. qt.version = qt.sdkver
  32. package:data_set("qt", qt)
  33. return qt
  34. end)
  35. on_install(function (package)
  36. import("core.base.semver")
  37. import("core.project.config")
  38. import("core.tool.toolchain")
  39. local version = package:version()
  40. local versionstr = version:shortstr()
  41. local host
  42. if is_host("windows") or package:is_plat("mingw") then
  43. host = "windows"
  44. elseif is_host("linux") then
  45. host = "linux"
  46. elseif is_host("macosx") then
  47. host = "mac"
  48. else
  49. raise("unhandled host " .. os.host())
  50. end
  51. local target
  52. if package:is_plat("windows", "mingw", "linux", "macosx") then
  53. target = "desktop"
  54. elseif package:is_plat("android") then
  55. target = "android"
  56. elseif package:is_plat("iphoneos") then
  57. target = "ios"
  58. else
  59. raise("unhandled plat " .. package:plat())
  60. end
  61. local arch
  62. if package:is_plat("windows", "mingw") then
  63. local winarch
  64. if package:is_arch("x64", "x86_64", "arm64") then
  65. winarch = "64"
  66. elseif version:lt("6.0") and package:is_arch("x86", "i386") then -- 32bits support was removed in Qt6
  67. winarch = "32"
  68. else
  69. raise("unhandled arch " .. package:targetarch())
  70. end
  71. local compiler_version
  72. if package:is_plat("windows") then
  73. local vs = toolchain.load("msvc"):config("vs")
  74. if tonumber(vs) >= 2019 or version:ge("6.0") then
  75. compiler_version = "msvc2019"
  76. elseif vs == "2017" or vs == "2015" then
  77. compiler_version = "msvc" .. vs
  78. else
  79. raise("unhandled msvc version " .. vs)
  80. end
  81. if package:is_arch("x64", "x86_64") then
  82. compiler_version = compiler_version .. "_64"
  83. elseif package:is_arch("arm64") then -- arm64 support was added in Qt6.2
  84. compiler_version = compiler_version .. "_arm64"
  85. end
  86. else
  87. local cc = package:tool("cc")
  88. local ccversion = os.iorunv(cc, {"-dumpversion"}):trim()
  89. local mingw_version = semver.new(ccversion)
  90. if version:ge("6.2.2") then
  91. compiler_version = "mingw"
  92. elseif mingw_version:ge("8.1") then
  93. compiler_version = "mingw81"
  94. elseif mingw_version:ge("7.3") then
  95. compiler_version = "mingw73"
  96. elseif mingw_version:ge("5.3") then
  97. compiler_version = "mingw53"
  98. else
  99. raise("unhandled mingw version " .. version)
  100. end
  101. end
  102. arch = "win" .. winarch .. "_" .. compiler_version
  103. elseif package:is_plat("linux") then
  104. arch = "gcc_64"
  105. elseif package:is_plat("macosx") then
  106. arch = "clang_64"
  107. elseif package:is_plat("android") then
  108. if version:le("5.13") or version:ge("6.0") then
  109. if package:is_arch("x86_64", "x64") then
  110. arch = "android_x86_64"
  111. elseif package:is_arch("arm64", "arm64-v8a") then
  112. arch = "android_arm64_v8a"
  113. elseif package:is_arch("armv7", "armv7-a", "armeabi", "armeabi-v7a") then
  114. arch = "android_armv7"
  115. elseif package:is_arch("x86") then
  116. arch = "android_x86"
  117. else
  118. raise("unhandled arch " .. package:targetarch())
  119. end
  120. else
  121. arch = "android"
  122. end
  123. end
  124. local installdir = package:installdir()
  125. os.vrunv("aqt", {"install-qt", "-O", installdir, host, target, versionstr, arch})
  126. -- move files to root
  127. os.mv(path.join(installdir, versionstr, "*", "*"), installdir)
  128. os.rmdir(path.join(installdir, versionstr))
  129. -- special case for cross-compilation since we need binaries we can run on the host
  130. if package:is_cross() then
  131. local runhost
  132. if is_host("windows") then
  133. runhost = "windows"
  134. elseif is_host("linux") then
  135. runhost = "linux"
  136. elseif is_host("macosx") then
  137. runhost = "mac"
  138. else
  139. raise("unhandled host " .. os.host())
  140. end
  141. local hostarch
  142. if is_host("windows") then
  143. local winarch
  144. if os.arch():find("64", 1, true) then
  145. winarch = "64"
  146. else
  147. winarch = "32"
  148. end
  149. local compiler_version
  150. local vs = toolchain.load("msvc"):config("vs")
  151. if tonumber(vs) >= 2019 or version:ge("6.0") then
  152. compiler_version = "msvc2019"
  153. elseif vs == "2017" or vs == "2015" then
  154. compiler_version = "msvc" .. vs
  155. else
  156. raise("unhandled msvc version " .. vs)
  157. end
  158. if os.arch() == "x64" then
  159. compiler_version = compiler_version .. "_64"
  160. elseif os.arch() == "arm64" then
  161. compiler_version = compiler_version .. "_arm64"
  162. end
  163. hostarch = "win" .. winarch .. "_" .. compiler_version
  164. elseif is_host("linux") then
  165. hostarch = "gcc_64"
  166. elseif is_host("macosx") then
  167. hostarch = "clang_64"
  168. end
  169. -- download qtbase to bin_host folder
  170. os.vrunv("aqt", {"install-qt", "-O", path.join(installdir, "bin_host"),
  171. runhost, "desktop", versionstr, hostarch})
  172. -- add symbolic links for useful tools
  173. local tool_folders = {}
  174. if version:ge("6.0") then
  175. tool_folders.bin = {
  176. qmake = true,
  177. qmake6 = true
  178. }
  179. tool_folders.libexec = {
  180. moc = true,
  181. rcc = true,
  182. uic = true
  183. }
  184. else
  185. tool_folders.bin = {
  186. qmake = true,
  187. moc = true,
  188. rcc = true,
  189. uic = true
  190. }
  191. end
  192. for folder, tools in pairs(tool_folders) do
  193. for _, file in ipairs(os.files(path.join(installdir, "bin_host", versionstr, "*", folder, "*"))) do
  194. local filename = path.filename(file)
  195. if tools[filename] then
  196. local targetpath = path.join(installdir, folder, filename)
  197. os.rm(targetpath)
  198. if is_host("windows") then
  199. os.cp(file, targetpath)
  200. else
  201. os.ln(file, targetpath)
  202. end
  203. -- some tools like CMake will try to run moc.exe even on Linux, trick them (ln bin/moc.exe => bin_host/bin/moc)
  204. if package:is_plat("mingw") then
  205. os.rm(targetpath .. ".exe")
  206. if is_host("windows") then
  207. os.cp(file, targetpath .. ".exe")
  208. else
  209. os.ln(file, targetpath .. ".exe")
  210. end
  211. end
  212. end
  213. end
  214. end
  215. end
  216. end)
  217. on_test(function (package)
  218. local qt = assert(package:data("qt"))
  219. local function getbin(name)
  220. if is_host("windows") then
  221. name = name .. ".exe"
  222. end
  223. local exec = path.join(qt.bindir, name)
  224. if not os.isexec(exec) and qt.libexecdir then
  225. exec = path.join(qt.libexecdir, name)
  226. end
  227. if not os.isexec(exec) and qt.libexecdir_host then
  228. exec = path.join(qt.libexecdir_host, name)
  229. end
  230. assert(os.isexec(exec), name .. " not found!")
  231. return exec
  232. end
  233. os.vrun(getbin("qmake") .. " -v")
  234. os.vrun(getbin("moc") .. " -v")
  235. -- rcc -v and uic -v seems to hang CI forever
  236. --os.vrun(getbin("rcc") .. " -v") -- rcc -v hangs CI
  237. --os.vrun(getbin("uic") .. " -v") -- uic -v seems to hang on CI
  238. end)