Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add qt_host option to enable cross-platform Qt Builds using host SD… #2

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 55 additions & 9 deletions xmake/modules/detect/sdks/find_qt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,21 @@ function _find_qmake(sdkdir, sdkver)
end

-- get qt environment
function _get_qtenvs(qmake)
function _get_qtenvs(qmake, sdkdir)
local envs = {}
local run_args = {"-query"}
if sdkdir then
local conf_paths = {path.join(sdkdir, "bin", "target_qt.conf"), path.join(sdkdir, "bin", "qt.conf")}
for _, conf_path in ipairs(conf_paths) do
if os.isfile(conf_path) then
table.join2(run_args, {"-qtconf", conf_path})
break
end
end
end
local results = try {
function ()
return os.iorunv(qmake, {"-query"})
return os.iorunv(qmake, run_args)
end,
catch {
function (errors)
Expand All @@ -215,24 +225,43 @@ function _get_qtenvs(qmake)
end
end

-- Verify and correct the Qt SDK version for cross-compiling.
-- qmake reports its own version (QT_VERSION), not the version specified in the SDK's configuration files.
function _tryfix_sdkver_for_cross(sdkdir, sdkver)
local qconfig_path = sdkdir and path.join(sdkdir, "mkspecs", "qconfig.pri")
if not sdkver or not os.isfile(qconfig_path) then
return sdkver
end
-- Extract the actual SDK version from qconfig.pri
local actual_sdkver = io.readfile(qconfig_path):match("QT_VERSION%s*=%s*(%S+)") -- Expected format: QT_VERSION = x.y.z
if not actual_sdkver then
return sdkver
end
if sdkver ~= actual_sdkver then
wprint("Host Qt SDK version (%s) differs from Target Qt SDK version (%s). To prevent build issues, please ensure both use the same version.", sdkver, actual_sdkver);
end
return actual_sdkver
end

-- find qt sdk toolchains
function _find_qt(sdkdir, sdkver)
function _find_qt(sdkdir, sdkver, sdkdir_host)

-- find qmake
local qmake = _find_qmake(sdkdir, sdkver)
local qmake = _find_qmake(sdkdir_host or sdkdir, sdkver)
if not qmake then
return
end

-- get qt environments
local qtenvs = _get_qtenvs(qmake)
local located_sdkdir = sdkdir and _find_sdkdir(sdkdir, sdkver)
local qtenvs = _get_qtenvs(qmake, located_sdkdir or sdkdir)
if not qtenvs then
return
end

-- get qt toolchains
sdkdir = qtenvs.QT_INSTALL_PREFIX
local sdkver = qtenvs.QT_VERSION
local sdkver = _tryfix_sdkver_for_cross(sdkdir, qtenvs.QT_VERSION)
local bindir = qtenvs.QT_INSTALL_BINS
local libexecdir = qtenvs.QT_INSTALL_LIBEXECS
local qmldir = qtenvs.QT_INSTALL_QML
Expand All @@ -259,6 +288,16 @@ function _find_qt(sdkdir, sdkver)
-- TODO
end
end

if sdkdir_host then
local located_sdkdir_host = _find_sdkdir(sdkdir_host, sdkver)
local qtenvs_host = _get_qtenvs(qmake, located_sdkdir_host or sdkdir_host)
if qtenvs_host then
bindir_host = qtenvs_host.QT_HOST_BINS or qtenvs_host.QT_INSTALL_BINS or bindir_host
libexecdir_host = qtenvs_host.QT_HOST_LIBEXECS or qtenvs_host.QT_INSTALL_LIBEXECS or libexecdir_host
end
end

return {sdkdir = sdkdir, bindir = bindir, bindir_host = bindir_host, libexecdir = libexecdir, libexecdir_host = libexecdir_host, libdir = libdir, includedir = includedir, qmldir = qmldir, pluginsdir = pluginsdir, mkspecsdir = mkspecsdir, sdkver = sdkver}
end

Expand All @@ -282,13 +321,16 @@ function main(sdkdir, opt)

-- attempt to load cache first
local key = "detect.sdks.find_qt"
local cacheinfo = detectcache:get(key) or {}
local cacheinfo = (sdkdir and detectcache:get2(key, sdkdir)) or detectcache:get(key) or {}
if not opt.force and cacheinfo.qt and cacheinfo.qt.sdkdir and os.isdir(cacheinfo.qt.sdkdir) then
return cacheinfo.qt
end

-- find qt
local qt = _find_qt(sdkdir or config.get("qt") or global.get("qt") or config.get("sdk"), opt.version or config.get("qt_sdkver"))
local sdkdir = sdkdir or config.get("qt") or global.get("qt") or config.get("sdk")
local sdkver = opt.version or config.get("qt_sdkver")
local sdkdir_host = opt.sdkdir_host or config.get("qt_host") or global.get("qt_host")
local qt = _find_qt(sdkdir, sdkver, sdkdir_host)
if qt then

-- save to config
Expand All @@ -314,7 +356,11 @@ function main(sdkdir, opt)

-- save to cache
cacheinfo.qt = qt or false
detectcache:set(key, cacheinfo)
if sdkdir then
detectcache:set2(key, sdkdir, cacheinfo)
else
detectcache:set(key, cacheinfo)
end
detectcache:save()
return qt
end
2 changes: 2 additions & 0 deletions xmake/platforms/bsd/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ platform("bsd")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {nil, "qt_sdkver", "kv", "auto", "The Qt SDK Version" }
}

Expand All @@ -48,6 +49,7 @@ platform("bsd")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
}
}

