From 18888ab37091dffb0e8327d64a43b6d98ebb433a Mon Sep 17 00:00:00 2001
From: EndrII <EndrIIMail@gmail.com>
Date: Wed, 9 Jun 2021 14:22:03 +0300
Subject: [PATCH] ref #519 implement of new system for creating run scripts.

---
 Deploy/DeployResources.qrc                    |   4 +
 .../Templates/deb/DEBIAN/postinst             |  15 +-
 .../Distributions/Templates/deb/DEBIAN/prerm  |   9 +-
 .../packages/default/meta/installscript.qs    |  22 ++-
 Deploy/Distributions/idistribution.cpp        |  21 ++-
 Deploy/ScriptsTemplates/linux.sh              |  34 ++++
 Deploy/ScriptsTemplates/windows.bat           |  22 +++
 Deploy/configparser.cpp                       | 106 ++++++------
 Deploy/configparser.h                         |   3 +-
 Deploy/deployconfig.cpp                       |   9 --
 Deploy/deployconfig.h                         |   9 --
 Deploy/deploycore.cpp                         |   5 +-
 Deploy/metafilemanager.cpp                    | 152 ++++++++----------
 Deploy/metafilemanager.h                      |   7 +
 Deploy/targetinfo.cpp                         |  82 +++++++++-
 Deploy/targetinfo.h                           |  90 ++++++++++-
 UnitTests/tst_deploytest.cpp                  |  12 ++
 md/en/Options.md                              |   3 +-
 md/ru/Options.md                              |   2 +
 19 files changed, 432 insertions(+), 175 deletions(-)
 create mode 100644 Deploy/ScriptsTemplates/linux.sh
 create mode 100644 Deploy/ScriptsTemplates/windows.bat

diff --git a/Deploy/DeployResources.qrc b/Deploy/DeployResources.qrc
index 602f56a..c0e29d8 100644
--- a/Deploy/DeployResources.qrc
+++ b/Deploy/DeployResources.qrc
@@ -26,4 +26,8 @@
         <file>Distributions/Templates/Icon.png</file>
         <file>Distributions/Templates/Icon.ico</file>
     </qresource>
+    <qresource prefix="/Scripts">
+        <file>ScriptsTemplates/windows.bat</file>
+        <file>ScriptsTemplates/linux.sh</file>
+    </qresource>
 </RCC>
diff --git a/Deploy/Distributions/Templates/deb/DEBIAN/postinst b/Deploy/Distributions/Templates/deb/DEBIAN/postinst
index caeaebe..55918ee 100755
--- a/Deploy/Distributions/Templates/deb/DEBIAN/postinst
+++ b/Deploy/Distributions/Templates/deb/DEBIAN/postinst
@@ -1,6 +1,7 @@
 #!/bin/bash
 
 APPS=$BASH_ARRAY_APPLICATIONS
+APPS_SHORTCUTS=$BASH_ARRAY_SHORTCUTS_APPLICATIONS
 
 TARGET_DIR=/opt/$PREFIX/
 
@@ -35,14 +36,20 @@ do
     
     DEST_NAME=$app
 
-    SRC_FILE="$TARGET_DIR/$app.sh"
-    DEST_FILE="/usr/share/applications/$app.desktop"
-    createShortCut
-
     if [ ! -e /usr/bin/"${app,,}" ]; then
         ln -s "$TARGET_DIR/$app.sh" /usr/bin/"${app,,}"
         echo "${app,,}"
     fi
 done
 
+for app in "${APPS_SHORTCUTS[@]}"
+do
+
+    DEST_NAME=$app
+
+    SRC_FILE="$TARGET_DIR/$app"
+    DEST_FILE="/usr/share/applications/${app%.*}.desktop"
+    createShortCut
+done
+
 
diff --git a/Deploy/Distributions/Templates/deb/DEBIAN/prerm b/Deploy/Distributions/Templates/deb/DEBIAN/prerm
index 0e0a2e6..64b778a 100755
--- a/Deploy/Distributions/Templates/deb/DEBIAN/prerm
+++ b/Deploy/Distributions/Templates/deb/DEBIAN/prerm
@@ -1,15 +1,18 @@
 #!/bin/bash
 
 APPS=$BASH_ARRAY_APPLICATIONS
+APPS_SHORTCUTS=$BASH_ARRAY_SHORTCUTS_APPLICATIONS
 
 for app in "${APPS[@]}"
 do
 
-    SRC_FILE="$TARGET_DIR/$app.sh"
-    rm "/usr/share/applications/$app.desktop"
-
     if [ -e /usr/bin/"${app,,}" ]; then
         rm /usr/bin/"${app,,}"
         echo "Remove ${app,,}"
     fi
 done
+
+for app in "${APPS_SHORTCUTS[@]}"
+do
+    rm "/usr/share/applications/${app%.*}.desktop"
+done
diff --git a/Deploy/Distributions/Templates/qif/packages/default/meta/installscript.qs b/Deploy/Distributions/Templates/qif/packages/default/meta/installscript.qs
index 554f184..4a74850 100644
--- a/Deploy/Distributions/Templates/qif/packages/default/meta/installscript.qs
+++ b/Deploy/Distributions/Templates/qif/packages/default/meta/installscript.qs
@@ -2,6 +2,13 @@ function Component() {
 
 }
 
