Uploaded image for project: 'Qbs ("Cubes")'
  1. Qbs ("Cubes")
  2. QBS-956

Improve deployment process ( too complicated, practically undocumented )

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Out of scope
    • Not Evaluated
    • None
    • 1.4.5
    • Documentation, General
    • None
    • OSX, Linux, Windows

    Description

      Deployment is undividable part of creating application.
      QBS is perfect for building process. Great reusability and simplification of project definitions.
      Example of simplification In CoreApp (code down) there can be anything handling multiplatform app, translation, icons, resources etc. even deployment ( but it is hard to define ) And this few lines of code can be used for one main.cpp up to for hunderds files in subproject and it will works the same. That's really perfect i like it very much.

      import qbs.base 1.0
      import qbs.FileInfo
      import "../../common/coreapp.qbs" as CoreApp
      CoreApp {
              name: FileInfo.baseName(path);
              Depends { name: "Qt.sql" }
          }
      }
      

      But deployment which can be done using adding .pri file into project in qmake is really nightmere. All examples ends with building process. No documentation on deployment.

      include(../common/hgversioning.pri) // hg version available within code
      include(../common/appdeployment.pri) // deploys application 
      include(translation.pri) // deploys translationsdeployment 
      include(whatsnew.pri) // deploys what's new
      include(help.pri) // creates and deploys help files
      

      Each file has maximum of 30 lines and it uses *QMAKE_POST_LINK* and it works on windows or osx universally for any application where it is added in project file. ( if it uses similar folder structer of course )

      By this few line I can tell which application can be deployed which has help and I can copy it in any other project and it will always work without any problem.

      *Example of qmake deployment for application, works for any my project for any application*

      # Deployment
      CONFIG (release, release|debug) {
          macx {
              QMAKE_POST_LINK += macdeployqt $${DESTDIR}/$${TARGET}.app &
          } else: win32 {
              QMAKE_POST_LINK += windeployqt $${DESTDIR}/$${TARGET}.exe &
          }
      }
      

      *Similar code for QBS which does not work anyway ( macdeploy does not work with qbs QBS-954 )* It is large because I was solving not working macdeployqt

      import qbs
      import qbs.FileInfo
      import qbs.Process
      
      Product {
          type: [ "deployment" ]
          property bool debug: true
          Rule{
              inputs:["qbs", depProduct]
              inputsFromDependencies: [depProduct]
      
              Artifact  {
                  filePath: "deploy" + product.name
                  fileTags: [ "deployment" ]
              }
              prepare: {
                  var cmd;
                  var deployqt;
                  var targetOS = product.moduleProperty("qbs", "targetOS");
                  var targetDep = product.dependencies[0];
                  var targetName = targetDep.name;
                  if (targetOS.contains("windows")) {
                      targetName = targetName + ".exe";
                      deployqt = FileInfo.joinPaths(product.moduleProperty("Qt.core", "binPath"), "windeployqt");
                  } else if (targetOS.contains("osx")) {
                      targetName = targetName + ".app";
                      deployqt = FileInfo.joinPaths(product.moduleProperty("Qt.core", "binPath"), "macdeployqt");
                  }
                  var libDir = product.moduleProperty("Qt.core", "libPath");
                  var pluginDir = product.moduleProperty("Qt.core", "pluginPath");
                  var targetPath = FileInfo.path(product.moduleProperty("qbs", "installRoot") + "/" + targetDep.relativeInstallDir + "/" + targetName);
      
                  if (product.debug) {
                      print("deploy:" + deployqt);
                      print("targetname:" + targetName);
                      print("targetpath:" + targetPath);
                      print("path:" + FileInfo.path(deployqt));
                      print("libdir:" + libDir);
                      print("plugin:" + pluginDir);
                  }
      
      
                  cmd = new JavaScriptCommand();
                  cmd.command = deployqt;
                  cmd.target = targetName;
                  cmd.workingDir = targetPath;
                  cmd.libdir = libDir;
                  cmd.plugindir = pluginDir;
                  cmd.description = "deploying: " + targetDep.name
                  cmd.sourceCode = function() {
                      var process = new Process();
                      try {
                          process.setWorkingDirectory(workingDir);
                          process.setEnv("QTDIR", FileInfo.path(command) + "/..");
                          process.setEnv("QT_INSTALL_LIBS", libdir);
                          process.setEnv("QT_INSTALL_PLUGINS", plugindir);
                          process.exec(command, [target, "-verbose=3"]);
                          if (process.exitCode() !== 0) {
                              throw(process.readStdErr());
                          } else {
                              print(process.readStdOut());
                              print(process.readStdErr());
                          }
                      } finally {
                          process.close();
                      }
                  };
      
                  return cmd;
              }
          }
      }
      

      And I had to use many workarounds. ( install in relative folder to qbs.installFolder in order to deploy it to specific folder in home/shared folder etc.
      One line of code with QMAKE_POST_LINK is replaced with bloat code. That's not step forward but huge steps back!
      I wanted to simplify it by moving it to process.js script, but what is accessible from qbs is not always accesibble form .js what is accessible from product is not assessible from Rule etc. Not possible to create user script userCommand(command, arguments), because of that accessible dependancy which is not obvious and it like playing mouse and a cat game.

      Then I can use Deployment.qbs like this ( it works only on windows )

      Deployment {
              property string depProduct: "teru"
              name: depProduct + "deploy"
              Depends { name: "teru" }
              Depends { name: "Qt.core" }
          }
      

      On OSX it does not work for two reasons: install-dir is not created, because I am using workaround to install it to different folder. And on OSX ../../../.. relative path does not work if path does not exists. On windows it does work.
      And as I told, macdeployqt does not work with qbs projects.

      What QBS does not have

      • Documentation of deployment ( QBS concentrate for unknown reason only on building process, not on creating applications )
      • Examples with deployment ( no example creates application, it creates executables )
      • No option to change install location within QBS ( workaround use path relative to qbs.instllRoot using FileInfo.relativePath, but it does not work for shared folders different discs/letters ) something like DESTDIR *why not to have qbs.installRoot accessible from QBS itself?* If you think that you approach is better, OK, but please do not limit other approaches. I do not want to change command line argument or implement some other preprocessor step in order to make it dependand on tag from mercurial ( test_Jira_tag, is release to test folder for testing jira issue etc. )
      • No information how to copy application bundle into installDir
        fileTagsFilter: [ "application" ]
        qbs.install: true
        qbs.installDir: product.relativeInstallDir
        qbs.installSourceBase: product.buildDirectory
        

        This does not work! Bacause it will copy only executable

         
                fileTagsFilter: [ "infoplist", "application", "pkginfo" ]
        

        This fileTagsFillter will copy infolist and pkginfo. Nothing is documented. I have found it in some source code.

      *Suggestion:*
      Create example application dependent on internal libraries and external ( downloadable from internet and builded ) which can be deployed on one click from QtCreator ( or by running qbs from command line ) in windows linux and osx.

      Why, becase anybody can delete any code which does not suite him, but create one is extremly hard with QBS.
      I can create start project on github.com, but I do not understand QBS much ( about 1 week experience )
      Examples in QBS are too simple and not one is complete.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            Unassigned Unassigned
            fbucek fbucek
            Votes:
            6 Vote for this issue
            Watchers:
            9 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes