From 9214e805d9ff63adfa7066a15b03da0ee652b4da Mon Sep 17 00:00:00 2001 From: Andrey Bychkov Date: Tue, 11 Aug 2026 19:04:33 +0300 Subject: [PATCH] add rpm support for deploy_tool --- utils/deploy_tool/main.cpp | 81 ++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/utils/deploy_tool/main.cpp b/utils/deploy_tool/main.cpp index 69b15942..b1a7acb9 100644 --- a/utils/deploy_tool/main.cpp +++ b/utils/deploy_tool/main.cpp @@ -40,7 +40,7 @@ void setCommands() { cmd_copydir = "cp -rf "; ign_err_suffix = " 2> /dev/null"; # ifdef MAC_OS - qplatforms = "cocoa"; + qplatforms = "cocoa"; # else qplatforms = "xcb,wayland"; # endif @@ -88,6 +88,8 @@ void usage() { piCout << "-M " << Green << "- \"otool\" path, overrides \"ldd\""; piCout << "-D " << Green << "- \"dpkg\" path, default \"/usr/bin/dpkg\""; piCout << "--dpkg-workdir " << Green << "- dpkg \"admindir\" path, default \"\""; + piCout << "-R " << Green << "- \"rpm\" path, overrides \"dpkg\" for dependency queries"; + piCout << "--rpm-rootdir " << Green << "- rpm \"--root\" path, default \"\""; piCout << "--name-tool " << Green << "- \"install_name_tool\" path, default \"install_name_tool\""; piCout << "--strip " << Green << "- \"strip\" path, default \"strip\""; piCout << "--no-strip " << Green << "- disable strip (save debug info)"; @@ -108,7 +110,7 @@ void usage() { piCout << "--qt-plugins-dir " << Green << "- dir where place Qt plugins, default \"\""; piCout << "--qt-qml-dir " << Green << "- dir where place Qt QML modules, default \"\""; piCout << "--qt-conf-dir " << Green << "- dir where place \"qt.conf\", default \"\""; - piCout << "--dependencies " << Green << "- search dependencies by , print them and copy missing libraries"; + piCout << "--dependencies " << Green << "- search dependencies by or , print them and copy missing libraries"; piCout << "--prefix " << Green << "- print before dependencies"; piCout << ""; piCout << Bold << "Input control"; @@ -143,8 +145,9 @@ QtDep qt_deps[] = {QtDep("core", PIStringList() << "platforms"), int depth = 8; -bool fake = false, is_ldd = true, is_deps = false, need_qt = false, make_qt_format = true, rpath = false, win_target = false; -PIString ldd, readelf, objdump, otool, dpkg, nametool, strip, out_dir, qt_dir, dpkg_workdir; +bool fake = false, is_ldd = true, is_deps = false, need_qt = false, make_qt_format = true, rpath = false, win_target = false, + use_rpm = false; +PIString ldd, readelf, objdump, otool, dpkg, rpm_tool, nametool, strip, out_dir, qt_dir, dpkg_workdir, rpm_rootdir; PIString qt_pref, qt_suff, qt_conf_dir, qt_plugins_dir, qt_qml_dir, target_dir; PIStringList styles, lib_dirs, add_libs, platforms, sqldrivers, input_files, plugin_libs, qt_add_libs, qml_list; PISet all_libs, miss_libs, all_deps, frameworks, framework_libs, miss_frameworks, qt_plugins, ignore_libs, qt_libs; @@ -270,8 +273,8 @@ void procLdd(PIString file, bool ext_lib = false, int cur_depth = 0) { ++cur_depth; if (cur_depth > depth) return; static PIStringList ignore_ext = {"png", "jpg", "jpeg", "gif", "bmp", "svg", "tif", "tiff", "ico", "pdf", - "txt", "cfg", "conf", "json", "qml", "glsl", "fraq", "vert", "geom", "qmltypes", - "metainfo", "ts", "qm", "ttf", "htm", "html", "md", "sms", "smsee", "blockmodel"}; + "txt", "cfg", "conf", "json", "qml", "glsl", "fraq", "vert", "geom", "qmltypes", + "metainfo", "ts", "qm", "ttf", "htm", "html", "md", "sms", "smsee", "blockmodel"}; PIString ext = PIFile::FileInfo(file).extension(); if (ignore_ext.contains(ext.toLowerCase())) return; piCout << "scan" << file << "..."; @@ -381,7 +384,7 @@ void copyWildcard(const PIString & from, const PIString & to) { PIFile::FileInfo fi(from); system(("robocopy \"" + fi.dir() + "\" \"" + to + "\" \"" + fi.name() + "\" /E /NJH /NJS /NP /NDL /NS /NC /NFL 1> NUL").data()); #else - auto _r = system((cmd_copy + from + " \"" + to + "/\"" + cmd_suffix).data()); + auto _r = system((cmd_copy + from + " \"" + to + "/\"" + cmd_suffix).data()); NO_UNUSED(_r); #endif } @@ -488,6 +491,43 @@ bool procDpkg(const PIString & l) { } +bool procRpm(const PIString & l) { + PIString rpmdir; + if (!rpm_rootdir.isEmpty()) rpmdir = " --root " + rpm_rootdir; + PIFile::FileInfo fi; + fi.path = l; + PIString cmd = rpm_tool + rpmdir + " -qf " + fi.path + ign_err_suffix; + // PICout(true) << "** rpm:" << cmd; + PIString vs = execute(cmd).trim(); + if (!vs.isEmpty()) { + PIStringList lines = vs.split('\n'); + for (auto line: lines) { + line.trim(); + if (line.isEmpty()) continue; + // Filter out -devel, -debuginfo, -static packages + if (line.contains("-devel") || line.contains("-debuginfo") || line.contains("-static")) continue; + // Extract package name: "name-version-release.arch" → "name" + // Find first hyphen that's not part of version + int verStart = -1; + for (int i = 0; i < line.size_s(); ++i) { + if (line[i] == '-' && i + 1 < line.size_s() && line[i + 1].isDigit()) { + verStart = i; + break; + } + } + if (verStart > 0) { + PIString pkgName = line.left(verStart); + // PICout(true) << "** found \"" << pkgName << "\" for \"" << l << "\""; + all_deps << pkgName; + return true; + } + } + } + // piCout << "No rpm dep on" << l; + return false; +} + + void patchNameTool() { if (nametool.isEmpty()) return; PIStringList clibs = all_libs.toVector(), flibs = framework_libs.toVector(), patch_list; @@ -616,6 +656,8 @@ int main(int argc, char * argv[]) { cli.addArgument("no-strip", PIChar('\0'), false); cli.addArgument("Dpkg", true); cli.addArgument("dpkg-workdir", PIChar('\0'), true); + cli.addArgument("Rpm", true); + cli.addArgument("rpm-rootdir", PIChar('\0'), true); cli.addArgument("depth", true); cli.addArgument("qtdir", true); cli.addArgument("add_libs", true); @@ -645,14 +687,19 @@ int main(int argc, char * argv[]) { if (cli.hasArgument("no-strip")) strip.clear(); dpkg = cli.argumentValue("Dpkg"); dpkg_workdir = cli.argumentValue("dpkg-workdir"); + rpm_tool = cli.argumentValue("Rpm"); + rpm_rootdir = cli.argumentValue("rpm-rootdir"); + if (!rpm_tool.isEmpty()) use_rpm = true; #ifdef WINDOWS readelf.replaceAll("/", "\\"); objdump.replaceAll("/", "\\"); otool.replaceAll("/", "\\"); nametool.replaceAll("/", "\\"); dpkg.replaceAll("/", "\\"); + rpm_tool.replaceAll("/", "\\"); #endif if (dpkg.isEmpty()) dpkg = "/usr/bin/dpkg"; + if (rpm_tool.isEmpty()) rpm_tool = "/usr/bin/rpm"; int etcnt = 0; if (!readelf.isEmpty()) ++etcnt; if (!objdump.isEmpty()) ++etcnt; @@ -707,14 +754,14 @@ int main(int argc, char * argv[]) { qt_add_libs = cli.argumentValue("qt-modules").split(DELIM).removeAll(""); auto getQtSubdir = [&cli](const char * arg, PIString & var) { - var = cli.argumentValue(arg).trim(); - if (var.isEmpty()) - var = out_dir; - else { - if (!PIFile::FileInfo(var).isAbsolute()) var = out_dir + "/" + var; - } - if (!var.endsWith("/")) var += "/"; - var.replaceAll("//", "/"); + var = cli.argumentValue(arg).trim(); + if (var.isEmpty()) + var = out_dir; + else { + if (!PIFile::FileInfo(var).isAbsolute()) var = out_dir + "/" + var; + } + if (!var.endsWith("/")) var += "/"; + var.replaceAll("//", "/"); }; getQtSubdir("qt-conf-dir", qt_conf_dir); getQtSubdir("qt-plugins-dir", qt_plugins_dir); @@ -771,7 +818,7 @@ int main(int argc, char * argv[]) { PIVector qlibs = qt_libs.toVector(); piCout << "check for installed Qt" << qlibs; for (const auto & l: qlibs) { - if (procDpkg(l)) { + if (use_rpm ? procRpm(l) : procDpkg(l)) { piCout << "system Qt found!"; need_qt_plugins = false; break; @@ -817,7 +864,7 @@ int main(int argc, char * argv[]) { l.replaceAll("/", "\\"); #endif bool need_cp = true; - if (is_deps) need_cp = !procDpkg(l); + if (is_deps) need_cp = !(use_rpm ? procRpm(l) : procDpkg(l)); if (need_cp) { piCout << "copy" << l; if (!fake) {