+function getBasename(file) {
+    if (!file.length)
+        return ""
+
+    return file.split('.')[0];
+}
+
 function generateShortCutCmd(cmd) {
 
     var prefix = "$PREFIX";
@@ -12,8 +19,8 @@ function generateShortCutCmd(cmd) {
 
         component.addOperation(
             "CreateShortcut",
-            "@TargetDir@/" + prefix + "/" + cmd + ".bat",
-            "@DesktopDir@/" + cmd + ".lnk",
+            "@TargetDir@/" + prefix + "/" + cmd,
+            "@DesktopDir@/" + getBasename(cmd) + ".lnk",
             "iconPath=@TargetDir@/$ICON",
             "iconId=0");
 
@@ -23,14 +30,14 @@ function generateShortCutCmd(cmd) {
     if (systemInfo.kernelType === "linux") {
         console.log("create icons!!! on LINUX");
         component.addOperation("CreateDesktopEntry",
-                               "@HomeDir@/.local/share/applications/" + cmd + ".desktop",
+                               "@HomeDir@/.local/share/applications/" + getBasename(cmd) + ".desktop",
                                "Version=@Version@\n
                                 Type=Application\n
                                 Terminal=false\n
-                                Exec=\"@TargetDir@/" + prefix + "/" + cmd + ".sh\"\n
-                                Name=" + cmd + "\n
+                                Exec=\"@TargetDir@/" + prefix + "/" + cmd + "\"\n
+                                Name=" + getBasename(cmd) + "\n
                                 Icon=@TargetDir@/$ICON\n
-                                Name[en_US]=" + cmd);
+                                Name[en_US]=" + getBasename(cmd));
 
         console.log("create icons!!! on LINUX done");
     }
@@ -41,8 +48,9 @@ Component.prototype.createOperations = function() {
     component.createOperations();
 
     var cmdArray = ["array", "of", "cmds"]; // will be changed in cqtdeployer
+    var shortcutsCmdArray = ["array", "of", "shortcut", "cmds"]; // will be changed in cqtdeployer
 
-    cmdArray.forEach( function (item){
+    shortcutsCmdArray.forEach( function (item){
         generateShortCutCmd(item);
     });
 
diff --git a/Deploy/Distributions/idistribution.cpp b/Deploy/Distributions/idistribution.cpp
index 937b389..2d8aaf6 100644
--- a/Deploy/Distributions/idistribution.cpp
+++ b/Deploy/Distributions/idistribution.cpp
@@ -196,10 +196,25 @@ bool iDistribution::collectInfo(const DistroModule& pkg,
 
     QString cmdArray = "[";
     QString bashArray = "(";
+    QString cmdShortCutsArray = "[";
+    QString bashShortCutsArray = "(";
 
     int initSize = cmdArray.size();
     for (const auto &target :pkg.targets()) {
-        auto fileinfo =  QFileInfo(target);
+        const DeployConfig *cfg = DeployCore::_config;
+        auto fileinfo = QFileInfo(target);
+        auto targetInfo =  cfg->targets().value(target);
+
+        if (targetInfo.getShortCut()) {
+            if (cmdArray.size() > initSize) {
+                cmdShortCutsArray += ",";
+                bashShortCutsArray += " ";
+            }
+
+            cmdShortCutsArray += "\"" + targetInfo.getRunScriptFile() + "\"";
+            bashShortCutsArray += "\"" + targetInfo.getRunScriptFile() + "\"";
+        }
+
         if (fileinfo.suffix().compare("exe", ONLY_WIN_CASE_INSENSIATIVE) == 0 || fileinfo.suffix().isEmpty()) {
             if (cmdArray.size() > initSize) {
                 cmdArray += ",";
@@ -211,9 +226,13 @@ bool iDistribution::collectInfo(const DistroModule& pkg,
     }
     cmdArray += "]";
     bashArray += ")";
+    cmdShortCutsArray += "]";
+    bashShortCutsArray += ")";
 
     info.Custom = {{"[\"array\", \"of\", \"cmds\"]", cmdArray}};
+    info.Custom["[\"array\", \"of\", \"shortcut\", \"cmds\"]"] = cmdShortCutsArray;
 
+    info.Custom["$BASH_ARRAY_APPLICATIONS"] = bashArray;
     info.Custom["$BASH_ARRAY_APPLICATIONS"] = bashArray;
 
     if (info.Name.isEmpty()) {
diff --git a/Deploy/ScriptsTemplates/linux.sh b/Deploy/ScriptsTemplates/linux.sh
new file mode 100644
index 0000000..c9e1aae
--- /dev/null
+++ b/Deploy/ScriptsTemplates/linux.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# This is default bat run script of The CQtDeployer project.
+# This file contains key word that will replaced after deploy project.
+#
+# ####################################################################
+#
+# CQT_LIB_PATH - are releative path to libraryes of a deployed distribution.
+# CQT_QML_PATH - are releative path to qml libraryes of a deployed distribution.
+# CQT_PLUGIN_PATH - are releative path to qt plugins of a deployed distribution.
+# CQT_BIN_PATH - are releative path to targets of a deployed distribution.
+
+# CQT_SYSTEM_LIB_PATH - are releative path to system libraryes of a deployed distribution.
+# CQT_BASE_NAME - are base name of the executable that will be launched after run this script.
+# CQT_CUSTOM_SCRIPT_BLOCK - This is code from the customScript option
+# CQT_RUN_COMMAND - This is command for run application. Requred BASE_DIR variable.
+#
+# ####################################################################
+
+BASE_DIR=$(dirname \"$(readlink -f \"$0\")\")
+export LD_LIBRARY_PATH=\"$BASE_DIR\"CQT_LIB_PATH:\"$BASE_DIR\":$LD_LIBRARY_PATH
+export QML_IMPORT_PATH=\"$BASE_DIR\"CQT_QML_PATH:$QML_IMPORT_PATH
+export QML2_IMPORT_PATH=\"$BASE_DIR\"CQT_QML_PATH:$QML2_IMPORT_PATH
+export QT_PLUGIN_PATH=\"$BASE_DIR\"CQT_PLUGIN_PATH:$QT_PLUGIN_PATH
+export QTWEBENGINEPROCESS_PATH=\"$BASE_DIR\"CQT_BIN_PATH/QtWebEngineProcess
+export QTDIR=\"$BASE_DIR\"
+export CQT_PKG_ROOT=\"$BASE_DIR\"
+export CQT_RUN_FILE=\"$BASE_DIR/CQT_BASE_NAME.sh\"
+
+export QT_QPA_PLATFORM_PLUGIN_PATH=\"$BASE_DIR\"CQT_PLUGIN_PATH/platforms:$QT_QPA_PLATFORM_PLUGIN_PATH
+
+CQT_CUSTOM_SCRIPT_BLOCK
+
+CQT_RUN_COMMAND
diff --git a/Deploy/ScriptsTemplates/windows.bat b/Deploy/ScriptsTemplates/windows.bat
new file mode 100644
index 0000000..af3f2f6
--- /dev/null
+++ b/Deploy/ScriptsTemplates/windows.bat
@@ -0,0 +1,22 @@
+:: This is default bat run script of The CQtDeployer project.
+:: This file contains key word that will replaced after deploy project.
+
+:: ####################################################################
+
+:: LIB_PATH - are releative path to libraryes of a deployed distribution.
+:: SYSTEM_LIB_PATH - are releative path to system libraryes of a deployed distribution.
+:: BASE_NAME - are base name of the executable that will be launched after run this script.
+:: CUSTOM_SCRIPT_BLOCK - This is code from the customScript option
+:: RUN_COMMAND - This is command for run application. Requred BASE_DIR variable.
+
+:: ####################################################################
+
+@echo off
+SET BASE_DIR=%~dp0
+SET PATH=%BASE_DIR%LIB_PATH;%PATH%;SYSTEM_LIB_PATH
+SET CQT_PKG_ROOT=%BASE_DIR%
+SET CQT_RUN_FILE=%BASE_DIR%BASE_NAME.bat
+
+CUSTOM_SCRIPT_BLOCK
+
+RUN_COMMAND
diff --git a/Deploy/configparser.cpp b/Deploy/configparser.cpp
index f7f4085..135bb89 100644
--- a/Deploy/configparser.cpp
+++ b/Deploy/configparser.cpp
@@ -75,7 +75,7 @@ void parseTargetPrivate(DeployConfig& conf,
         auto pair = iconPair.split(DeployCore::getSeparator(1), splitbehavior);
 
         if (pair.size() == 1) {
-            QuasarAppUtils::Params::log(QString("Set new default icon for all tagets: " + pair.value(0)),
+            QuasarAppUtils::Params::log(QString("Set new default property for all tagets: " + pair.value(0)),
                                         QuasarAppUtils::Debug);
             for (auto& editableTarget: cointainer) {
                 (editableTarget.*adder)(pair.value(0));
@@ -96,7 +96,7 @@ void parseTargetPrivate(DeployConfig& conf,
         }
 
         for (const auto &target: targetsMap) {
-            QuasarAppUtils::Params::log(QString("Set new icon for %0 taget. Icon: %1").
+            QuasarAppUtils::Params::log(QString("Set new property for %0 taget.").
                                         arg(pair.value(0), pair.value(1)),
                                         QuasarAppUtils::Debug);
             (target->*adder)(pair.value(1));
@@ -104,6 +104,34 @@ void parseTargetPrivate(DeployConfig& conf,
     }
 }
 
+template <typename Enabler>
+bool enableOptionFotTargetPrivate(DeployConfig& conf,
+                        const QStringList &inputParams,
+                        Enabler enabler) {
+
+    for (const auto &iconPair: inputParams) {
+        auto pair = iconPair.split(DeployCore::getSeparator(1), splitbehavior);
+
+        if (pair.size() != 1) {
+            QuasarAppUtils::Params::log(QString("Failed parese list of option values, This option support only single leve list. "
+                                                " Example: use -Option val1,val2,val3 "),
+                                        QuasarAppUtils::Error);
+            return false;
+        }
+
+        const auto targetsMap = conf.getTargetsListByFilter(pair.value(0));
+
+        for (const auto &target: targetsMap) {
+            QuasarAppUtils::Params::log(QString("Set new property for %0 taget.").
+                                        arg(pair.value(0)),
+                                        QuasarAppUtils::Debug);
+            (target->*enabler)();
+        }
+    }
+
+    return true;
+}
+
 bool ConfigParser::parseParams() {
 
     auto path = QuasarAppUtils::Params::getArg("confFile");
@@ -578,35 +606,6 @@ bool ConfigParser::initPackages() {
     return true;
 }
 
-bool ConfigParser::initRunScripts() {
-    const auto list = QuasarAppUtils::Params::getArg("runScript").split(DeployCore::getSeparator(0), splitbehavior);
-
-    for (const auto& line: list) {
-        auto pair = line.split(DeployCore::getSeparator(1), splitbehavior);
-        if (pair.size() != 2) {
-            QuasarAppUtils::Params::log("Syntax error of the runScript option."
-                                        " Example of use :"
-                                        " -runScript \"myTarget;path/To/Target/RunScript.sh,"
-                                        "mySecondTarget;path/To/Target/SecondRunScript.sh\"",
-                                        QuasarAppUtils::Error);
-            return false;
-        }
-
-        QFileInfo script(pair.value(1));
-
-        if (!script.isFile()) {
-            QuasarAppUtils::Params::log(QString("The %0 file does not exist.").arg(script.absoluteFilePath()),
-                                        QuasarAppUtils::Error);
-            return false;
-        }
-
-        _config.registerRunScript(pair.value(0),
-                                  script.absoluteFilePath());
-    }
-
-    return true;
-}
-
 bool ConfigParser::initQmlInput() {
 
     auto qmlDir = QuasarAppUtils::Params::getArg("qmlDir").
@@ -683,11 +682,6 @@ bool ConfigParser::parseDeployMode() {
         }
     }
 
-
-    if (!initRunScripts()) {
-        return false;
-    }
-
     initIgnoreEnvList();
     initEnvirement();
     initIgnoreList();
@@ -706,9 +700,9 @@ bool ConfigParser::parseDeployMode() {
                                         " then you must use the classic version of CQtDeployer instead of the snap version."
                                         " This is due to the fact that the snap version"
                                         " runs in an isolated container and has limited access"
-                                        " to system utilities and the environment. "
-                                        "For get the classic version of cqtdeployer use the cqtdeployer installer "
-                                        "https://github.com/QuasarApp/CQtDeployer/releases", QuasarAppUtils::Info);
+                                        " to system utilities and the environment."
+                                        " For get the classic version of cqtdeployer use the cqtdeployer installer"
+                                        " https://github.com/QuasarApp/CQtDeployer/releases", QuasarAppUtils::Info);
         }
 
         return false;
@@ -760,15 +754,39 @@ bool ConfigParser::parseInitMode() {
     return true;
 }
 
-void ConfigParser::configureTargets() {
+bool ConfigParser::configureTargets() {
     const auto icons = QuasarAppUtils::Params::getArg("icon").
             split(DeployCore::getSeparator(0), splitbehavior);
 
+    const auto runScripts = QuasarAppUtils::Params::getArg("runScript").
+            split(DeployCore::getSeparator(0), splitbehavior);
+
+    const auto disableShortcuts = QuasarAppUtils::Params::getArg("disableRunScript").
+            split(DeployCore::getSeparator(0), splitbehavior);
+
+    const auto disableRunScripts = QuasarAppUtils::Params::getArg("disableShortCut").
+            split(DeployCore::getSeparator(0), splitbehavior);
+
+
     if (icons.size()) {
         parseTargetPrivate(_config, icons, &TargetInfo::setIcon);
     }
 
-    return;
+    if (runScripts.size()) {
+        parseTargetPrivate(_config, runScripts, &TargetInfo::setRunScript);
+    }
+
+    if (disableShortcuts.size() && !enableOptionFotTargetPrivate(_config, disableShortcuts, &TargetInfo::disableShortCut)) {
+        packagesErrorLog("disableShortCut");
+        return false;
+    }
+
+    if (disableRunScripts.size() && !enableOptionFotTargetPrivate(_config, disableRunScripts, &TargetInfo::disableRunScript)) {
+        packagesErrorLog("disableRunScript");
+        return false;
+    }
+
+    return true;
 }
 
 bool ConfigParser::parseClearMode() {
@@ -1150,7 +1168,7 @@ bool ConfigParser::initQmake() {
 
         auto qt = *qtList.begin();
 
-        if (qt.right(3).compare("lib", Qt::CaseInsensitive)) {
+        if (qt.rightRef(3).compare(QString("lib"), Qt::CaseInsensitive)) {
             return initQmakePrivate(QFileInfo(qt + "/../bin/qmake").absoluteFilePath());
         }
 
@@ -1566,9 +1584,7 @@ bool ConfigParser::smartMoveTargets() {
 
     _config.targetsEdit() = temp;
 
-    configureTargets();
-
-    return result;
+    return result && configureTargets();
 }
 
 ConfigParser::ConfigParser(FileManager *filemanager, PluginsParser *pluginsParser, DependenciesScanner* scaner, Packing *pac):
diff --git a/Deploy/configparser.h b/Deploy/configparser.h
index 54a9d20..69f3685 100644
--- a/Deploy/configparser.h
+++ b/Deploy/configparser.h
@@ -52,7 +52,6 @@ private:
     bool loadFromFile(const QString& file);
     bool initDistroStruct();
     bool initPackages();
-    bool initRunScripts();
     bool parseDeployMode();
     bool parseInfoMode();
     bool parseInitMode();
@@ -60,7 +59,7 @@ private:
      * @brief configureTargets Sets targets data from options.
      * @return true if function finishe successfull
      */
-    void configureTargets();
+    bool configureTargets();
 
     bool parseClearMode();
 
diff --git a/Deploy/deployconfig.cpp b/Deploy/deployconfig.cpp
index 09836b2..e9439d1 100644
--- a/Deploy/deployconfig.cpp
+++ b/Deploy/deployconfig.cpp
@@ -104,15 +104,6 @@ void DeployConfig::setDefaultPackage(const QString &value) {
     defaultPackage = value;
 }
 
-void DeployConfig::registerRunScript(const QString &targetName,
-                                     const QString &scriptPath) {
-    _runScripts.insert(targetName, scriptPath);
-}
-
-QString DeployConfig::getRunScript(const QString &targetName) const {
-    return _runScripts.value(targetName, "");
-}
-
 QtMajorVersion DeployConfig::isNeededQt() const {
 
     auto Qt = QtMajorVersion::NoQt;
diff --git a/Deploy/deployconfig.h b/Deploy/deployconfig.h
index 2abdf08..f2935a5 100644
--- a/Deploy/deployconfig.h
+++ b/Deploy/deployconfig.h
@@ -122,9 +122,6 @@ public:
     QString getDefaultPackage() const;
     void setDefaultPackage(const QString &value);
 
-    void registerRunScript(const QString& targetName, const QString& scriptPath);
-    QString getRunScript(const QString& targetName) const;
-
      /**
      * @brief isNeededQt This method return all needed qt major version for all targets.
      * @return qt major version
@@ -155,12 +152,6 @@ private:
      */
     QHash<QString, DistroModule> _packages;
 
-    /**
-     * @brief _runScripts
-     * target - pathToScript
-     */
-    QHash<QString, QString> _runScripts;
-
     /**
      * @brief targetDir -  targe directory (this folder conteins all files of distrebution kit)
      */
diff --git a/Deploy/deploycore.cpp b/Deploy/deploycore.cpp
index 8d5a3dd..37ba1cd 100644
--- a/Deploy/deploycore.cpp
+++ b/Deploy/deploycore.cpp
@@ -295,7 +295,10 @@ void DeployCore::help() {
 
         {
             "Part 4 Control of packages options", {
-                {"-icon [target;val,val]", "Sets path to icon for a targets"}
+                {"-icon [target;val,val]", "Sets path to icon for a targets"},
+                {"-disableRunScript [target;val,val]", "Disables a generation of run script for selected targets"},
+                {"-disableShortCut [target;val,val]", "Disables a generation of shortcut for selected targets"}
+
             }
         },
 
diff --git a/Deploy/metafilemanager.cpp b/Deploy/metafilemanager.cpp
index b0c3aac..b2b9ab6 100644
--- a/Deploy/metafilemanager.cpp
+++ b/Deploy/metafilemanager.cpp
@@ -27,46 +27,15 @@ bool MetaFileManager::createRunScriptWindows(const QString &target) {
     QFileInfo targetInfo(target);
 
     QString content;
-    auto runScript = cnf->getRunScript(targetInfo.fileName());
-    if (runScript.size()) {
-        QFile script(runScript);
-        if (!script.open(QIODevice::ReadOnly)) {
-            return false;
-        }
-        content = script.readAll();
-        script.close();
+    auto runScript = targetinfo.getRunScript();
 
-    } else {
-
-        bool fGui = DeployCore::isGui(_mudulesMap.value(target));
-        auto systemLibsDir = distro.getLibOutDir() + DeployCore::systemLibsFolderName();
-
-        content =
-                "@echo off \n"
-                "SET BASE_DIR=%~dp0\n"
-                "SET PATH=%BASE_DIR%" + distro.getLibOutDir() + ";%PATH%;" + systemLibsDir + "\n"
-                "SET CQT_PKG_ROOT=%BASE_DIR%\n"
-                "SET CQT_RUN_FILE=%BASE_DIR%%0.bat\n"
-
-                "%3\n";
-
-        // Run application as invoke of the console for consle applications
-        // And run gui applciation in the detached mode.
-        if (fGui) {
-            content += "start \"%0\" %4 \"%BASE_DIR%" + distro.getBinOutDir() + "%1\" %2 \n";
-        } else {
-            content += "call \"%BASE_DIR%" + distro.getBinOutDir() + "%1\" %2 \n";
-        }
-
-        content = content.arg(targetInfo.baseName(), targetInfo.fileName(), "%*",
-                              generateCustoScriptBlok(true)); // %0 %1 %2 %3
-
-        content = QDir::toNativeSeparators(content);
-
-        if (fGui) {
-            content = content.arg("/B"); // %4
-        }
+    QFile script(runScript);
+    if (!script.open(QIODevice::ReadOnly)) {
+        return false;
     }
+    content = script.readAll();
+    script.close();
+    replace(toReplace(target, distro), content);
 
     QString fname = DeployCore::_config->getTargetDir(target) + QDir::separator() + targetInfo.baseName()+ ".bat";
 
@@ -90,6 +59,7 @@ bool MetaFileManager::createRunScriptWindows(const QString &target) {
 
 bool MetaFileManager::createRunScriptLinux(const QString &target) {
     auto cnf = DeployCore::_config;
+    auto targetinfo = cnf->targets().value(target);
 
     if (!cnf->targets().contains(target)) {
         return false;
@@ -99,48 +69,15 @@ bool MetaFileManager::createRunScriptLinux(const QString &target) {
     QFileInfo targetInfo(target);
 
     QString content;
-    auto runScript = cnf->getRunScript(targetInfo.fileName());
-    if (runScript.size()) {
-        QFile script(runScript);
-        if (!script.open(QIODevice::ReadOnly)) {
-            return false;
-        }
-        content = script.readAll();
-        script.close();
-
-    } else {
-
-        auto systemLibsDir = distro.getLibOutDir() + DeployCore::systemLibsFolderName();
-
-        content =
-                "#!/bin/sh\n"
-                "BASE_DIR=$(dirname \"$(readlink -f \"$0\")\")\n"
-                "export "
-                "LD_LIBRARY_PATH=\"$BASE_DIR\"" + distro.getLibOutDir() +
-                ":\"$BASE_DIR\":$LD_LIBRARY_PATH:\"$BASE_DIR\"" + systemLibsDir + "\n"
-                "export QML_IMPORT_PATH=\"$BASE_DIR\"" + distro.getQmlOutDir() + ":$QML_IMPORT_PATH\n"
-                "export QML2_IMPORT_PATH=\"$BASE_DIR\"" + distro.getQmlOutDir() + ":$QML2_IMPORT_PATH\n"
-                "export QT_PLUGIN_PATH=\"$BASE_DIR\"" + distro.getPluginsOutDir() + ":$QT_PLUGIN_PATH\n"
-                "export QTWEBENGINEPROCESS_PATH=\"$BASE_DIR\"" + distro.getBinOutDir() + "QtWebEngineProcess\n"
-                "export QTDIR=\"$BASE_DIR\"\n"
-                "export CQT_PKG_ROOT=\"$BASE_DIR\"\n"
-                "export CQT_RUN_FILE=\"$BASE_DIR/%2\"\n"
-
-                "export "
-                "QT_QPA_PLATFORM_PLUGIN_PATH=\"$BASE_DIR\"" + distro.getPluginsOutDir() +
-                "platforms:$QT_QPA_PLATFORM_PLUGIN_PATH\n"
-                ""
-                "%1\n"
-                "\"$BASE_DIR" + distro.getBinOutDir() + "%0\" \"$@\"\n";
-
-        content = content.arg(targetInfo.fileName()); // %0
-
-        content = content.arg(generateCustoScriptBlok(false),
-                              targetInfo.baseName()+ ".sh"); // %1 %2
-
-
-
+    auto runScript = targetinfo.getRunScript();
+    QFile script(runScript);
+    if (!script.open(QIODevice::ReadOnly)) {
+        return false;
     }
+    content = script.readAll();
+    script.close();
+    replace(toReplace(target, distro), content);
+
 
     QString fname = DeployCore::_config->getTargetDir(target) + QDir::separator() + targetInfo.baseName()+ ".sh";
 
@@ -173,9 +110,9 @@ QString MetaFileManager::generateCustoScriptBlok(bool bat) const {
     auto cstSh = QuasarAppUtils::Params::getArg("customScript", "");
     if (cstSh.size()) {
         res = "\n" +
-              commentMarker + "Begin Custom Script (generated by customScript flag)\n"
+                commentMarker + "Begin Custom Script (generated by customScript flag)\n"
               "%0\n" +
-              commentMarker + "End Custom Script\n"
+                commentMarker + "End Custom Script\n"
               "\n";
 
         res = res.arg(cstSh);
@@ -248,14 +185,63 @@ bool MetaFileManager::createQConf(const QString &target) {
                             QFileDevice::ReadOwner);
 }
 
+QHash<QString, QString> MetaFileManager::toReplace(const QString& target,
+                                                   const DistroModule& distro) const {
+    QFileInfo targetInfo(target);
+
+    QHash<QString, QString> result = {
+        {"CQT_BIN_PATH", distro.getBinOutDir()},
+        {"CQT_LIB_PATH", distro.getLibOutDir()},
+        {"CQT_QML_PATH", distro.getQmlOutDir()},
+        {"CQT_PLUGIN_PATH", distro.getPluginsOutDir()},
+        {"CQT_SYSTEM_LIB_PATH", distro.getLibOutDir() + DeployCore::systemLibsFolderName()},
+        {"CQT_BASE_NAME", targetInfo.baseName()}
+    };
+
+    bool fGui = DeployCore::isGui(_mudulesMap.value(target));
+
+
+    if (targetInfo.completeSuffix().compare(".exe", Qt::CaseInsensitive) == 0) {
+        result.insert("CQT_CUSTOM_SCRIPT_BLOCK", generateCustoScriptBlok(true));
+
+        // Run application as invoke of the console for consle applications
+        // And run gui applciation in the detached mode.
+        QString runCmd;
+        if (fGui) {
+            runCmd = "start \"" + targetInfo.baseName() + "\" /B " +
+                    "\"%BASE_DIR%" + distro.getBinOutDir() + targetInfo.fileName() + "\" %*";
+        } else {
+            runCmd = "call \"%BASE_DIR%" + distro.getBinOutDir() + targetInfo.fileName() + "\" %*";
+        }
+
+        result.insert("CQT_RUN_COMMAND", runCmd);
+
+    } else {
+        result.insert("CQT_CUSTOM_SCRIPT_BLOCK", generateCustoScriptBlok(false));
+
+        QString runCmd = "\"$BASE_DIR" + distro.getBinOutDir() + targetInfo.fileName() + "\" \"$@\" ";
+
+        result.insert("CQT_RUN_COMMAND", runCmd);
+    }
+
+    return result;
+}
+
+void MetaFileManager::replace(const QHash<QString, QString> &map, QString &content) {
+    for (auto it = map.begin(); it != map.end(); ++it) {
+        content = content.replace(it.key(), it.value());
+    }
+
+}
+
 void MetaFileManager::createRunMetaFiles(const QHash<QString, DeployCore::QtModule>& modulesMap) {
 
     _mudulesMap = modulesMap;
     for (auto i = DeployCore::_config->targets().cbegin(); i != DeployCore::_config->targets().cend(); ++i) {
 
-        if (!createRunScript(i.key())) {
+        if (i.value().fEnableRunScript() && !createRunScript(i.key())) {
             QuasarAppUtils::Params::log("Failed to create a run script: " + i.key(),
-                                         QuasarAppUtils::Error);
+                                        QuasarAppUtils::Error);
         }
 
         if (!createQConf(i.key())) {
diff --git a/Deploy/metafilemanager.h b/Deploy/metafilemanager.h
index 8bb88d1..533d540 100644
--- a/Deploy/metafilemanager.h
+++ b/Deploy/metafilemanager.h
@@ -12,6 +12,8 @@
 #include <deploycore.h>
 
 class FileManager;
+class DistroModule;
+class TargetInfo;
 
 class MetaFileManager
 {
@@ -32,6 +34,11 @@ private:
 
     bool createQConf(const QString &target);
 
+    QHash<QString, QString> toReplace(const QString &target,
+                                      const DistroModule &distro) const;
+
+    void replace(const QHash<QString, QString>& map, QString& content);
+
     FileManager* _fileManager = nullptr;
     QHash<QString, DeployCore::QtModule> _mudulesMap;
 };
diff --git a/Deploy/targetinfo.cpp b/Deploy/targetinfo.cpp
index 562d6f3..0209413 100644
--- a/Deploy/targetinfo.cpp
+++ b/Deploy/targetinfo.cpp
@@ -6,21 +6,28 @@
 //#
 
 #include "targetinfo.h"
+#include "deploycore.h"
+#include "deployconfig.h"
 
 TargetInfo::TargetInfo() {
 
 }
 
-QString TargetInfo::getPackage() const {
-    return package;
+TargetInfo::~TargetInfo() {
+    if (_fEnableRunScript)
+        delete _fEnableRunScript;
+}
+
+const QString & TargetInfo::getPackage() const {
+    return _package;
 }
 
 void TargetInfo::setPackage(const QString &value) {
-    package = value;
+    _package = value;
 }
 
 QString TargetInfo::getIcon() const {
-    if (icon.isEmpty()) {
+    if (_icon.isEmpty()) {
         QFileInfo info(getName());
         if (info.suffix() == "exe") {
             return ":/shared/Distributions/Templates/Icon.ico";
@@ -30,11 +37,74 @@ QString TargetInfo::getIcon() const {
 
     }
 
-    return icon;
+    return _icon;
 }
 
 void TargetInfo::setIcon(const QString &value) {
-    icon = value;
+    _icon = value;
+}
+
+bool TargetInfo::getShortCut() const {
+    return _fEnableShortCut;
+}
+
+void TargetInfo::setShortCut(bool shortcut) {
+    _fEnableShortCut = shortcut;
+}
+
+void TargetInfo::disableShortCut() {
+    setShortCut(false);
+}
+
+QString TargetInfo::getRunScript() const {
+    if (_runScript.isEmpty()) {
+        QFileInfo info(getName());
+        if (info.suffix() == "exe") {
+            return ":/Scripts/ScriptsTemplates/windows.bat";
+        }
+
+        return ":/Scripts/ScriptsTemplates/linux.sh";
+    }
+
+    return _runScript;
+}
+
+void TargetInfo::setRunScript(const QString &newRunScript) {
+    _runScript = newRunScript;
+}
+
+QString TargetInfo::getRunScriptFile() const {
+
+    if (_fEnableRunScript) {
+        QFileInfo runscriptInfo(_runScript);
+        QFileInfo info(getName());
+
+        return info.baseName() + "." + runscriptInfo.completeSuffix();
+    }
+
+    return getName();
+}
+
+bool TargetInfo::fEnableRunScript() const {
+
+    if (!_fEnableRunScript) {
+        QFileInfo info(fullPath());
+        QString compleSufix = info.completeSuffix();
+        return compleSufix.compare(".exe", Qt::CaseInsensitive) == 0 || compleSufix.isEmpty();
+    }
+
+    return _fEnableRunScript;
+}
+
+void TargetInfo::setFEnableRunScript(bool newFEnableRunScript) {
+    if (!_fEnableRunScript)
+        _fEnableRunScript = new bool;
+
+    *_fEnableRunScript = newFEnableRunScript;
+}
+
+void TargetInfo::disableRunScript() {
+    setFEnableRunScript(false);
 }
 
 
diff --git a/Deploy/targetinfo.h b/Deploy/targetinfo.h
index 68e30d1..9862b41 100644
--- a/Deploy/targetinfo.h
+++ b/Deploy/targetinfo.h
@@ -11,20 +11,102 @@
 #include "distrostruct.h"
 #include "libinfo.h"
 
+/**
+ * @brief The TargetInfo class This clas scontains information about target object. (executable or another files marked in a bin option)
+ */
 class DEPLOYSHARED_EXPORT TargetInfo: public LibInfo
 {
 public:
     TargetInfo();
+    ~TargetInfo();
 
-    QString getPackage() const;
+    /**
+     * @brief getPackage This method return name of the package in that contains this target.
+     * @return  name of the package in that contains this target.
+     */
+    const QString & getPackage() const;
+
+    /**
+     * @brief setPackage This method sets new value for pacakge name in that contains this target.
+     * @param value new This is new value of the pacakge.
+     */
     void setPackage(const QString &value);
 
+    /**
+     * @brief getIcon This method return path to default icon of the target.
+     * @return icon path.
+     * @note if the icon not set then return default icon.
+     */
     QString getIcon() const;
+
+    /**
+     * @brief setIcon This method sets new iconf for target.
+     * @param value
+     */
     void setIcon(const QString &value);
 
+    /**
+     * @brief getShortCut This method return true if the target need to create shortcut.
+     * @return true if shortcut needed for this target.
+     */
+    bool getShortCut() const;
+
+    /**
+     * @brief setShortCut This method sets new status of the creating shortcut.
+     * @param shortcut This is new value of the shortcut
+     */
+    void setShortCut(bool shortcut);
+
+    /**
+     * @brief disableShortCut This method disable shortcut for this target.
+     */
+    void disableShortCut();
+
+    /**
+     * @brief getRunScript This method return path to run script.
+     * @return path to run script
+     * @note By Default return path to default run scrip file from cqtdeployer resources.
+     */
+    QString getRunScript() const;
+
+    /**
+     * @brief setRunScript sets New path of the run script.
+     * @param newRunScript This is new path of the run sscript.
+     */
+    void setRunScript(const QString &newRunScript);
+
+    /**
+     * @brief getRunScriptFile This method return name fo the run script file or executable file if the run script are not needed
+     * @return runscript name
+     */
+    QString getRunScriptFile() const;
+
+
+    /**
+     * @brief fEnableRunScript This return true if the run script will be generateed for this target else false.
+     * @return true if the run script will be generateed for this target else false.
+     */
+    bool fEnableRunScript() const;
+
+    /**
+     * @brief setFEnableRunScript This method enable or disable generation runScript.
+     * @param newFEnableRunScript New value.
+     */
+    void setFEnableRunScript(bool newFEnableRunScript);
+
+    /**
+     * @brief disableRunScript This method disable run script for this target.
+     */
+    void disableRunScript();
+
 private:
-    QString package = "";
-    QString icon = "";
-};
+    QString _package = "";
+    QString _icon = "";
+    bool _fEnableShortCut = true;
+    bool *_fEnableRunScript = nullptr;
+
+    QString _runScript = "";
+
+ };
 
 #endif // TARGETINFO_H
diff --git a/UnitTests/tst_deploytest.cpp b/UnitTests/tst_deploytest.cpp
index a67a6bb..a9eeaee 100644
--- a/UnitTests/tst_deploytest.cpp
+++ b/UnitTests/tst_deploytest.cpp
@@ -181,6 +181,9 @@ private slots:
 
     void testMd5();
 
+    void testDisableShortcuts();
+    void testDisableRunScripts();
+
     void customTest();
 };
 
@@ -1464,6 +1467,15 @@ void deploytest::testMd5() {
                    "qifFromSystem"}, &comapareTreeqif);
 }
 
+void deploytest::testDisableShortcuts() {
+    QVERIFY(false);
+}
+
+void deploytest::testDisableRunScripts() {
+    QVERIFY(false);
+
+}
+
 void deploytest::customTest() {
     //runTestParams({"-confFile", "",
     //               "qifFromSystem"});
diff --git a/md/en/Options.md b/md/en/Options.md
index 24a32c2..f168ee8 100644
--- a/md/en/Options.md
+++ b/md/en/Options.md
@@ -126,7 +126,8 @@ cqtdeployer -option1 value1 -option2 list, of, values ​​flag1 flag2 flag3
 | Option                      | Descriptiion                                              |
 |-----------------------------|-----------------------------------------------------------|
 |  -icon [target;val,val]    | Sets path to icon for a targets                           |
-
+|  -disableRunScript [target;val,val] | Disables a generation of run script for selected targets|
+|  -disableShortCut [target;val,val]  | Disables a generation of shortcut for selected targets |
 
 ### Plugins Controll Options
 
diff --git a/md/ru/Options.md b/md/ru/Options.md
index 8a41025..7ff3fa9 100644
--- a/md/ru/Options.md
+++ b/md/ru/Options.md
@@ -123,6 +123,8 @@ cqtdeployer -option1 value1 -option2 list,of,values flag1 flag2 flag3
 | Option                      | Descriptiion                                              |
 |-----------------------------|-----------------------------------------------------------|
 |  -icon [target;val,val]     | Установит путь к иконке или логотипу для целе             |
+|  -disableRunScript [target; val, val]| Отключает создание сценария выполнения для выбранных целей |
+|  -disableShortCut [target; val, val] | Отключает создание ярлыков для выбранных целей | 
 
 ### Параметры управления плагинами: