Getting the source directory at runtime



  • Is there a way to know what the source directory of the project is at runtime?

    EDIT
    I havent stated my problem clearly. I have a project that contains external assets that the application needs access to. Adding these assets as resources leads to the compiled application being 100MB+ since it's packing the assets in the .exe. I dont want that.

    What I have done so far is to use the INSTALLS variable in the .pro file so that qmake can copy over the assets during the build process, but this requires setting up QtCreator to run the install command as stated here:
    http://stackoverflow.com/questions/11593165/qtcreator-copy-files-to-output-directory-with-installs

    The DISTFILES variable doesnt seem to work out of the box either. There's also surprisingly very little information on it on the internet too.

    I'm seeking a way to allow the application to be aware of the external (non-source) assets placed in the project folder. I need people to be able to just download the code from the repo, open the project in QtCreator and run it with all the assets copied to the output folder.

    Here's the link to the repo: https://github.com/jahshaka/VR

    EDIT 2

    I found the solution. I used QMAKE_EXTRA_TARGETS to add a post-build target that runs a copy command to move the assets to the output folder.

    http://stackoverflow.com/questions/19066593/copy-a-file-to-build-directory-after-compiling-project-with-qt/39234363#39234363

    copydata.commands = $(COPY_FILE) \"$$shell_path($$PWD\\archive.png)\" \"$$shell_path($$OUT_PWD)\" 
    first.depends = $(first) copydata
    export(first.depends)
    export(copydata.commands)
    QMAKE_EXTRA_TARGETS += first copydata
    

  • Qt Champions 2016

    @njbrown said in Getting the source directory at runtime:

    Is there a way to know what the source directory of the project is at runtime?

    Do you mean when running qmake? Because the other thing doesn't make any sense ... after you compile and link there is no concept of source, much less source directory (ignoring debug information for the sake of argument). Why would you need such information anyway?



  • There are a couple of ways you could do this, such as:

    • use the __FILE__ preprocessor macro
    • use the build system (qmake, cmake, etc) to define a custom macro

    Qt's QFINDTESTDATA() macro uses both approaches

    #ifdef QT_TESTCASE_BUILDDIR
    # define QFINDTESTDATA(basepath)\
        QTest::qFindTestData(basepath, __FILE__, __LINE__, QT_TESTCASE_BUILDDIR)
    #else
    # define QFINDTESTDATA(basepath)\
        QTest::qFindTestData(basepath, __FILE__, __LINE__)
    #endif
    

    Here __FILE__ is the standard C preprocessor macro, and QT_TESTCASE_BUILDDIR is added to the compiler flags automatically by qmake (presumably when the *.pro file includes CONFIG += testcase), but you can roll your own too if you'd like.

    Just wondering, what do you want to use that directory for at runtime?

    Cheers.



  • @kshegunov I havent stated my problem clearly. I have a project that contains external assets that the application needs access to. Adding these assets as resources leads to the compiled application being 100MB+ since it's packing the assets in the .exe. I dont want that.

    What I have done so far is to use the INSTALLS variable in the .pro file so that qmake can copy over the assets during the build process, but this requires setting up QtCreator to run the install command as stated here:
    http://stackoverflow.com/questions/11593165/qtcreator-copy-files-to-output-directory-with-installs

    The DISTFILES variable doesnt seem to work out of the box either. There's also surprisingly very little information on it on the internet too.

    I'm seeking a way to allow the application to be aware of the external (non-source) assets placed in the project folder. I need people to be able to just download the code from the repo, open the project in QtCreator and run it with all the assets copied to the output folder.

    My next approach is to make the application aware of the project folder itself where the assets are kept. Can this be done?

    @Paul-Colby your solution seems to require running the app as a test project. Am I wrong?
    I like the second option you stated, using the build system to define a macro.
    I tried:

    DEFINES += SOURCE_PATH=$$PWD
    

    which does give me the directory without double quotes to denote it as a string, which results in a compile error when i try this:

    qDebug()<<SOURCE_PATH;
    

    Is there a way to get quotes around the macro?

    Here's the link to the repo: https://github.com/jahshaka/VR



  • Hi @njbrown,

    Thanks for expanding on your question :)

    Yes, the QFINDTESTDATA() marco requires Qt Test, but I was only presenting it an example of the sorts of things you could do, not suggesting that you'd want to use it in production code ;)

    In this case, it sounds to me a lot like you really just want to write something very similar to the (internal) QString QTest::qFindTestData function - ie just use it as inspiration.

    As the comments within that function say, the "find" order is:

        //  1. relative to test binary.
    
        //  2. installed path.
    
        //  3. relative to test source.
    
        // 4. Try resources
    
        // 5. Try current directory
    
        // 6. Try main source directory
    

    Again you can just use that implementation as inspiration. It sounds to me like you want to first try relative to the current application binary (step 1 above), then perhaps relative to the application's source directory (step 3 and/or 6). Presumably the first option would match production installations, and the second option would work as a fallback for running-within--Qt-Creator scenarios?

    Just a side thought... (I assume) its steps 3 and 6 that use the __FILE__ and QT_TESTCASE_BUILDDIR macros respectively. Presumably step 2 would use the INSTALLS (or related) values. The others (steps 1, 4 and 5) are standard C/C++/Qt.

    Cheers.


  • Qt Champions 2016

    @njbrown said in Getting the source directory at runtime:

    Adding these assets as resources leads to the compiled application being 100MB+ since it's packing the assets in the .exe. I dont want that.

    Why don't you compile the assets as an external resource that you load at runtime? Incidentally this will also output the compiled binary resource package in your build directory ($$OUT_PWD in qmake terms).

    DEFINES += SOURCE_PATH=$$PWD
    

    That's a rather risky macro. $$PWD contains the .pro file's directory and it's not a relative path. There's some magic that can be done with qmake but I advise against it. If you require something to be done before/after building, add a pre/post-build step. For a simple example you could take a look here or mr Colby's blog.



  • @njbrown said in Getting the source directory at runtime:

    I'm seeking a way to allow the application to be aware of the external (non-source) assets placed in the project folder

    When you deploy your application put the files you need in the same folder of the executable (or one relative to it) and use QCoreApplication::applicationFilePath() to get it


  • Qt Champions 2016

    @VRonin said in Getting the source directory at runtime:

    use QCoreApplication::applicationFilePath() to get it

    QString fileName = "resource_file.bin";
    QString filePath = QDir(QCoreApplication::applicationDirPath()).filePath(fileName);
    


  • I found the solution to the problem. Instead of pointing my app to the project's source folder, I provided an extra qmake target (to QMAKE_EXTRA_TARGETS) that runs a copy command that copies the assets over the output folder post-build. It works without having to setup anything extra.

    Resources that helped me understand QMAKE_EXTRA_TARGETS :
    http://colby.id.au/pre-pre-build-commands-with-qmake/
    http://dragly.org/2013/11/05/copying-data-files-to-the-build-directory-when-working-with-qmake/

    This link had the solution:
    http://stackoverflow.com/questions/19066593/copy-a-file-to-build-directory-after-compiling-project-with-qt/39234363#39234363

    copydata.commands = $(COPY_FILE) \"$$shell_path($$PWD\\archive.png)\" \"$$shell_path($$OUT_PWD)\" 
    first.depends = $(first) copydata
    export(first.depends)
    export(copydata.commands)
    QMAKE_EXTRA_TARGETS += first copydata
    

    Thanks for all the help guys!



  • I'm not 100% convinced this is the right solution. QMAKE_EXTRA_TARGETS is used to customise the build step. what I would have done is:

    isEmpty(PREFIX) {
     PREFIX = $$DESTDIR
    }
    target.path = $$PREFIX
    extraResource.path = $$PREFIX
    extraResource.files += archive.png
    INSTALLS += target extraResource
    

    now make install will place the extra resources in the folder of the binary (or wherever you want by setting the PREFIX variable when you run qmake


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.