Expand Down
2 changes: 2 additions & 0 deletions xmake/platforms/haiku/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ platform("haiku")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {nil, "qt_sdkver", "kv", "auto", "The Qt SDK Version" }
}

Expand All @@ -46,6 +47,7 @@ platform("haiku")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
}
}

Expand Down
2 changes: 2 additions & 0 deletions xmake/platforms/linux/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ platform("linux")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {nil, "qt_sdkver", "kv", "auto", "The Qt SDK Version" }
, {category = "Vcpkg Configuration" }
, {nil, "vcpkg", "kv", "auto", "The Vcpkg Directory" }
Expand All @@ -49,6 +50,7 @@ platform("linux")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {category = "Vcpkg Configuration" }
, {nil, "vcpkg", "kv", "auto", "The Vcpkg Directory" }
}
Expand Down
2 changes: 2 additions & 0 deletions xmake/platforms/macosx/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ platform("macosx")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {nil, "qt_sdkver", "kv", "auto", "The Qt SDK Version" }
, {category = "Vcpkg Configuration" }
, {nil, "vcpkg", "kv", "auto", "The Vcpkg Directory" }
Expand All @@ -63,6 +64,7 @@ platform("macosx")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {category = "Vcpkg Configuration" }
, {nil, "vcpkg", "kv", "auto", "The Vcpkg Directory" }
}
Expand Down
2 changes: 2 additions & 0 deletions xmake/platforms/windows/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ platform("windows")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {nil, "qt_sdkver", "kv", "auto", "The Qt SDK Version" }
, {category = "WDK Configuration" }
, {nil, "wdk", "kv", "auto", "The WDK Directory" }
Expand All @@ -71,6 +72,7 @@ platform("windows")
, {nil, "cuda", "kv", "auto", "The Cuda SDK Directory" }
, {category = "Qt SDK Configuration" }
, {nil, "qt", "kv", "auto", "The Qt SDK Directory" }
, {nil, "qt_host", "kv", "auto", "The Qt Host SDK Directory" }
, {category = "WDK Configuration" }
, {nil, "wdk", "kv", "auto", "The WDK Directory" }
, {category = "Vcpkg Configuration" }
Expand Down
18 changes: 9 additions & 9 deletions xmake/rules/qt/deploy/android.lua
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ function main(target, opt)
end

-- get androiddeployqt
local androiddeployqt = path.join(qt.bindir, "androiddeployqt" .. (is_host("windows") and ".exe" or ""))
if not os.isexec(androiddeployqt) and qt.bindir_host then
androiddeployqt = path.join(qt.bindir_host, "androiddeployqt" .. (is_host("windows") and ".exe" or ""))
local androiddeployqt = qt.bindir_host and path.join(qt.bindir_host, "androiddeployqt" .. (is_host("windows") and ".exe" or ""))
if (not androiddeployqt or not os.isexec(androiddeployqt)) and qt.bindir then
androiddeployqt = path.join(qt.bindir, "androiddeployqt" .. (is_host("windows") and ".exe" or ""))
end
assert(os.isexec(androiddeployqt), "androiddeployqt not found!")

