8

I'm writing a cross-platform C++ program using Qt and I want to package/embed a number of binary executables within the program. The program should be able to execute these binaries at runtime.

I figured, I would need QResource and QProcess using start() and the ":/..." notation, but I don't seem to get the process running. Is there anything I am missing? Should it work like this? Does the binary need to be set as executable?

Background: I am writing a tool which uses Git and I don't want to require the end-user to install Git manually.

(Trying this on Mac OS X, BTW.)

Update:

I am using the following code (C++, Qt on Mac OS X):

QString program = ":/git";
QStringList arguments;
arguments << "help" << "commit";
myProcess->start(program, arguments);

The Git executable is in the project path, my resources.qrc references it like so:

<qresource prefix="/">
    <file>git</file>
</qresource>

I'm not getting an error, but the program is not executed. Behavior is the same when I set program to a non-existing file. Replacing ":/git" by the absolute path to git works perfectly.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jan
  • 1,160
  • 1
  • 9
  • 11

4 Answers4

11

You can't execute a program directly from a resource.

If you had a program in a resource and you wanted to execute it, you'd first have to read it out of the resource, write it to a file, make the file executable, then execute it.

Also, when you say that you're not getting an error, that probably means that you aren't checking for errors properly.

rohanpm
  • 4,264
  • 17
  • 16
  • Thank you Rohan. "Not getting an error" was just lazy speak for "it fails silently". I guess I would get an error if I checked properly :) – jan Dec 23 '09 at 11:07
  • For windows: https://www.blackhat.com/presentations/bh-usa-07/Harbour/Whitepaper/bh-usa-07-harbour-WP.pdf – Dmitry Sazonov Sep 25 '15 at 11:29
4

Several years late, but the question is still relevant. I had the same problem when wanting to embed rclone.

In the .pro file, add

# From http://stackoverflow.com/a/37561981
defineReplace(copyToDir) {
    files = $$1
    DIR = $$2
    LINK =

    for(FILE, files) {
        LINK += $$QMAKE_COPY $$shell_path($$FILE) $$shell_path($$DIR) $$escape_expand(\\n\\t)
    }
    return($$LINK)
}

defineReplace(copyToBuilddir) {
    return($$copyToDir($$1, $$OUT_PWD))
}

# Copy the binary files dependent on the system architecture
win32 {
    message("Windows")
    QMAKE_POST_LINK += $$copyToBuilddir($$PWD/rclone/windows/rclone.exe)
}else: unix:!macx {
    message("Linux")
    QMAKE_POST_LINK += $$copyToBuilddir($$PWD/rclone/linux/rclone)
}else: macx: {
    # Here we want to place the binaries inside the application bundle, so the 
    # QMAKE_POST_LINK approach will not work because it places them in the same
    # directory as the bundle and not inside it. Instead, use QMAKE_BUNDLE_DATA.
    message("macOS")
    MediaFiles.files += $$PWD/rclone/macOS/rclone
    MediaFiles.path = Contents/MacOS
    QMAKE_BUNDLE_DATA += MediaFiles
}

Notice how there are slight differences for each platform, but in general the approach is the same.

qmake will copy this files to the destination directory, and they will be accessible by simply making the process call to the local relative directory.

In the following code, I call the executable from QML, and it's going to be very similar in C++ as well:

var rcloneCommand
if (Qt.platform.os === "windows") {
    console.log("Windows")
    rcloneCommand = "rclone.exe"
} else {
    console.log("OSX/Linux")
    rcloneCommand = "./rclone"
}
qProcess.start(rcloneCommand, ["--config", "rclone.conf", "-v", "copy", "--stats", "1s", source, destination]);
Kenn Sebesta
  • 7,485
  • 1
  • 19
  • 21
2

I don't think resources would work. Processes are created by operating system, and resources are handled by application.

One possible solution would be bundle additional executables somewhere in your application directory and execute them from that path.

  • thank you! can you indicate how you would embed them in the application bundle (osx)? I would like to avoid having an installer - a simple dmg image should be all user would have to download. – jan Dec 21 '09 at 21:04
0

So the problem doesn't seem to be extracting the git executable from the resource so much as executing it?

The git program is generate don disk correctly, can you check it's permissions ?

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263