mirror of
https://github.com/QuasarApp/CQtDeployer.git
synced 2025-04-28 02:34:34 +00:00
build fix
This commit is contained in:
parent
f7db00d8be
commit
a6c4ddadf9
@ -5,13 +5,14 @@
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#include "deploy.h"
|
||||
#include "extracter.h"
|
||||
#include "quasarapp.h"
|
||||
#include "deploycore.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QList>
|
||||
#include <deploy.h>
|
||||
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
@ -25,15 +26,16 @@ int main(int argc, const char *argv[]) {
|
||||
qWarning() << "wrong parametrs";
|
||||
DeployCore::help();
|
||||
exit(0);
|
||||
};
|
||||
}
|
||||
QuasarAppUtils::Params::setEnable("noWriteInFileLog", true);
|
||||
|
||||
|
||||
Deploy deploy;
|
||||
|
||||
if (!DeployCore::parseQt(&deploy)) {
|
||||
if (!deploy.prepare()) {
|
||||
qCritical() << "error parse imput data";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return deploy.deploy();
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ SOURCES += \
|
||||
cqt.cpp \
|
||||
deploy.cpp \
|
||||
deploycore.cpp \
|
||||
deployparams.cpp \
|
||||
envirement.cpp \
|
||||
extracter.cpp \
|
||||
filemanager.cpp \
|
||||
pe.cpp \
|
||||
igetlibinfo.cpp \
|
||||
@ -65,8 +65,8 @@ HEADERS += \
|
||||
deploy.h \
|
||||
deploy_global.h \
|
||||
deploycore.h \
|
||||
deployparams.h \
|
||||
envirement.h \
|
||||
extracter.h \
|
||||
filemanager.h \
|
||||
pe.h \
|
||||
igetlibinfo.h \
|
||||
|
135
Deploy/cqt.cpp
135
Deploy/cqt.cpp
@ -4,6 +4,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include "deploycore.h"
|
||||
#include "filemanager.h"
|
||||
#include "quasarapp.h"
|
||||
|
||||
bool CQT::parseParams() {
|
||||
@ -16,6 +17,8 @@ bool CQT::parseParams() {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeployCore::_config = &_config;
|
||||
|
||||
return true;
|
||||
}
|
||||
case RunMode::Clear: {
|
||||
@ -26,6 +29,8 @@ bool CQT::parseParams() {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeployCore::_config = &_config;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -37,6 +42,8 @@ bool CQT::parseParams() {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeployCore::_config = &_config;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -45,12 +52,8 @@ bool CQT::parseParams() {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeployConfig CQT::config() const {
|
||||
|
||||
}
|
||||
|
||||
void CQT::setConfig(const DeployConfig &config) {
|
||||
_config = config;
|
||||
const DeployConfig *CQT::config() const {
|
||||
return &_config;
|
||||
}
|
||||
|
||||
bool CQT::createFromDeploy() const {
|
||||
@ -63,14 +66,88 @@ bool CQT::loadFromFile() {
|
||||
|
||||
bool CQT::parseQtDeployMode() {
|
||||
|
||||
auto bin = QuasarAppUtils::Params::getStrArg("bin").split(',');
|
||||
|
||||
if (!setTargets(bin)) {
|
||||
|
||||
auto binDir = QuasarAppUtils::Params::getStrArg("binDir");
|
||||
if (!(setTargetsRecursive(binDir) || setTargets({"./"}))) {
|
||||
qCritical() << "setTargetDir fail!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
initIgnoreEnvList();
|
||||
initEnvirement();
|
||||
initIgnoreList();
|
||||
|
||||
_config.depchLimit = 0;
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("recursiveDepth")) {
|
||||
bool ok;
|
||||
_config.depchLimit = QuasarAppUtils::Params::getArg("recursiveDepth").toInt(&ok);
|
||||
if (!ok) {
|
||||
_config.depchLimit = 0;
|
||||
qWarning() << "recursiveDepth is invalid! use default value 0";
|
||||
}
|
||||
}
|
||||
|
||||
auto listLibDir = QuasarAppUtils::Params::getStrArg("libDir").split(",");
|
||||
auto listExtraPlugin =
|
||||
QuasarAppUtils::Params::getStrArg("extraPlugin").split(",");
|
||||
setExtraPath(listLibDir);
|
||||
setExtraPlugins(listExtraPlugin);
|
||||
|
||||
auto qmake = QuasarAppUtils::Params::getStrArg("qmake");
|
||||
QString basePath = "";
|
||||
|
||||
QFileInfo info(qmake);
|
||||
|
||||
if (!info.isFile() || (info.baseName() != "qmake")) {
|
||||
qInfo() << "deploy only C libs because qmake is not found";
|
||||
return true;
|
||||
}
|
||||
|
||||
basePath = info.absolutePath();
|
||||
setQmake(qmake);
|
||||
|
||||
auto qmlDir = QuasarAppUtils::Params::getStrArg("qmlDir");
|
||||
QDir dir(basePath);
|
||||
|
||||
if (QFileInfo::exists(qmlDir) ||
|
||||
QuasarAppUtils::Params::isEndable("allQmlDependes")) {
|
||||
_config.deployQml = true;
|
||||
|
||||
} else {
|
||||
QuasarAppUtils::Params::verboseLog("qml dir not exits!",
|
||||
QuasarAppUtils::VerboseLvl::Warning);
|
||||
}
|
||||
|
||||
if (!dir.cdUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setQtDir(dir.absolutePath());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CQT::parseQtInfoMode() {
|
||||
if ((QuasarAppUtils::Params::isEndable("v") ||
|
||||
QuasarAppUtils::Params::isEndable("version"))) {
|
||||
DeployCore::printVersion();
|
||||
return true;
|
||||
}
|
||||
|
||||
DeployCore::help();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CQT::parseQtClearMode() {
|
||||
setTargetDir("./");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CQT::setTargetDir(const QString &target) {
|
||||
@ -343,8 +420,50 @@ QStringList CQT::getDirsRecursive(const QString &path) {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CQT::smartMoveTargets() {
|
||||
|
||||
QMap<QString, bool> temp;
|
||||
bool result = true;
|
||||
for (auto i = _config.targets.cbegin(); i != _config.targets.cend(); ++i) {
|
||||
|
||||
QFileInfo target(i.key());
|
||||
auto targetPath = _config.targetDir + (DeployCore::isLib(target) ? "/lib" : "/bin");
|
||||
|
||||
if (target.completeSuffix().contains("dll", Qt::CaseInsensitive) ||
|
||||
target.completeSuffix().contains("exe", Qt::CaseInsensitive)) {
|
||||
|
||||
targetPath = _config.targetDir;
|
||||
|
||||
}
|
||||
|
||||
if (!_fileManager->smartCopyFile(target.absoluteFilePath(), targetPath, _config.targetDir)) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
|
||||
CQT::CQT() {
|
||||
|
||||
temp.insert(targetPath + "/" + target.fileName(), i.value());
|
||||
|
||||
}
|
||||
|
||||
_config.targets = temp;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CQT::CQT(FileManager *filemanager):
|
||||
_fileManager(filemanager) {
|
||||
|
||||
assert(_fileManager);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
_config.appDir = QuasarAppUtils::Params::getStrArg("appPath");
|
||||
|
||||
if (_config.appDir.right(4) == "/bin") {
|
||||
_config.appDir = _config.appDir.left(_config.appDir.size() - 4);
|
||||
}
|
||||
#else
|
||||
_config.appDir = QuasarAppUtils::Params::getStrArg("appPath");
|
||||
#endif
|
||||
|
||||
QuasarAppUtils::Params::verboseLog("appDir = " + _config.appDir);
|
||||
}
|
||||
|
11
Deploy/cqt.h
11
Deploy/cqt.h
@ -9,6 +9,7 @@
|
||||
#include <QMap>
|
||||
#include <QDir>
|
||||
|
||||
class FileManager;
|
||||
|
||||
struct DeployConfig {
|
||||
QString qmake = "";
|
||||
@ -40,7 +41,7 @@ class CQT
|
||||
private:
|
||||
|
||||
DeployConfig _config;
|
||||
|
||||
FileManager *_fileManager;
|
||||
bool createFromDeploy() const;
|
||||
bool loadFromFile();
|
||||
bool parseQtDeployMode();
|
||||
@ -68,12 +69,14 @@ private:
|
||||
void initEnvirement();
|
||||
|
||||
QStringList getDirsRecursive(const QString &path);
|
||||
|
||||
bool smartMoveTargets();
|
||||
|
||||
public:
|
||||
CQT();
|
||||
CQT(FileManager *filemanager);
|
||||
bool parseParams();
|
||||
|
||||
DeployConfig config() const;
|
||||
void setConfig(const DeployConfig &config);
|
||||
const DeployConfig* config() const;
|
||||
};
|
||||
|
||||
#endif // CQT_H
|
||||
|
@ -5,560 +5,26 @@
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#include "cqt.h"
|
||||
#include "deploy.h"
|
||||
#include "deploycore.h"
|
||||
#include "pluginsparser.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include "extracter.h"
|
||||
#include "filemanager.h"
|
||||
#include <quasarapp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include <fstream>
|
||||
|
||||
|
||||
bool Deploy::getDeployQml() const { return deployQml; }
|
||||
|
||||
void Deploy::setDeployQml(bool value) { deployQml = value; }
|
||||
|
||||
QString Deploy::getQmlScaner() const { return externQmlScaner; }
|
||||
|
||||
QString Deploy::getQmake() const { return qmake; }
|
||||
|
||||
void Deploy::clear(bool force) {
|
||||
_fileManager.clear(targetDir, force);
|
||||
}
|
||||
|
||||
bool Deploy::deployMSVC() {
|
||||
qInfo () << "try deploy msvc";
|
||||
|
||||
auto msvcInstaller = DeployCore::getVCredist(qmake);
|
||||
|
||||
if (msvcInstaller.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _fileManager.copyFile(msvcInstaller, targetDir);
|
||||
}
|
||||
|
||||
bool Deploy::createRunScript(const QString &target) {
|
||||
|
||||
QString content =
|
||||
"#!/bin/sh\n"
|
||||
"BASE_DIR=$(dirname \"$(readlink -f \"$0\")\")\n"
|
||||
"export "
|
||||
"LD_LIBRARY_PATH=\"$BASE_DIR\"/lib:\"$BASE_DIR\":$LD_LIBRARY_PATH\n"
|
||||
"export QML_IMPORT_PATH=\"$BASE_DIR\"/qml:QML_IMPORT_PATH\n"
|
||||
"export QML2_IMPORT_PATH=\"$BASE_DIR\"/qml:QML2_IMPORT_PATH\n"
|
||||
"export QT_PLUGIN_PATH=\"$BASE_DIR\"/plugins:QT_PLUGIN_PATH\n"
|
||||
"export QTDIR=\"$BASE_DIR\"\n"
|
||||
"export "
|
||||
"QT_QPA_PLATFORM_PLUGIN_PATH=\"$BASE_DIR\"/plugins/"
|
||||
"platforms:QT_QPA_PLATFORM_PLUGIN_PATH\n"
|
||||
"%2"
|
||||
"\"$BASE_DIR\"/bin/%1 \"$@\"";
|
||||
|
||||
content = content.arg(QFileInfo(target).fileName());
|
||||
int ld_index = find("ld-linux", _fileManager.getDeployedFilesStringList());
|
||||
|
||||
if (ld_index >= 0 && QuasarAppUtils::Params::isEndable("deploySystem") &&
|
||||
!QuasarAppUtils::Params::isEndable("noLibc")) {
|
||||
|
||||
content = content.arg(QString("\nexport LD_PRELOAD=\"$BASE_DIR\"/lib/%0\n").
|
||||
arg(QFileInfo(_fileManager.getDeployedFilesStringList()[ld_index]).fileName()));
|
||||
} else {
|
||||
content = content.arg("");
|
||||
}
|
||||
|
||||
|
||||
QString fname = targetDir + QDir::separator() + QFileInfo(target).baseName()+ ".sh";
|
||||
|
||||
QFile F(fname);
|
||||
if (!F.open(QIODevice::WriteOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
F.write(content.toUtf8());
|
||||
F.flush();
|
||||
F.close();
|
||||
|
||||
_fileManager.addToDeployed(fname);
|
||||
|
||||
return F.setPermissions(QFileDevice::ExeOther | QFileDevice::WriteOther |
|
||||
QFileDevice::ReadOther | QFileDevice::ExeUser |
|
||||
QFileDevice::WriteUser | QFileDevice::ReadUser |
|
||||
QFileDevice::ExeOwner | QFileDevice::WriteOwner |
|
||||
QFileDevice::ReadOwner);
|
||||
}
|
||||
|
||||
bool Deploy::createQConf() {
|
||||
|
||||
QString content =
|
||||
"[Paths]\n"
|
||||
"Prefix= ./\n"
|
||||
"Libraries= ./\n"
|
||||
"Plugins= ./plugins\n"
|
||||
"Imports= ./qml\n"
|
||||
"Qml2Imports= ./qml\n";
|
||||
|
||||
|
||||
QString fname = targetDir + QDir::separator() + "qt.conf";
|
||||
|
||||
QFile F(fname);
|
||||
if (!F.open(QIODevice::WriteOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
F.write(content.toUtf8());
|
||||
F.flush();
|
||||
F.close();
|
||||
|
||||
_fileManager.addToDeployed(fname);
|
||||
|
||||
return F.setPermissions(QFileDevice::ExeOther | QFileDevice::WriteOther |
|
||||
QFileDevice::ReadOther | QFileDevice::ExeUser |
|
||||
QFileDevice::WriteUser | QFileDevice::ReadUser |
|
||||
QFileDevice::ExeOwner | QFileDevice::WriteOwner |
|
||||
QFileDevice::ReadOwner);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Deploy::deploy() {
|
||||
qInfo() << "target deploy started!!";
|
||||
|
||||
smartMoveTargets();
|
||||
|
||||
for (auto i = targets.cbegin(); i != targets.cend(); ++i) {
|
||||
extract(i.key());
|
||||
}
|
||||
|
||||
if (deployQml && !extractQml()) {
|
||||
qCritical() << "qml not extacted!";
|
||||
}
|
||||
|
||||
PluginsParser pluginsParser(&scaner);
|
||||
|
||||
QStringList plugins;
|
||||
pluginsParser.scan(DeployCore::qtDir + "/plugins", plugins);
|
||||
copyPlugins(plugins);
|
||||
|
||||
|
||||
_fileManager.copyFiles(neadedLibs, targetDir);
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("deploySystem")) {
|
||||
_fileManager.copyFiles(systemLibs, targetDir);
|
||||
}
|
||||
|
||||
if (!QuasarAppUtils::Params::isEndable("noStrip") && !_fileManager.strip(targetDir)) {
|
||||
QuasarAppUtils::Params::verboseLog("strip failed!");
|
||||
}
|
||||
|
||||
if (!QuasarAppUtils::Params::isEndable("noTranslations")) {
|
||||
if (!copyTranslations(DeployCore::extractTranslation(neadedLibs))) {
|
||||
qWarning() << " copy TR ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
if (!deployMSVC()) {
|
||||
QuasarAppUtils::Params::verboseLog("deploy msvc failed");
|
||||
}
|
||||
|
||||
bool targetWindows = false;
|
||||
|
||||
for (auto i = targets.cbegin(); i != targets.cend(); ++i) {
|
||||
|
||||
if (QFileInfo(i.key()).completeSuffix() == "exe") {
|
||||
targetWindows = true;
|
||||
}
|
||||
|
||||
if (i.value() && !createRunScript(i.key())) {
|
||||
qCritical() << "run script not created!";
|
||||
}
|
||||
}
|
||||
|
||||
if (targetWindows && !createQConf()) {
|
||||
QuasarAppUtils::Params::verboseLog("create qt.conf failr", QuasarAppUtils::Warning);
|
||||
}
|
||||
|
||||
_fileManager.saveDeploymendFiles(targetDir);
|
||||
|
||||
qInfo() << "deploy done!";
|
||||
|
||||
|
||||
}
|
||||
|
||||
QString Deploy::getQtDir() const { return DeployCore::qtDir; }
|
||||
|
||||
void Deploy::setDepchLimit(int value) { depchLimit = value; }
|
||||
|
||||
int Deploy::find(const QString &str, const QStringList &list) const {
|
||||
for (int i = 0 ; i < list.size(); ++i) {
|
||||
if (list[i].contains(str))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Deploy::copyPlugin(const QString &plugin) {
|
||||
|
||||
QStringList listItems;
|
||||
|
||||
if (!_fileManager.copyFolder(plugin, targetDir + "/plugins/" + QFileInfo(plugin).fileName(),
|
||||
QStringList() << ".so.debug" << "d.dll", &listItems)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto item : listItems) {
|
||||
extract(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Deploy::copyPlugins(const QStringList &list) {
|
||||
for (auto plugin : list) {
|
||||
if (!copyPlugin(plugin)) {
|
||||
qWarning() << plugin << " not copied!";
|
||||
}
|
||||
}
|
||||
QFileInfo info;
|
||||
|
||||
for (auto extraPlugin : extraPlugins) {
|
||||
|
||||
info.setFile(extraPlugin);
|
||||
if (info.isDir()) {
|
||||
|
||||
_fileManager.copyFolder(info.absoluteFilePath(),
|
||||
targetDir + "/plugins/" + info.baseName(),
|
||||
QStringList() << ".so.debug" << "d.dll");
|
||||
} else {
|
||||
_fileManager.copyFile(info.absoluteFilePath(),
|
||||
targetDir + QDir::separator() + "plugins");
|
||||
extract(info.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Deploy::copyTranslations(QStringList list) {
|
||||
|
||||
QDir dir(translationDir);
|
||||
if (!dir.exists() || list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
for (auto &&i: list) {
|
||||
filters.push_back("*" + i + "*");
|
||||
}
|
||||
|
||||
auto listItems = dir.entryInfoList(filters, QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto &&i: listItems) {
|
||||
_fileManager.copyFile(i.absoluteFilePath(), targetDir + "/translations");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QFileInfoList Deploy::findFilesInsideDir(const QString &name,
|
||||
const QString &dirpath) {
|
||||
QFileInfoList files;
|
||||
|
||||
QDir dir(dirpath);
|
||||
|
||||
auto list = dir.entryInfoList( QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto && item :list) {
|
||||
if (item.isFile()) {
|
||||
if (item.fileName().contains(name)) {
|
||||
files += item;
|
||||
}
|
||||
} else {
|
||||
files += findFilesInsideDir(name, item.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
QString Deploy::filterQmlPath(const QString &path) {
|
||||
if (path.contains(qmlDir)) {
|
||||
auto endIndex = path.indexOf(QDir::separator(), qmlDir.size() + 1);
|
||||
QString module =
|
||||
path.mid(qmlDir.size() + 1, endIndex - qmlDir.size() - 1);
|
||||
return qmlDir + QDir::separator() + module;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void Deploy::extractLib(const QString &file) {
|
||||
qInfo() << "extract lib :" << file;
|
||||
|
||||
auto data = scaner.scan(file);
|
||||
|
||||
for (auto &line : data) {
|
||||
bool isIgnore = false;
|
||||
for (auto ignore : ignoreList) {
|
||||
if (line.fullPath().contains(ignore)) {
|
||||
QuasarAppUtils::Params::verboseLog(line.fullPath() + " ignored by filter" + ignore);
|
||||
isIgnore = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIgnore) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.getPriority() != LibPriority::SystemLib && !neadedLibs.contains(line.fullPath())) {
|
||||
neadedLibs << line.fullPath();
|
||||
} else if (QuasarAppUtils::Params::isEndable("deploySystem") &&
|
||||
line.getPriority() == LibPriority::SystemLib &&
|
||||
!systemLibs.contains(line.fullPath())) {
|
||||
systemLibs << line.fullPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString Deploy::concatEnv() const {
|
||||
|
||||
if (deployEnvironment.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
QString result = deployEnvironment.first();
|
||||
for (auto i: deployEnvironment) {
|
||||
result += (":" + i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Deploy::smartMoveTargets() {
|
||||
|
||||
QMap<QString, bool> temp;
|
||||
bool result = true;
|
||||
for (auto i = targets.cbegin(); i != targets.cend(); ++i) {
|
||||
|
||||
QFileInfo target(i.key());
|
||||
auto targetPath = targetDir + (isLib(target) ? "/lib" : "/bin");
|
||||
|
||||
if (target.completeSuffix().contains("dll", Qt::CaseInsensitive) ||
|
||||
target.completeSuffix().contains("exe", Qt::CaseInsensitive)) {
|
||||
|
||||
targetPath = targetDir;
|
||||
|
||||
}
|
||||
|
||||
if (!_fileManager.smartCopyFile(target.absoluteFilePath(), targetPath, targetDir)) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
|
||||
temp.insert(targetPath + "/" + target.fileName(), i.value());
|
||||
|
||||
}
|
||||
|
||||
targets = temp;
|
||||
|
||||
scaner.setEnvironment(deployEnvironment);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Deploy::isLib(const QFileInfo &file) {
|
||||
return file.completeSuffix().contains("so", Qt::CaseInsensitive)
|
||||
|| file.completeSuffix().contains("dll", Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QStringList Deploy::extractImportsFromDir(const QString &filepath) {
|
||||
QProcess p;
|
||||
|
||||
QProcessEnvironment env;
|
||||
|
||||
env.insert("LD_LIBRARY_PATH", concatEnv());
|
||||
env.insert("QML_IMPORT_PATH", DeployCore::qtDir + "/qml");
|
||||
env.insert("QML2_IMPORT_PATH", DeployCore::qtDir + "/qml");
|
||||
env.insert("QT_PLUGIN_PATH", DeployCore::qtDir + "/plugins");
|
||||
env.insert("QT_QPA_PLATFORM_PLUGIN_PATH", DeployCore::qtDir + "/plugins/platforms");
|
||||
|
||||
p.setProcessEnvironment(env);
|
||||
p.setProgram(externQmlScaner);
|
||||
p.setArguments(QStringList()
|
||||
<< "-rootPath" << filepath << "-importPath" << qmlDir);
|
||||
p.start();
|
||||
|
||||
if (!p.waitForFinished()) {
|
||||
qWarning() << filepath << " not scaning!";
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
auto rawData = p.readAll();
|
||||
|
||||
if (p.exitCode()) {
|
||||
qWarning() << "scaner error " << p.errorString() << "exitCode: " << p.exitCode();
|
||||
}
|
||||
|
||||
QuasarAppUtils::Params::verboseLog("rawData from extractImportsFromDir: " + rawData);
|
||||
|
||||
auto data = QJsonDocument::fromJson(rawData);
|
||||
|
||||
if (!data.isArray()) {
|
||||
qWarning() << "wrong data from qml scaner! of " << filepath;
|
||||
}
|
||||
|
||||
auto array = data.array();
|
||||
|
||||
QStringList result;
|
||||
|
||||
for (auto object : array) {
|
||||
|
||||
auto module = object.toObject().value("path").toString();
|
||||
|
||||
if (module.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!result.contains(module)) {
|
||||
result << module;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Deploy::extractQmlAll() {
|
||||
|
||||
if (!QFileInfo::exists(qmlDir)) {
|
||||
qWarning() << "qml dir wrong!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList listItems;
|
||||
|
||||
if (!_fileManager.copyFolder(qmlDir, targetDir + "/qml",
|
||||
QStringList() << ".so.debug" << "d.dll",
|
||||
&listItems)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto item : listItems) {
|
||||
extract(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Deploy::extractQmlFromSource(const QString& sourceDir) {
|
||||
|
||||
QFileInfo info(sourceDir);
|
||||
|
||||
if (!info.isDir()) {
|
||||
qCritical() << "extract qml fail! qml source dir not exits or is not dir " << sourceDir;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasarAppUtils::Params::verboseLog("extractQmlFromSource " + info.absoluteFilePath());
|
||||
|
||||
if (!QFileInfo::exists(qmlDir)) {
|
||||
qWarning() << "qml dir wrong!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList plugins;
|
||||
QStringList listItems;
|
||||
QStringList filter;
|
||||
filter << ".so.debug" << "d.dll" << ".pdb";
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("qmlExtern")) {
|
||||
|
||||
/// @todo remove in verison 1.3
|
||||
qInfo() << "use extern qml scaner!";
|
||||
|
||||
plugins = extractImportsFromDir(info.absoluteFilePath());
|
||||
|
||||
} else {
|
||||
qInfo() << "use own qml scaner!";
|
||||
|
||||
QML ownQmlScaner(qmlDir);
|
||||
|
||||
if (!ownQmlScaner.scan(plugins, info.absoluteFilePath())) {
|
||||
QuasarAppUtils::Params::verboseLog("qml scaner run failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_fileManager.copyFolder(qmlDir, targetDir + "/qml",
|
||||
filter , &listItems, &plugins)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto item : listItems) {
|
||||
extract(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Deploy::extractQml() {
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("qmlDir")) {
|
||||
return extractQmlFromSource(
|
||||
QuasarAppUtils::Params::getStrArg("qmlDir"));
|
||||
|
||||
} else if (QuasarAppUtils::Params::isEndable("allQmlDependes")) {
|
||||
return extractQmlAll();
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Deploy::extract(const QString &file) {
|
||||
QFileInfo info(file);
|
||||
|
||||
auto sufix = info.completeSuffix();
|
||||
|
||||
if (sufix.contains("dll", Qt::CaseSensitive) ||
|
||||
sufix.contains("exe", Qt::CaseSensitive) ||
|
||||
sufix.isEmpty() || sufix.contains("so", Qt::CaseSensitive)) {
|
||||
|
||||
extractLib(file);
|
||||
} else {
|
||||
QuasarAppUtils::Params::verboseLog("file with sufix " + sufix + " not supported!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Deploy::Deploy() {
|
||||
_fileManager.loadDeployemendFiles(targetDir);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
appDir = QuasarAppUtils::Params::getStrArg("appPath");
|
||||
|
||||
if (appDir.right(4) == "/bin") {
|
||||
appDir = appDir.left(appDir.size() - 4);
|
||||
}
|
||||
#else
|
||||
appDir = QuasarAppUtils::Params::getStrArg("appPath");
|
||||
#endif
|
||||
|
||||
QuasarAppUtils::Params::verboseLog("appDir = " + appDir);
|
||||
|
||||
_fileManager = new FileManager();
|
||||
_paramsParser = new CQT(_fileManager);
|
||||
_extracter = new Extracter(_fileManager);
|
||||
}
|
||||
|
||||
bool Deploy::prepare() {
|
||||
return _paramsParser->parseParams();
|
||||
}
|
||||
|
||||
int Deploy::deploy() {
|
||||
_fileManager->loadDeployemendFiles(_paramsParser->config()->targetDir);
|
||||
_extracter->deploy();
|
||||
_fileManager->saveDeploymendFiles(_paramsParser->config()->targetDir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,66 +7,27 @@
|
||||
|
||||
#ifndef DEPLOY_H
|
||||
#define DEPLOY_H
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <dependenciesscanner.h>
|
||||
|
||||
#include "deploy_global.h"
|
||||
#include "filemanager.h"
|
||||
#include "qml.h"
|
||||
|
||||
class DEPLOYSHARED_EXPORT Deploy {
|
||||
private:
|
||||
class CQT;
|
||||
class Extracter;
|
||||
class FileManager;
|
||||
|
||||
QStringList neadedLibs;
|
||||
QStringList systemLibs;
|
||||
class DEPLOYSHARED_EXPORT Deploy
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
DependenciesScanner scaner;
|
||||
FileManager _fileManager;
|
||||
|
||||
int find(const QString& str, const QStringList& list) const;
|
||||
|
||||
void extract(const QString &file);
|
||||
bool copyPlugin(const QString &plugin);
|
||||
void copyPlugins(const QStringList &list);
|
||||
bool copyTranslations(QStringList list);
|
||||
|
||||
bool createQConf();
|
||||
|
||||
bool extractQml();
|
||||
|
||||
|
||||
QStringList extractImportsFromDir(const QString &dirpath);
|
||||
QFileInfoList findFilesInsideDir(const QString &name, const QString &dirpath);
|
||||
bool extractQmlAll();
|
||||
bool extractQmlFromSource(const QString &sourceDir);
|
||||
QString filterQmlPath(const QString &path);
|
||||
void extractLib(const QString & file);
|
||||
|
||||
void addEnv(const QString& dir);
|
||||
QString concatEnv() const;
|
||||
bool smartMoveTargets();
|
||||
bool isLib(const QFileInfo &file);
|
||||
bool setBinDir(const QString& dir, bool recursive = false);
|
||||
|
||||
bool deployMSVC();
|
||||
CQT * _paramsParser;
|
||||
Extracter *_extracter;
|
||||
FileManager *_fileManager;
|
||||
|
||||
|
||||
public:
|
||||
Deploy();
|
||||
bool prepare();
|
||||
int deploy();
|
||||
|
||||
bool getDeployQml() const;
|
||||
void setDeployQml(bool value);
|
||||
|
||||
bool createRunScript(const QString &target);
|
||||
|
||||
void deploy();
|
||||
|
||||
void clear(bool force);
|
||||
|
||||
|
||||
friend class deploytest;
|
||||
};
|
||||
|
||||
#endif // DEPLOY_H
|
||||
|
@ -5,7 +5,7 @@
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#include "deploy.h"
|
||||
#include "extracter.h"
|
||||
#include "deploycore.h"
|
||||
#include "quasarapp.h"
|
||||
|
||||
@ -13,11 +13,14 @@
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QLibraryInfo>
|
||||
#include <cqt.h>
|
||||
|
||||
//QString DeployCore::qtDir = "";
|
||||
//QStringList DeployCore::extraPaths = QStringList();
|
||||
|
||||
|
||||
const DeployConfig* DeployCore::_config = nullptr;
|
||||
|
||||
QtModuleEntry DeployCore::qtModuleEntries[] = {
|
||||
{ QtBluetoothModule, "bluetooth", "Qt5Bluetooth", nullptr },
|
||||
{ QtConcurrentModule, "concurrent", "Qt5Concurrent", "qtbase" },
|
||||
@ -184,7 +187,6 @@ void DeployCore::help() {
|
||||
{ " -targetDir [params] : Sets target directory(by default it is the path to the first deployable file)" },
|
||||
{ " noStrip : Skips strip step" },
|
||||
{ " noTranslations : Skips the translations files." },
|
||||
{ " qmlExtern : Use the qml external scanner (qmlimportscaner)" },
|
||||
{ " | It doesn't work without qmake and inside a snap package" },
|
||||
{ " v / version : Shows compiled version" },
|
||||
{ " verbose [1-3] : Shows debug log" },
|
||||
@ -195,124 +197,6 @@ void DeployCore::help() {
|
||||
{ "Example (only C libs): cqtdeployer -bin myApp clear" }};
|
||||
|
||||
QuasarAppUtils::Params::showHelp(help);
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool DeployCore::parseQtClearMode(Deploy *deploy) {
|
||||
deploy->clear(QuasarAppUtils::Params::isEndable("force-clear"));
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool DeployCore::parseQtInfoMode() {
|
||||
|
||||
if ((QuasarAppUtils::Params::isEndable("v") ||
|
||||
QuasarAppUtils::Params::isEndable("version"))) {
|
||||
DeployCore::printVersion();
|
||||
return true;
|
||||
}
|
||||
|
||||
DeployCore::help();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool DeployCore::parseQtDeployMode(Deploy *deploy) {
|
||||
auto bin = QuasarAppUtils::Params::getStrArg("bin").split(',');
|
||||
|
||||
if (!deploy->setTargets(bin)) {
|
||||
|
||||
auto binDir = QuasarAppUtils::Params::getStrArg("binDir");
|
||||
if (!(deploy->setTargetsRecursive(binDir) || deploy->setTargets({"./"}))) {
|
||||
qCritical() << "setTargetDir fail!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
deploy->initIgnoreEnvList();
|
||||
deploy->initEnvirement();
|
||||
|
||||
deploy->initIgnoreList();
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("clear") ||
|
||||
QuasarAppUtils::Params::isEndable("force-clear")) {
|
||||
qInfo() << "clear old data";
|
||||
deploy->clear(QuasarAppUtils::Params::isEndable("force-clear"));
|
||||
}
|
||||
|
||||
int limit = 0;
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("recursiveDepth")) {
|
||||
bool ok;
|
||||
limit = QuasarAppUtils::Params::getArg("recursiveDepth").toInt(&ok);
|
||||
if (!ok) {
|
||||
limit = 0;
|
||||
qWarning() << "recursiveDepth is invalid! use default value 0";
|
||||
}
|
||||
}
|
||||
|
||||
deploy->setDepchLimit(limit);
|
||||
|
||||
auto listLibDir = QuasarAppUtils::Params::getStrArg("libDir").split(",");
|
||||
auto listExtraPlugin =
|
||||
QuasarAppUtils::Params::getStrArg("extraPlugin").split(",");
|
||||
deploy->setExtraPath(listLibDir);
|
||||
deploy->setExtraPlugins(listExtraPlugin);
|
||||
|
||||
auto qmake = QuasarAppUtils::Params::getStrArg("qmake");
|
||||
QString basePath = "";
|
||||
|
||||
QFileInfo info(qmake);
|
||||
|
||||
if (!info.isFile() || (info.baseName() != "qmake")) {
|
||||
qInfo() << "deploy only C libs because qmake is not found";
|
||||
return true;
|
||||
}
|
||||
|
||||
basePath = info.absolutePath();
|
||||
deploy->setQmake(qmake);
|
||||
|
||||
auto qmlDir = QuasarAppUtils::Params::getStrArg("qmlDir");
|
||||
QDir dir(basePath);
|
||||
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("qmlExtern")) {
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
auto scaner = basePath + QDir::separator() + "qmlimportscanner.exe";
|
||||
#else
|
||||
auto scaner = basePath + QDir::separator() + "qmlimportscanner";
|
||||
#endif
|
||||
if ( !QFileInfo::exists(scaner)) {
|
||||
QuasarAppUtils::Params::verboseLog("qml scaner not defined, using own scaner!",
|
||||
QuasarAppUtils::VerboseLvl::Warning);
|
||||
QuasarAppUtils::Params::setEnable("qmlExtern", false);
|
||||
} else {
|
||||
deploy->setQmlScaner(scaner);
|
||||
}
|
||||
}
|
||||
|
||||
if (QFileInfo::exists(qmlDir) ||
|
||||
QuasarAppUtils::Params::isEndable("allQmlDependes")) {
|
||||
deploy->setDeployQml(true);
|
||||
|
||||
} else {
|
||||
QuasarAppUtils::Params::verboseLog("qml dir not exits!",
|
||||
QuasarAppUtils::VerboseLvl::Warning);
|
||||
}
|
||||
|
||||
if (!dir.cdUp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deploy->setQtDir(dir.absolutePath());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeployCore::parseQt(Deploy *deploy) {
|
||||
}
|
||||
|
||||
QStringList DeployCore::extractTranslation(const QStringList &libs) {
|
||||
@ -347,6 +231,19 @@ void DeployCore::printVersion() {
|
||||
qInfo() << "Qt: " + getQtVersion();
|
||||
}
|
||||
|
||||
int DeployCore::find(const QString &str, const QStringList &list) {
|
||||
for (int i = 0 ; i < list.size(); ++i) {
|
||||
if (list[i].contains(str))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool DeployCore::isLib(const QFileInfo &file) {
|
||||
return file.completeSuffix().contains("so", Qt::CaseInsensitive)
|
||||
|| file.completeSuffix().contains("dll", Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
MSVCVersion DeployCore::getMSVC(const QString &_qmake) {
|
||||
QFileInfo qmake(_qmake);
|
||||
|
||||
@ -456,14 +353,14 @@ QString DeployCore::getMSVCVersion(MSVCVersion msvc) {
|
||||
|
||||
bool DeployCore::isQtLib(const QString &lib) {
|
||||
QFileInfo info(lib);
|
||||
return !qtDir.isEmpty() && info.absoluteFilePath().contains(qtDir);
|
||||
return !_config->qtDir.isEmpty() && info.absoluteFilePath().contains(_config->qtDir);
|
||||
|
||||
}
|
||||
|
||||
bool DeployCore::isExtraLib(const QString &lib) {
|
||||
QFileInfo info(lib);
|
||||
|
||||
for (auto i : extraPaths) {
|
||||
for (auto i : _config->extraPaths) {
|
||||
if (info.absoluteFilePath().contains(i)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include "deploy_global.h"
|
||||
|
||||
enum MSVCVersion: int {
|
||||
@ -51,7 +52,8 @@ enum class RunMode: int {
|
||||
Clear
|
||||
};
|
||||
|
||||
class Deploy;
|
||||
class Extracter;
|
||||
class DeployConfig;
|
||||
|
||||
class DEPLOYSHARED_EXPORT DeployCore
|
||||
{
|
||||
@ -122,6 +124,7 @@ public:
|
||||
|
||||
|
||||
static QtModuleEntry qtModuleEntries[];
|
||||
static const DeployConfig * _config;
|
||||
|
||||
static MSVCVersion getMSVC(const QString & _qmake);
|
||||
static QString getVCredist(const QString & _qmake);
|
||||
@ -135,11 +138,13 @@ public:
|
||||
static void verboseLog(const QString &str);
|
||||
static RunMode getMode();
|
||||
static void help();
|
||||
static bool parseQt(Deploy *deploy);
|
||||
static QStringList extractTranslation(const QStringList& libs);
|
||||
static QString getAppVersion();
|
||||
static QString getQtVersion();
|
||||
static void printVersion();
|
||||
static int find(const QString &str, const QStringList &list);
|
||||
static bool isLib(const QFileInfo &file);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
#include "deployparams.h"
|
||||
|
||||
DeployParams::DeployParams()
|
||||
{
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#ifndef DEPLOYPARAMS_H
|
||||
#define DEPLOYPARAMS_H
|
||||
|
||||
#include "deploy_global.h"
|
||||
|
||||
class DEPLOYSHARED_EXPORT DeployParams
|
||||
{
|
||||
public:
|
||||
DeployParams();
|
||||
};
|
||||
|
||||
#endif // DEPLOYPARAMS_H
|
@ -75,6 +75,24 @@ int Envirement::size() const {
|
||||
return _deployEnvironment.size();
|
||||
}
|
||||
|
||||
QString Envirement::concatEnv() const {
|
||||
|
||||
if (_deployEnvironment.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
QString result = _deployEnvironment.first();
|
||||
for (auto i: _deployEnvironment) {
|
||||
#ifdef Q_OS_UNIX
|
||||
result += (":" + i);
|
||||
#else
|
||||
result += (";" + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Envirement::Envirement()
|
||||
{
|
||||
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
void addEnv(const QString &dir, const QString &appDir, const QString &targetDir);
|
||||
|
||||
int size() const;
|
||||
QString concatEnv() const;
|
||||
};
|
||||
|
||||
#endif // ENVIREMENT_H
|
||||
|
415
Deploy/extracter.cpp
Normal file
415
Deploy/extracter.cpp
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#include "extracter.h"
|
||||
#include "deploycore.h"
|
||||
#include "pluginsparser.h"
|
||||
#include "cqt.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <quasarapp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include <fstream>
|
||||
|
||||
bool Extracter::deployMSVC() {
|
||||
qInfo () << "try deploy msvc";
|
||||
auto msvcInstaller = DeployCore::getVCredist(DeployCore::_config->qmake);
|
||||
|
||||
if (msvcInstaller.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _fileManager->copyFile(msvcInstaller, DeployCore::_config->targetDir);
|
||||
}
|
||||
|
||||
bool Extracter::copyPlugin(const QString &plugin) {
|
||||
|
||||
QStringList listItems;
|
||||
|
||||
if (!_fileManager->copyFolder(plugin, DeployCore::_config->targetDir + "/plugins/" + QFileInfo(plugin).fileName(),
|
||||
QStringList() << ".so.debug" << "d.dll", &listItems)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto item : listItems) {
|
||||
extract(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Extracter::copyPlugins(const QStringList &list) {
|
||||
for (auto plugin : list) {
|
||||
if (!copyPlugin(plugin)) {
|
||||
qWarning() << plugin << " not copied!";
|
||||
}
|
||||
}
|
||||
QFileInfo info;
|
||||
|
||||
for (auto extraPlugin : DeployCore::_config->extraPlugins) {
|
||||
|
||||
info.setFile(extraPlugin);
|
||||
if (info.isDir()) {
|
||||
|
||||
_fileManager->copyFolder(info.absoluteFilePath(),
|
||||
DeployCore::_config->targetDir + "/plugins/" + info.baseName(),
|
||||
QStringList() << ".so.debug" << "d.dll");
|
||||
} else {
|
||||
_fileManager->copyFile(info.absoluteFilePath(),
|
||||
DeployCore::_config->targetDir + QDir::separator() + "plugins");
|
||||
extract(info.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Extracter::createRunScript(const QString &target) {
|
||||
|
||||
QString content =
|
||||
"#!/bin/sh\n"
|
||||
"BASE_DIR=$(dirname \"$(readlink -f \"$0\")\")\n"
|
||||
"export "
|
||||
"LD_LIBRARY_PATH=\"$BASE_DIR\"/lib:\"$BASE_DIR\":$LD_LIBRARY_PATH\n"
|
||||
"export QML_IMPORT_PATH=\"$BASE_DIR\"/qml:QML_IMPORT_PATH\n"
|
||||
"export QML2_IMPORT_PATH=\"$BASE_DIR\"/qml:QML2_IMPORT_PATH\n"
|
||||
"export QT_PLUGIN_PATH=\"$BASE_DIR\"/plugins:QT_PLUGIN_PATH\n"
|
||||
"export QTDIR=\"$BASE_DIR\"\n"
|
||||
"export "
|
||||
"QT_QPA_PLATFORM_PLUGIN_PATH=\"$BASE_DIR\"/plugins/"
|
||||
"platforms:QT_QPA_PLATFORM_PLUGIN_PATH\n"
|
||||
"%2"
|
||||
"\"$BASE_DIR\"/bin/%1 \"$@\"";
|
||||
|
||||
content = content.arg(QFileInfo(target).fileName());
|
||||
int ld_index = DeployCore::find("ld-linux", _fileManager->getDeployedFilesStringList());
|
||||
|
||||
if (ld_index >= 0 && QuasarAppUtils::Params::isEndable("deploySystem") &&
|
||||
!QuasarAppUtils::Params::isEndable("noLibc")) {
|
||||
|
||||
content = content.arg(QString("\nexport LD_PRELOAD=\"$BASE_DIR\"/lib/%0\n").
|
||||
arg(QFileInfo(_fileManager->getDeployedFilesStringList()[ld_index]).fileName()));
|
||||
} else {
|
||||
content = content.arg("");
|
||||
}
|
||||
|
||||
|
||||
QString fname = DeployCore::_config->targetDir + QDir::separator() + QFileInfo(target).baseName()+ ".sh";
|
||||
|
||||
QFile F(fname);
|
||||
if (!F.open(QIODevice::WriteOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
F.write(content.toUtf8());
|
||||
F.flush();
|
||||
F.close();
|
||||
|
||||
_fileManager->addToDeployed(fname);
|
||||
|
||||
return F.setPermissions(QFileDevice::ExeOther | QFileDevice::WriteOther |
|
||||
QFileDevice::ReadOther | QFileDevice::ExeUser |
|
||||
QFileDevice::WriteUser | QFileDevice::ReadUser |
|
||||
QFileDevice::ExeOwner | QFileDevice::WriteOwner |
|
||||
QFileDevice::ReadOwner);
|
||||
}
|
||||
|
||||
bool Extracter::createQConf() {
|
||||
|
||||
QString content =
|
||||
"[Paths]\n"
|
||||
"Prefix= ./\n"
|
||||
"Libraries= ./\n"
|
||||
"Plugins= ./plugins\n"
|
||||
"Imports= ./qml\n"
|
||||
"Qml2Imports= ./qml\n";
|
||||
|
||||
|
||||
QString fname = DeployCore::_config->targetDir + QDir::separator() + "qt.conf";
|
||||
|
||||
QFile F(fname);
|
||||
if (!F.open(QIODevice::WriteOnly)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
F.write(content.toUtf8());
|
||||
F.flush();
|
||||
F.close();
|
||||
|
||||
_fileManager->addToDeployed(fname);
|
||||
|
||||
return F.setPermissions(QFileDevice::ExeOther | QFileDevice::WriteOther |
|
||||
QFileDevice::ReadOther | QFileDevice::ExeUser |
|
||||
QFileDevice::WriteUser | QFileDevice::ReadUser |
|
||||
QFileDevice::ExeOwner | QFileDevice::WriteOwner |
|
||||
QFileDevice::ReadOwner);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Extracter::deploy() {
|
||||
qInfo() << "target deploy started!!";
|
||||
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("clear") ||
|
||||
QuasarAppUtils::Params::isEndable("force-clear")) {
|
||||
qInfo() << "clear old data";
|
||||
|
||||
_fileManager->clear(DeployCore::_config->targetDir,
|
||||
QuasarAppUtils::Params::isEndable("force-clear"));
|
||||
}
|
||||
|
||||
scaner.setEnvironment(DeployCore::_config->envirement.deployEnvironment());
|
||||
|
||||
for (auto i = DeployCore::_config->targets.cbegin(); i != DeployCore::_config->targets.cend(); ++i) {
|
||||
extract(i.key());
|
||||
}
|
||||
|
||||
if (DeployCore::_config->deployQml && !extractQml()) {
|
||||
qCritical() << "qml not extacted!";
|
||||
}
|
||||
|
||||
PluginsParser pluginsParser(&scaner);
|
||||
|
||||
QStringList plugins;
|
||||
pluginsParser.scan(DeployCore::_config->qtDir + "/plugins", plugins);
|
||||
copyPlugins(plugins);
|
||||
|
||||
|
||||
_fileManager->copyFiles(neadedLibs, DeployCore::_config->targetDir);
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("deploySystem")) {
|
||||
_fileManager->copyFiles(systemLibs, DeployCore::_config->targetDir);
|
||||
}
|
||||
|
||||
if (!QuasarAppUtils::Params::isEndable("noStrip") && !_fileManager->strip(DeployCore::_config->targetDir)) {
|
||||
QuasarAppUtils::Params::verboseLog("strip failed!");
|
||||
}
|
||||
|
||||
if (!QuasarAppUtils::Params::isEndable("noTranslations")) {
|
||||
if (!copyTranslations(DeployCore::extractTranslation(neadedLibs))) {
|
||||
qWarning() << " copy TR ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
if (!deployMSVC()) {
|
||||
QuasarAppUtils::Params::verboseLog("deploy msvc failed");
|
||||
}
|
||||
|
||||
bool targetWindows = false;
|
||||
|
||||
for (auto i = DeployCore::_config->targets.cbegin(); i != DeployCore::_config->targets.cend(); ++i) {
|
||||
|
||||
if (QFileInfo(i.key()).completeSuffix() == "exe") {
|
||||
targetWindows = true;
|
||||
}
|
||||
|
||||
if (i.value() && !createRunScript(i.key())) {
|
||||
qCritical() << "run script not created!";
|
||||
}
|
||||
}
|
||||
|
||||
if (targetWindows && !createQConf()) {
|
||||
QuasarAppUtils::Params::verboseLog("create qt.conf failr", QuasarAppUtils::Warning);
|
||||
}
|
||||
|
||||
_fileManager->saveDeploymendFiles(DeployCore::_config->targetDir);
|
||||
|
||||
qInfo() << "deploy done!";
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool Extracter::copyTranslations(QStringList list) {
|
||||
|
||||
QDir dir(DeployCore::_config->translationDir);
|
||||
if (!dir.exists() || list.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
for (auto &&i: list) {
|
||||
filters.push_back("*" + i + "*");
|
||||
}
|
||||
|
||||
auto listItems = dir.entryInfoList(filters, QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto &&i: listItems) {
|
||||
_fileManager->copyFile(i.absoluteFilePath(), DeployCore::_config->targetDir + "/translations");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QFileInfoList Extracter::findFilesInsideDir(const QString &name,
|
||||
const QString &dirpath) {
|
||||
QFileInfoList files;
|
||||
|
||||
QDir dir(dirpath);
|
||||
|
||||
auto list = dir.entryInfoList( QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
|
||||
for (auto && item :list) {
|
||||
if (item.isFile()) {
|
||||
if (item.fileName().contains(name)) {
|
||||
files += item;
|
||||
}
|
||||
} else {
|
||||
files += findFilesInsideDir(name, item.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
QString Extracter::filterQmlPath(const QString &path) {
|
||||
if (path.contains(DeployCore::_config->qmlDir)) {
|
||||
auto endIndex = path.indexOf(QDir::separator(), DeployCore::_config->qmlDir.size() + 1);
|
||||
QString module =
|
||||
path.mid(DeployCore::_config->qmlDir.size() + 1, endIndex - DeployCore::_config->qmlDir.size() - 1);
|
||||
return DeployCore::_config->qmlDir + QDir::separator() + module;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void Extracter::extractLib(const QString &file) {
|
||||
qInfo() << "extract lib :" << file;
|
||||
|
||||
auto data = scaner.scan(file);
|
||||
|
||||
for (auto &line : data) {
|
||||
bool isIgnore = false;
|
||||
for (auto ignore : DeployCore::_config->ignoreList) {
|
||||
if (line.fullPath().contains(ignore)) {
|
||||
QuasarAppUtils::Params::verboseLog(line.fullPath() + " ignored by filter" + ignore);
|
||||
isIgnore = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIgnore) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.getPriority() != LibPriority::SystemLib && !neadedLibs.contains(line.fullPath())) {
|
||||
neadedLibs << line.fullPath();
|
||||
} else if (QuasarAppUtils::Params::isEndable("deploySystem") &&
|
||||
line.getPriority() == LibPriority::SystemLib &&
|
||||
!systemLibs.contains(line.fullPath())) {
|
||||
systemLibs << line.fullPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Extracter::extractQmlAll() {
|
||||
|
||||
if (!QFileInfo::exists(DeployCore::_config->qmlDir)) {
|
||||
qWarning() << "qml dir wrong!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList listItems;
|
||||
|
||||
if (!_fileManager->copyFolder(DeployCore::_config->qmlDir, DeployCore::_config->targetDir + "/qml",
|
||||
QStringList() << ".so.debug" << "d.dll",
|
||||
&listItems)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto item : listItems) {
|
||||
extract(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Extracter::extractQmlFromSource(const QString& sourceDir) {
|
||||
|
||||
QFileInfo info(sourceDir);
|
||||
|
||||
if (!info.isDir()) {
|
||||
qCritical() << "extract qml fail! qml source dir not exits or is not dir " << sourceDir;
|
||||
return false;
|
||||
}
|
||||
|
||||
QuasarAppUtils::Params::verboseLog("extractQmlFromSource " + info.absoluteFilePath());
|
||||
|
||||
if (!QFileInfo::exists(DeployCore::_config->qmlDir)) {
|
||||
qWarning() << "qml dir wrong!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList plugins;
|
||||
QStringList listItems;
|
||||
QStringList filter;
|
||||
filter << ".so.debug" << "d.dll" << ".pdb";
|
||||
|
||||
QML ownQmlScaner(DeployCore::_config->qmlDir);
|
||||
|
||||
if (!ownQmlScaner.scan(plugins, info.absoluteFilePath())) {
|
||||
QuasarAppUtils::Params::verboseLog("qml scaner run failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_fileManager->copyFolder(DeployCore::_config->qmlDir, DeployCore::_config->targetDir + "/qml",
|
||||
filter , &listItems, &plugins)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto item : listItems) {
|
||||
extract(item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Extracter::extractQml() {
|
||||
|
||||
if (QuasarAppUtils::Params::isEndable("qmlDir")) {
|
||||
return extractQmlFromSource(
|
||||
QuasarAppUtils::Params::getStrArg("qmlDir"));
|
||||
|
||||
} else if (QuasarAppUtils::Params::isEndable("allQmlDependes")) {
|
||||
return extractQmlAll();
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Extracter::extract(const QString &file) {
|
||||
QFileInfo info(file);
|
||||
|
||||
auto sufix = info.completeSuffix();
|
||||
|
||||
if (sufix.contains("dll", Qt::CaseSensitive) ||
|
||||
sufix.contains("exe", Qt::CaseSensitive) ||
|
||||
sufix.isEmpty() || sufix.contains("so", Qt::CaseSensitive)) {
|
||||
|
||||
extractLib(file);
|
||||
} else {
|
||||
QuasarAppUtils::Params::verboseLog("file with sufix " + sufix + " not supported!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Extracter::Extracter(FileManager *fileManager):
|
||||
_fileManager(fileManager) {
|
||||
|
||||
assert(_fileManager);
|
||||
assert(DeployCore::_config);
|
||||
}
|
||||
|
55
Deploy/extracter.h
Normal file
55
Deploy/extracter.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#ifndef EXTRACTER_H
|
||||
#define EXTRACTER_H
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <dependenciesscanner.h>
|
||||
#include "deploy_global.h"
|
||||
#include "filemanager.h"
|
||||
#include "qml.h"
|
||||
|
||||
|
||||
class DEPLOYSHARED_EXPORT Extracter {
|
||||
private:
|
||||
|
||||
QStringList neadedLibs;
|
||||
QStringList systemLibs;
|
||||
|
||||
DependenciesScanner scaner;
|
||||
FileManager *_fileManager;
|
||||
|
||||
void extract(const QString &file);
|
||||
bool copyTranslations(QStringList list);
|
||||
|
||||
bool createQConf();
|
||||
bool extractQml();
|
||||
|
||||
QFileInfoList findFilesInsideDir(const QString &name, const QString &dirpath);
|
||||
bool extractQmlAll();
|
||||
bool extractQmlFromSource(const QString &sourceDir);
|
||||
QString filterQmlPath(const QString &path);
|
||||
void extractLib(const QString & file);
|
||||
|
||||
bool deployMSVC();
|
||||
|
||||
|
||||
bool copyPlugin(const QString &plugin);
|
||||
void copyPlugins(const QStringList &list);
|
||||
|
||||
|
||||
public:
|
||||
explicit Extracter(FileManager *fileManager);
|
||||
bool createRunScript(const QString &target);
|
||||
void deploy();
|
||||
|
||||
friend class deploytest;
|
||||
};
|
||||
|
||||
#endif // EXTRACTER_H_H
|
@ -6,7 +6,6 @@
|
||||
#include <deploy_global.h>
|
||||
|
||||
|
||||
class DeployedFiles;
|
||||
|
||||
class DEPLOYSHARED_EXPORT FileManager
|
||||
{
|
||||
|
@ -20,6 +20,8 @@ private:
|
||||
public:
|
||||
PluginsParser(DependenciesScanner *scaner);
|
||||
bool scan(const QString &pluginPath, QStringList& resDependencies);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // QTMODULES_H
|
||||
|
@ -43,7 +43,6 @@ Key differences of this program:
|
||||
| -targetDir [params] | Sets target directory(by default it is the path to the first deployable file)|
|
||||
| noStrip | Skips strip step |
|
||||
| noTranslations | Skips the translations files. |
|
||||
| qmlExtern | Use qml external scanner (qmlimportscaner) |
|
||||
| | It doesn't work without qmake and inside a snap package |
|
||||
| -verbose [0-3] | Shows debug log |
|
||||
| v / version | Shows compiled version |
|
||||
@ -114,7 +113,6 @@ Console QtDeployer является консольной реализацией
|
||||
| -targetDir [params] | Устанавливает целевой каталог (по умолчанию это путь к первому развертываемому файлу)|
|
||||
| noStrip | Пропускает шаг strip |
|
||||
| noTranslations | Пропускает файлы переводов |
|
||||
| qmlExtern | Использует внешний сканер qml (qmlimportscaner) |
|
||||
| | не работает без qmake и в snap |
|
||||
| -verbose [0-3] | Показывает дебаг лога |
|
||||
| v / version | Показывает версию приложения |
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <QtTest>
|
||||
#include <quasarapp.h>
|
||||
#include <deploycore.h>
|
||||
#include <deploy.h>
|
||||
#include <extracter.h>
|
||||
#include <dependenciesscanner.h>
|
||||
#include <qml.h>
|
||||
|
||||
@ -334,38 +334,38 @@ void deploytest::testDeployCore() {
|
||||
|
||||
void deploytest::testDeployTarget() {
|
||||
|
||||
Deploy *deploy = new Deploy();
|
||||
Extracter *deploy = new Extracter();
|
||||
QStringList targets;
|
||||
targets << "./test/bins/execTarget.exe";
|
||||
QVERIFY(deploy->setTargets(targets));
|
||||
delete deploy;
|
||||
targets.clear();
|
||||
|
||||
deploy = new Deploy();
|
||||
deploy = new Extracter();
|
||||
targets << "./test/bins/execTarget";
|
||||
QVERIFY(deploy->setTargets(targets));
|
||||
delete deploy;
|
||||
targets.clear();
|
||||
|
||||
deploy = new Deploy();
|
||||
deploy = new Extracter();
|
||||
targets << "./test/bins/execTarget.exe" << "./test/bins/execTarget";
|
||||
QVERIFY(deploy->setTargets(targets));
|
||||
delete deploy;
|
||||
targets.clear();
|
||||
|
||||
deploy = new Deploy();
|
||||
deploy = new Extracter();
|
||||
targets << "./test/bns/execTarget.exe";
|
||||
QVERIFY(!deploy->setTargets(targets));
|
||||
delete deploy;
|
||||
targets.clear();
|
||||
|
||||
deploy = new Deploy();
|
||||
deploy = new Extracter();
|
||||
targets << "./test/bins/";
|
||||
QVERIFY(deploy->setTargets(targets));
|
||||
delete deploy;
|
||||
targets.clear();
|
||||
|
||||
deploy = new Deploy();
|
||||
deploy = new Extracter();
|
||||
targets << "./test/bins/" << "./test/warning/";
|
||||
QVERIFY(deploy->setTargets(targets));
|
||||
|
||||
@ -444,7 +444,7 @@ void deploytest::testStrip() {
|
||||
void deploytest::testDeploy() {
|
||||
QuasarAppUtils::Params::parseParams(0, nullptr);
|
||||
|
||||
Deploy *deploy = new Deploy();
|
||||
Extracter *deploy = new Extracter();
|
||||
QVERIFY(!deploy->appDir.isEmpty());
|
||||
delete deploy;
|
||||
}
|
||||
@ -476,7 +476,7 @@ void deploytest::testExtractLib() {
|
||||
}
|
||||
|
||||
void deploytest::testDeployLdLinux() {
|
||||
auto deploy = new Deploy();
|
||||
auto deploy = new Extracter();
|
||||
int argc = 3;
|
||||
deploy->targetDir = "./test/bins/sh";
|
||||
QVERIFY(QDir("./").mkpath("./test/bins/sh/"));
|
||||
@ -615,7 +615,7 @@ void deploytest::testQmlExtrct() {
|
||||
|
||||
void deploytest::testSetTargetDir() {
|
||||
|
||||
Deploy dep;
|
||||
Extracter dep;
|
||||
|
||||
dep.setTargetDir();
|
||||
|
||||
@ -884,7 +884,7 @@ void deploytest::testTranslations() {
|
||||
DeployCore::qtDir = QFileInfo("./test/QtDir/").absoluteFilePath();
|
||||
|
||||
|
||||
Deploy *deploy = new Deploy();
|
||||
Extracter *deploy = new Extracter();
|
||||
|
||||
for (auto &&i: trList) {
|
||||
generateLib(i);
|
||||
|
Loading…
x
Reference in New Issue
Block a user