Expand Down Expand Up @@ -152,17 +152,17 @@ function main(target, opt)
settings_file:print(' "target-architecture": "%s",', target_arch)
settings_file:print(' "qml-root-path": "%s",', _escape_path(os.projectdir()))
-- for 6.2.x
local qmlimportscanner = path.join(qt.libexecdir, "qmlimportscanner")
if not os.isexec(qmlimportscanner) and qt.libexecdir_host then
qmlimportscanner = path.join(qt.libexecdir_host, "qmlimportscanner")
local qmlimportscanner = qt.libexecdir_host and path.join(qt.libexecdir_host, "qmlimportscanner" .. (is_host("windows") and ".exe" or ""))
if (not qmlimportscanner or not os.isexec(qmlimportscanner)) and qt.libexecdir then
qmlimportscanner = path.join(qt.libexecdir, "qmlimportscanner" .. (is_host("windows") and ".exe" or ""))
end
if os.isexec(qmlimportscanner) then
settings_file:print(' "qml-importscanner-binary": "%s",', _escape_path(qmlimportscanner))
end
-- for 6.3.x
local rcc = path.join(qt.bindir, "rcc")
if not os.isexec(rcc) and qt.bindir_host then
rcc = path.join(qt.bindir_host, "rcc")
local rcc = qt.bindir_host and path.join(qt.bindir_host, "rcc" .. (is_host("windows") and ".exe" or ""))
if (not rcc or not os.isexec(rcc)) and qt.bindir then
rcc = path.join(qt.bindir, "rcc" .. (is_host("windows") and ".exe" or ""))
end
if os.isexec(rcc) then
settings_file:print(' "rcc-binary": "%s",', _escape_path(rcc))
Expand Down
5 changes: 4 additions & 1 deletion xmake/rules/qt/deploy/macosx.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ function main(target, opt)
local qt = assert(find_qt(), "Qt SDK not found!")

-- get macdeployqt
local macdeployqt = path.join(qt.bindir, "macdeployqt")
local macdeployqt = qt.bindir_host and path.join(qt.bindir_host, "macdeployqt" .. (is_host("windows") and ".exe" or ""))
if (not macdeployqt or not os.isexec(macdeployqt)) and qt.bindir then
macdeployqt = path.join(qt.bindir, "macdeployqt" .. (is_host("windows") and ".exe" or ""))
end
assert(os.isexec(macdeployqt), "macdeployqt not found!")

-- generate target app
Expand Down
6 changes: 5 additions & 1 deletion xmake/rules/qt/env/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ rule("qt.env")

local qmlimportpath = target:values("qt.env.qmlimportpath") or {}
if target:is_plat("windows") or (target:is_plat("mingw") and is_host("windows")) then
target:add("runenvs", "PATH", qt.bindir)
for _, dir in ipairs({qt.bindir_host, qt.bindir}) do
if dir then
target:add("runenvs", "PATH", dir)
end
end
table.insert(qmlimportpath, qt.qmldir)
-- add targetdir in QML2_IMPORT_PATH in case of the user have qml plugins
table.insert(qmlimportpath, target:targetdir())
Expand Down
5 changes: 4 additions & 1 deletion xmake/rules/qt/install/mingw.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ function main(target, opt)
local qt = assert(find_qt(), "Qt SDK not found!")

-- get windeployqt
local windeployqt = path.join(qt.bindir, "windeployqt.exe")
local windeployqt = qt.bindir_host and path.join(qt.bindir_host, "windeployqt" .. (is_host("windows") and ".exe" or ""))
if (not windeployqt or not os.isexec(windeployqt)) and qt.bindir then
windeployqt = path.join(qt.bindir, "windeployqt" .. (is_host("windows") and ".exe" or ""))
end
assert(os.isexec(windeployqt), "windeployqt.exe not found!")

-- find qml directory
Expand Down
9 changes: 6 additions & 3 deletions xmake/rules/qt/install/windows.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ function main(target, opt)
local qt = assert(find_qt(), "Qt SDK not found!")

-- get windeployqt
local windeployqt = path.join(qt.bindir, "windeployqt.exe")
local windeployqt = qt.bindir_host and path.join(qt.bindir_host, "windeployqt" .. (is_host("windows") and ".exe" or ""))
if (not windeployqt or not os.isexec(windeployqt)) and qt.bindir then
windeployqt = path.join(qt.bindir, "windeployqt" .. (is_host("windows") and ".exe" or ""))
end
assert(os.isexec(windeployqt), "windeployqt.exe not found!")

