I'm currently building a testing library in Standard ML (using Poly/ML as the interpreter). I have the following directory structure:
project/a.sml
project/src/b.sml
project/src/c.sml
...
Where a.sml is just a bunch of calls to use
use "src/b.sml"
use "src/c.sml"
...
b.sml, c.sml etc. are all structure definitions like this
structure ComponentX
struct
...
end
which form nice, logically separated components of the library. I sometimes also create one module in one file, and then introduce a substructure within the same module in another file.
I can then use the testing library fine within the root directory of the project, by calling use "a.sml".
However, I can't seem to be able to use the code outside of its own directory, which is a bit of an issue. For example, say I'm in the parent directory of project. If I then call use "project/a.sml", the subsequent calls to use "src/x.sml" try to find a src directory in the parent (which doesn't exist).
Is there some way to do a relative use, or is there a better way to structure this altogether?
The use function itself in Poly/ML doesn't change the path when it is used recursively. You will need to change the path within the sub-directory explicitly using OS.FileSys.chDir. use is just a function so you could redefine it if you wanted. The OS.Path and OS.FileSys structures could be useful.
An alternative is to reorganise your code to make use of PolyML.make. You would have to rename your files to match the name of the structure that each file contains e.g. ComponentX.sml would contain structure ComponentX. For more on this see polyml.org/documentation/Reference/PolyMLMake.html or a this answer about Poly/ML with nested directory structures.
Related
I've had trouble with this issue across many languages, most recently with C++.
The Issue Exemplified
Let's say we're working with C++ and have the following file structure for a project:
("Project" main folder with three [modules, data, etc] subfolders)
Now say:
Our maincode.cpp is in the Project folder
moduleA.cpp is in modules folder
data.txt is in data folder
moduleA.cpp wants to read data.txt
So the way I'd currently do it would be to assume maincode.cpp gets compiled & executed inside the Project folder, and so hardcode the path data/data.txt in moduleA.cpp to do the reading (say I used fstream fs("data/data.txt") to do so).
But what if the code was, for some reason, executed inside etc folder?
Is there a way around this?
The Questions
Is this a valid question? Or am I missing something with the wd (working directory) concept fundamentals?
Are there any methods for working around absolute paths so as to solve this issue in C++?
Are there any universal methods for doing the same with any language?
If there are no reasonable methods, how would you approach this issue?
Please leave a comment if I missed any important details with the problem's illustration!
At some point the program has to make an assumption where the file(s) are. Either by getting it from user input or a relative path with the presumed filename. As already said in the comments, C++ recently got std::filesystem added in C++17 which can help you making cross-platform code that interacts with the hosts' filesystem.
That being said, every program, big or small, has to make certain assumptions at some point, deleting or moving certain files is problematic for any program in case the program requires them to be at a certain location under a certain name. This is not solvable other than presenting the user with an error message etc.
As #Hatted Rooster said, it's not generally solvable for some arbitrary file without making some assumptions, however there are frameworks that allow you to "store" some files in the resources embedded into the executable (or otherwise). Those frameworks would usually allow your to handle such files in a opaque way, without the need to rely on a current working dir or relative paths.
For example, see the Qt Resource System.
Your program can deduce the path from argv[0] in the main call, if you know that it is always relative to your executable or you use an absolute path like "C:\myProgram\data\data.txt".
The second approach works in every language.
While developing and translating an application, it might be nice if gettext will use the catalogs found in the local po/ dir so it wouldn't be necessary to call make install each time.
Is there a way to do it?
One of the problems is the naming convention: gettext looks for the catalog files in an hierarchy that looks like /usr/share/locale/LL/LC_MESSAGES/package.mo (where LL is two-letter language code), while usually in the development tree the binary catalogs reside in po/LL.gmo.
it might be nice if gettext will use the catalogs found in the local po/ dir so it wouldn't be necessary to call make install each time....Is there a way to do it?
If I am understanding your idea correctly, it sounds like gettext is able to do just that (i.e. change the translation path variable) if you follow the prescribed methods to set it up...
Translations should be stored in a path having a fixed structure.
First of all, we’ll have a root folder named to your taste (for
example “languages”). Inside it, we have to create a folder for every
targeted language whose name must comply to the ISO 3166 standard. So,
valid names for an Italian translation can be “it_IT” (Italian of
Italy), “it_CH” (Italian of Switzerland), “en_US” (English of USA),
and so on. Within the folder having the language code, we must have a
folder named “LC_MESSAGES” where, finally, we’ll store the translation
files.
From Here (there is a script example included in this link showing one method to perform this task)
Change "languages" in description above to "po", and that may do what you want?
I've got some older versions of boost code that uses the member function leaf() of the path class in the boost filesystem library. However, when trying to compile it recently, I've noticed this has disappeared and deprecated.
The task it is doing is getting all the directories that are in a specified folder and storing them.
For the sake of this example, let's just say I was outputting them to the console.
For the example, the directories could be:
/home/user/dir/
/home/user/dir/one
/home/user/dir/two
/hone/user/dir/three
So I pass in /home/user/dir into a directory_iterator and check if it's a directory using is_directory(). What I would like would be to print the last part of the paths, so...
one
two
three
I know I could do some string manipulation to do this by searching for the last / etc. but I would like to know if there is still a way to do this using the path class.
As I can read from the Boost documentation, the leaf() method has been replaced with filename(). You can get all the elements using iterators. More in Boost Filesystem Tutorial, including working example of usage.
This stackoverflow question shows how to get a list of all the dependencies for one or more targets. How do you get the same thing from within a SConstruct file?
Edit:
That is, as an Object or something. You could always recursively call scons -tree=all and grab stdout from that process, but I don't want a hack. I'd like access to the dependency object scons is using.
The best way to get this information is to just look at the source for SCons. You're looking for the file SCons/Script/Main.py, and in particular for the TreePrinter class. The basic idea is that all SCons nodes contain within themselves all the relevant details for reconstructing the dependancy graph.
The simplest test case I could think of is:
import os
env = Environment(ENV = os.environ)
app = env.Program('dummy', 'main.cpp')
for item in app:
for child in item.all_children():
print child
The code for doing this isn't really that complicated, but I certainly wouldn't want to rely on it not changing (it isn't part of the public interface for SCons).
I do not think that is possible from within the code. The code in the SConstruct file is the code that generates the tree. So the tree cannot be provided before all the code in the SConstruct file is executed. On the other hand I think it should be possible to get the object you mention within python, if you have the patience to look through the Scons code to see how they operate their --tree option. But you will have to wait until the tree is generated before you access it.
I am woking in c++.
Is there any method to know whether a directory contain a sub directory?
CFileFind seems have to search through total files.
It is time consuming if the only subdirectory is at the end of the list and the there are lots of files.
for example: directory A contains 99995 files and one subdirectory at the end of FindNextFile List. had I try 99995 times, then say: yes, it contains subdirectory?
Raymond Chen from Microsoft has written a post that probably applies here: Computing the size of a directory is more than just adding file sizes. In essence, he explains that information like the size of a dir cannot be stored in the dir's entry, because different users might have different permissions, possibly making some of the files invisible to them. Therefore, the only way to get the size the user should see is to calculate it upon request from the user.
In your case, the answer probably stems from the same reasoning. The list of directories available to your app can only be determined when your app asks for it, as its view of the root directory might be different than another app's, running with different credentials. Why Windows store directories along with files I don't know, but that's a given.
Since Win32 is as close as you'll get to the file system in user mode, I'd avoid any higher level solutions such as .NET, as it might only simplify the interface. A driver might work quicker, but that out of the scope of my knowledge.
If you are using the .Net framework you could use Directory.GetDirectories and check is the size of the array is 0. Do not know how if this will give you speed.
If you have control over the directories you could apply a naming convention so that directories that have sub directories are named one way and directories with out sub directories are named another.
You can try using the boost filesystem library.
A class by name directory_iterator [ declared in boost/filesystem/operations.hpp ] has many functions which can be used for listing files, finding whether the file is a sub-directory ( is_directory -- I guess this is what you are looking for ) etc..
Refer the following link for more information.
link text
It seems you are using MFC [ just saw that you are using CFileFind ], didn't see that earlier.
Sorry, Didn't have much info. You may have to use FindFirstFile/FindNextFile.
Whether this can be done very fast is entirely platform-dependent.
On Win32 you use FindFirstFile/FindNextFile or wrappers on top of those like MFC CFileFind and they list items in some order that can't be forced to list directories first.