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-installsThe 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.
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
-
@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, andQT_TESTCASE_BUILDDIR
is added to the compiler flags automatically by qmake (presumably when the*.pro
file includesCONFIG += 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.
- use the
-
@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-installsThe 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__
andQT_TESTCASE_BUILDDIR
macros respectively. Presumably step 2 would use theINSTALLS
(or related) values. The others (steps 1, 4 and 5) are standard C/C++/Qt.Cheers.
-
@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
inqmake
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 withqmake
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 -
@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#39234363copydata.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 thePREFIX
variable when you runqmake