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.
Related
I've been asked to make a small mod to some software that was written back in the mid naughties on IAR Embedded Workbench v3.3
I have had the original source files copied from an old machine to one I have been given for the task.
For the moment I am simply trying to get the software compiling. It took me a while to realise, or at least I thought I'd realised, that the reason it couldn't open various header files was that, incredibly, all the include paths were absolute, not relative.
So, I changed all the paths to be $PROJ_DIR$ relative, but then started to get different files that couldn't be opened. Then realised that the machine they gave me just happened to have a very similar directory structure to the original machine used and, amazingly, had quite a few of the same files in the directory structure of this machine I'm using as was on the machine used to compile the code originally.
I then thought, OK, I'll just check I have got my relative paths correct by choosing one of the header files it was complaining about not finding and putting, in the Preprocessor tab, an absolute path to the directory on this machine I'm using that contained the header file it wanted. However, that still wouldn't find the header file!
Finally, I put an absolute path in the c file to point to the desired header file.
#include "C:\absolute__Path\stdtyp.h"
And it compiled.
To confirm:
Putting C:\absolute__Path
in the Project | Options | C/C++ compiler | Preprocessor tab will not work if I just have:
#include "stdtyp.h"
in the c file.
I have used IAR in the past - not that much - but I have used it and I was sure that's where you set your include directories. So, am I wrong, or can there be something else that is overriding that path in the Preprocessor tab as described above?
Edit: I'm not wrong, after having slept on it, I decided to create a new project with random directories, subdirectories and header files. Sure enough, if I set and remove $PROJ_DIR$ referenced paths in the preprocessor tab, the new project compiles, then doesn't. So, there must be something, presumably in the ewp file that is borking it.
It turns out you can override the paths on an individual file by file basis. So, the rogue files had the paths overridden and had absolute paths.
Right click on the file in EW and select Options.
That then for most file shows a load of greyed out boxes. What I'd failed to do was thoroughly check all files. The few I'd randomly checked were greyed out, but some files had their properties overridden here with different (and absolute) paths put there.
At least now the project can be easily copied between machines having used relative paths.
I'm using Xcode (with C++) and my project layout (in the file system, not in Xcode) looks like this:
SubfolderA
-file_A_1, file_A_2
SubfolderB
-file_B_1, file_B_2
Right now I've set up this structure in Xcode via groups. And so, when I want to include file_A_2 in file_B_1, I write #include "file_A_2" in file_B_1.
Is there some way to make an inclusion look like #include "/SubfolderA/file_A_2", so that I can easily see to what directory/subfolder an included file belongs?
One way to see what's going on is to look at the Build Log and expand the line for compiling sourcefile.m. Look at the -I options being passed to the compiler.
If it's not to your liking you can add the source tree in the Build Settings > Header Search Paths to include $(ProjectDir)/srcroot and make it recursive, which saves you from adding each sub-folder individually.
In my experience this has never been necessary, however, as far as I can remember.
As far as the Xcode folders are concerned, if the top-level source folder is added then all sub-folders are automatically added when you add them to the filesystem, saving the hassle of keeping them in sync. You might need to add the top-level folder under the Source Files group for this to work, however.
Surprisingly, in Xcode's Build Settings I've added to User Header Search Paths non-recursive path to my project. This solved my problem.
I ended up here when I was having an issue with XCode while trying to include a header in a group by doing
#include "MyGroup/MyHeader.h"
Turns out the project structure and the file system weren't in sync, so I just had to remove my group from the project, put it in the correct place in Finder, then drag and drop it back into the project in the correct place and it worked for me.
I'm not sure if this is necessary or not, but I also have already set up my app's working directory because I am doing some game programming and need to be able to load in .png and make textures.
http://youtu.be/6NCtnKcwOas (select better quality!)
As you can see on the attached video, I have the two projects in my solution - a dll creator and a simple testing project. Just followed this tutorial .
Why does the MathFuncsDll.h still remain undetected?Everything works fine after specifying the full path after '#include'. However, I don't want to use such rough-and-ready method because it looks messy and unprofessionally.
If you can specify the file using an absolute path, but not by only using its filename, the compiler doesn't "know" about the folder containing that file.
You can tell the compiler about your additional include directories via the /I directive (documentation). And of course you can set that via the IDE.
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.
I understand SetCurrentDirectory shouldn't be used in a multithreaded application since the current directory is shared between all threads in the process.
What is the best approach to setting the directory with this in mind.
It can mostly be avoided setting the directory by including the full pathname when opening files instead of first navigating to them with SetCurrentDirectory, but is this the only solution?
I've encountered this problem before.
Any object that needs the concept of a current directory to support relative paths or searching (e.g. a build tool) has a member property that it maintains with its "current" path, then build the full path to open/create/search.
The initial value for CurrentPath can be retrieved once during the application's load phase, e.g. main(), WinMain(), DllInit(), etc. via GetCurrentDirectory and stored in a global. After that the Win32 version is ignored.
The OPENFILENAME structure has an initial directory member, so file open/save dialogs don't have to use the Win32 current directory.
Each process has a single current directory, so if you want each thread in your process use different current directory I think you should specify the full path in each.
A advice to use full paths in general and local paths only as a exception (and very carefully), when needed. I.e. the OpenFile Dialog may or may not change the current directory (depending on attributes) etc. Using filenames or local paths is a potential cause of trouble.
By my experience full paths do not slow down file access significantly. I wrote a app that opens thousands of files every minute and writes sorted data to other thousands of files - all using full paths and all on a windows mounted network drive. The bottleneck there was closing the files. Not opening them.