Qt Creator/qmake - Load assets folder from source directory, as opposed to build directory - c++

Is there a way to specify the root directory at runtime within a program's execution? The reason why I ask is because I'd like to be able to have an assets folder which I can access in code simply via "assets/" relatively, as opposed to having to type "absolute/path/to/assets". Worst case scenario I can create a macro or a const std::string/QString to append to everything, but I find that it would be cleaner to just allow the project to be able to access everything relatively FROM the source directory, as opposed to the actual build directory.
How can this be achieved, if at all?
edit
I should also state that I'm operating in Linux, and don't have any plans for multi-platform use at the moment, mainly due to the fact that I'm just creating study projects.

Switch your working directory to the application executable's directory, like so:
if (QDir::setCurrent(QCoreApplication::applicationDirPath())) {
// success!
...
}
This is cross-platform.

Related

"Embedding" a folder into a C/C++ program

I have a script library stored in .../lib/ that I want to embed into my program. So far, that sounds simple: On Windows, I'd use Windows Resource Files - on MacOS, I'd put them into a Resource folder and use the proper API to access the current bundle and it's resources. On plain Linux, I am not too sure how to do it... But, I want to be cross-platform anyway.
Now, I know that there are tools like IncBin (https://github.com/graphitemaster/incbin) and alike, but they are best used for single files. What I have, however, might even require some kind of file system abstraction.
So here is the few guesses and estimates I did. I'd like to know if there is possibly a better solution - or others, in general.
Create a Zip file and use MiniZ in order to read it's contents off a char array. Basically, running the zip file through IncBin and passing it as a buffer to MiniZ to let me work on that.
Use an abstracted FS layer like PhysicsFS or TTVFS and add the possibility to work off a Zip file or any other kind of archive.
Are there other solutions? Thanks!
I had this same issue, and I solved it by locating the library relative to argv[0]. But that only works if you invoke the program by its absolute path -- i.e., not via $PATH in the shell. So I invoke my program by a one-line script in ~/bin, or any other directory that's in your search path:
exec /wherever/bin/program "$#"
When the program is run, argv[0] is set to "/wherever/bin/program", and it knows to look in "/wherever/lib" for the related scripts.
Of course if you're installing directly into standard locations, you can rely on the standard directory structure, such as /usr/local/bin/program for the executable and /etc/program for related scripts & config files. The technique above is just when you want to be able to install a whole bundle in an arbitrary place.
EDIT: If you don't want the one-line shell script, you can also say:
alias program=/wherever/bin/program

Gradle native c++ non source files resources or assets folder location?

Context: I am primarily a Java developer and I use gradle for all my builds. As a hobby I've been playing around with C/C++ and found that gradle has the ability to build these as well. So instead of learning cmake/make just for some small hobby projects I thought I'd use gradle since I am familiar with it.
Question: How do I define locations for non-source files?
With Java there is a resources folder that you can put things like images, text files, etc... in and gradle will put these in the jar so in your code you can load them with relative paths pretty easily.
src > main > java for source files.
src > main > resources for assets.
Is there an equivalent way to do this for c++ projects?
Also if there is a default folder that would be good to know, but also how to define it in the build.gradle file to a different location would also be appreciated.
For reference here is my simple build file right now:
apply plugin: "cpp"
model {
components {
main(NativeExecutableSpec) {
sources {
cpp {
source {
srcDir "src"
}
}
}
}
}
}
In my code I'd like to be able to load an image, for example, with something like:
HoweverYouLoadAnImageInCpp("imageName.png");
While having a simple structure like:
root
--src
--images
If there is no way to currently do this, is there a workaround or a more standard way people do this in C/C++?
As mentioned in the comments, unlike jars in java, c/c++ does not seem to have a standard way of including assets in the executable. There do seem to be platform specific ways and gradle does seem to have support for Windows resource files, so if that is what you are looking for see the gradle docs.
I prefer not to do any platform specific things though so I thought I'd answer this with what I decided to do in case someone else finds this question with a similar need. If another, better, answer pops up and I notice I will change the selection.
In the end the executable will look for paths relative to where it is executed (from what I can tell at least.) So I just made a copy task to put the assets in a parallel folder.
task copyAssets {
copy {
from "."
into "build/exe/main"
include "images/**" // This will take the whole images folder from project root
}
}
build.dependsOn copyAssets
So when I gradle build now it will copy my images folder to the same folder that it builds my 'main' cpp source executable. And in my code I can access those images with:
HoweverYouGetImages("images/imagename.png");
You could of course get more fancy with your task and zip it up or compress your images and decompress on loading in your code.

path relative to cpp not working directory

I am working on some C++ code, that mainly provides a class for two other projects that share it but also includes a small program so that it can be used from the command line if needed. The class has to load some resources, that are written to several files in a resources folder. The path to these files is of course hard coded into the program, since I don't want any client using the class having to worry about loading those resources, other than calling an init method. When I compile the project on its own, with the hardcoded fopen("resources/myresource.dat") it works as expected, but when it is included in another project, the whole thing is typically placed into a separate subdirectory with only the header included as #include "subdir/myclass.h". In this case the hardcoded paths are invalid as the working directory is one folder higher.
How can I make sure the path to the resources folder is always valid, regardless of the path of the include?
How can I make sure the path to the resources folder is always valid, regardless of the path of the include?
It's not anyhow related to the include's path.
What you actually need is an installation routine, that provides you with a environment variable like $MYAPP_RESOURCE_PATH and having that expanded instead of your hardcoded path "resources/myresource.dat".
You can retrieve the environment variable's value with the getenv() function.

Using Non-Local Data/Media Files with a C++ Application (gtkmm)

I'm beginning development on an acoustic spectrum analysis tool (inspired by spek) written in C++ with gtkmm (C++ bindings for the GTK+ GUI toolkit). I would imagine that I should know how to do this by now, however...
My directory structure is a-la-GNOME, e.g src/, data/, po/, man/. The specific situation that presented the need for my inquiry is the use of a GTK UI Manager that will be located in data/ui. For this specific situation, I want to be able to load the user-interface from this file in an install-independent manner (e.g. loading of the file does not depend on a make install; the executable may be run [and load the UI file] either from src/ after running make [thus compiling the sources into the selfsame exectuable] or from its install prefix). How would I refer to the UI file in my source code (keeping in mind that the loading of the file is not performed by creating a file object (fopen(...)) but rather by passing a file location as a string argument to (UIManager).add_ui_from_file(...))?
In addition to this particular situation of a UI file, how would I do similar references to files (i.e. databases, INI files, XML schemas) by using the autotools build process? Is there a piece of relevant Automake code to quickly set up a project to use this type of directory structure?
simply try to use both files (with the un-installed taking precedence):
if(!(UIManager).add_ui_from_file(../data/ui/mygui))
(UIManager).add_ui_from_file(/incalled/location/mygui)
In Glom, I created a helper function that tries both locations, with both locations being defined in the Makefile.am (this is simpler if you have only one Makefile.am, by using non-recursive automake, which is simpler anyway):
http://git.gnome.org/browse/glom/tree/glom/glade_utils.h#n38

How to make XCode put required resources in "build" folder?

I am trying out lua script with C++ in Mac OS X. I was finding a way to make the program returning the current working directory. That's no problem with getcwd, but then I came one thing:
My foo.lua stays at its initial path only. When I compile program, it is not being copied over to the build/Debug directory. Sure, I can grab my script there, but that's just impractical. XCode or any IDE should carry resources to the build zone. XCode does this automatically with iPhone app, but this seems to be a different case. For this case, how to command XCode to put the respective resources in the build directories?
int main (int argc, char * const argv[]) {
...
...
luaL_dofile(luaVM,"/Users/yourNameHere/Desktop/LuaSandbox/LetsTryLua/foo.lua");
//typing the whole absolute path here is just ugly and impractical.
...
...
printf("working directory: %s", buffer);
//output is: working directory: /Users/yourNameHere/Desktop/LuaSandbox/LetsTryLua/build/Debug
...
...
Rather than hard code the path to your Lua script you may want to use the NSBundle API's to find it:
NSBundle * mainNSBundle = [NSBundle mainBundle];
NSString * luaFilePath = [mainNSBundle pathForResource:#"foo"
ofType:#"lua"
inDirectory:NULL
forLocalization:NULL];
luaL_dofile(luaVM,[luaFilePath UTF8String]);
This will find it in the bundle's folder (if you added the "Copy Bundle Resources" build step to your target as the above poster suggested.
Because you're using a .lua file as a resource, I suspect that isn't recognised as a standard resource type and hence it hasn't been automatically copied. You should be able to do this though by adding an extra Copy Bundle Resources build step to your target and then add your file to it in the project view.
If you're creating a command line tool that is not a bundle, then there's never going to be a good solution. If you're creating a regular app then the aforementioned solution will work, but you're going to have to stop assuming that your working directory is set to anything even remotely meaningful at any point in time and use the appropriate methods for finding resources stored within your bundle.