-- find qml directory
Expand Down Expand Up @@ -73,9 +76,9 @@ function main(target, opt)
end
-- bind qt bin path
-- https://github.com/xmake-io/xmake/issues/4297
if qt.bindir then
if qt.bindir_host or qt.bindir then
envs = envs or {}
envs.PATH = {qt.bindir}
envs.PATH = {qt.bindir_host, qt.bindir}
local curpath = os.getenv("PATH")
if curpath then
table.join2(envs.PATH, path.splitenv(curpath))
Expand Down
6 changes: 5 additions & 1 deletion xmake/rules/qt/load.lua
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,11 @@ function main(target, opt)
target:add("linkdirs", qt.libdir)
target:add("syslinks", "ws2_32", "gdi32", "ole32", "advapi32", "shell32", "user32", "opengl32", "imm32", "winmm", "iphlpapi")
-- for debugger, https://github.com/xmake-io/xmake-vscode/issues/225
target:add("runenvs", "PATH", qt.bindir)
for _, dir in ipairs({qt.bindir_host, qt.bindir}) do
if dir then
target:add("runenvs", "PATH", dir)
end
end
elseif target:is_plat("mingw") then
target:set("frameworks", nil)
-- we need to fix it, because gcc maybe does not work on latest mingw when `-isystem D:\a\_temp\msys64\mingw64\include` is passed.
Expand Down
15 changes: 9 additions & 6 deletions xmake/rules/qt/moc/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ rule("qt.moc")

-- get moc
local qt = assert(target:data("qt"), "Qt not found!")
local moc = path.join(qt.bindir, is_host("windows") and "moc.exe" or "moc")
if not os.isexec(moc) and qt.libexecdir then
moc = path.join(qt.libexecdir, is_host("windows") and "moc.exe" or "moc")
end
if not os.isexec(moc) and qt.libexecdir_host then
moc = path.join(qt.libexecdir_host, is_host("windows") and "moc.exe" or "moc")
local moc
local moc_name = is_host("windows") and "moc.exe" or "moc"
for _, dir in ipairs({qt.bindir_host, qt.libexecdir_host, qt.bindir, qt.libexecdir}) do
if dir then
moc = path.join(dir, moc_name)
if os.isexec(moc) then
break
end
end
end
assert(moc and os.isexec(moc), "moc not found!")

Expand Down
15 changes: 9 additions & 6 deletions xmake/rules/qt/qmltyperegistrar/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@ rule("qt.qmltyperegistrar")
local qt = assert(target:data("qt"), "Qt not found!")

-- get qmltyperegistrar
local qmltyperegistrar = path.join(qt.bindir, is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar")
if not os.isexec(qmltyperegistrar) and qt.libexecdir then
qmltyperegistrar = path.join(qt.libexecdir, is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar")
end
if not os.isexec(qmltyperegistrar) and qt.libexecdir_host then
qmltyperegistrar = path.join(qt.libexecdir_host, is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar")
local qmltyperegistrar
local qmltyperegistrar_name = is_host("windows") and "qmltyperegistrar.exe" or "qmltyperegistrar"
for _, dir in ipairs({qt.bindir_host, qt.libexecdir_host, qt.bindir, qt.libexecdir}) do
if dir then
qmltyperegistrar = path.join(dir, qmltyperegistrar_name)
if os.isexec(qmltyperegistrar) then
break
end
end
end
assert(qmltyperegistrar and os.isexec(qmltyperegistrar), "qmltyperegistrar not found!")

Expand Down
15 changes: 9 additions & 6 deletions xmake/rules/qt/qrc/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ rule("qt.qrc")

-- get rcc
local qt = assert(target:data("qt"), "Qt not found!")
local rcc = path.join(qt.bindir, is_host("windows") and "rcc.exe" or "rcc")
if not os.isexec(rcc) and qt.libexecdir then
rcc = path.join(qt.libexecdir, is_host("windows") and "rcc.exe" or "rcc")
end
if not os.isexec(rcc) and qt.libexecdir_host then
rcc = path.join(qt.libexecdir_host, is_host("windows") and "rcc.exe" or "rcc")
local rcc
local rcc_name = is_host("windows") and "rcc.exe" or "rcc"
for _, dir in ipairs({qt.bindir_host, qt.libexecdir_host, qt.bindir, qt.libexecdir}) do
if dir then
rcc = path.join(dir, rcc_name)
if os.isexec(rcc) then
break
end
end
end
assert(os.isexec(rcc), "rcc not found!")

Expand Down
Loading
Loading