On Wednesday, 2 March 2016 at 20:40:39 UTC, Sebastien Alaiwan wrote:

However, it feels wrong that modules (foo, bar) inside the same package ("pkg") need to repeat the "absolute" package name when referencing each other, I mean "import pkg.foo" instead of "import foo". Not because of the extra typing, but because of the dependency it introduces. But as I said, maybe my vision is wrong.

The package name is part of the module name. If you use thislib.somemod and thatlib.somemod, how would you disambiguate them without the package name? Even in C and C++, libraries are often distributed with header files in a sub directory, where the top-level directory is intended to be added to the include path and not the subdirecotry, otherwise two includes with the same name conflict. Some libraries go further and prefix their header files with a namespace (like sdl_foo.h, sdl_bar.h), because they get no help from the compiler with this. Making the package name part of the fully qualified module name helps minimize the likelihood of such conflicts. It also gives a natural namespace for conflicting symbols in two modules named foo. You can use thispack.somemod.foo and thatpack.somemod.foo to disambiguate.


- I only work with separate compilation, using gdc (Windows-dmd produces OMF, which is a dealbreaker ; but I use rdmd a lot for small programs).

-m64 or -m32mscoff

- I often mix C code with D, sometimes, C++ code. I compile them using gcc/g++.

Assuming MinGW, the GDC is definitely your best bet here. The flags above will get DMD to produce COFF for the MS linker, but MinGW COFF and MS COFF are not always compatible.



With this flat directory structure, the only way test.d can import files is by saying, "import stack;", not "import lib_algo.stack". (adding ".." to the list of import directories might do the trick, but this would definitely feel wrong).

It is wrong. You should add ../mylibs :)


Now, let's see a project using this "lib_algo", I call it "myGame".

$ cd myProjects
$ find <files relevant to this discussion>
myGame/lib_algo/options.d
myGame/lib_algo/....
myGame/lib_algo/array2d.d
myGame/lib_algo/project.mk
myGame/lib_algo/Makefile
myGame/src/main.d
myGame/Makefile


"lib_algo" simply is an external (aka "git submodule"), pointing to a specific revision of the repository "lib_algo". The top-level "Makefile" of the projects includes "lib_algo/project.mk", and all is well, I can compose the list of source files to compile without having to rely on "convenience/intermediate" libraries.

Now, if "src/main.d" wants to import "array2d.d", currently, I must write "import array2d.d", and add "-I myGame/lib_algo" to my compiler command line.
I said in a previous post that this would not scale.
That's because with this scheme, obviously, I can't have two modules having the same name, even if they belong to different libraries. Let's say I have "lib_algo/utils.d" and "lib_geom/utils.d", if "main.d" says "import utils.d", it's ambiguous.

Assuming that all of the libraries you are going to use are set up the same way, then you can simply pass -ImyGame. Then you can use lib_algo.utils, lib_geom.utils, and so on. What's the problem with that?


Clearly, "main.d" needs to say "import lib_algo.utils". However, if I do this, I must add a module declaration in "lib_algo/utils.d", and I must change
"lib_algo/test.d" so it says "import lib_algo.utils".

This is where it begins to feel clumsy. Why should lib_algo need to be modified in order to resolve an ambiguity happening in "myGame" ?

You shouldn't have to "change" it. This is how it should be set up from the beginning. The idea is that you decide on a module structure as soon as you start your project and then you stick to it.

The module declaration is necessary when using packages because otherwise DMD has no idea how far up the path to go to create a default package name. That's why the it uses only the file name when no module declaration is present. The package name is the solution to *prevent* ambiguities, not to resolve them after the fact. If you don't want lib_algo/util.d and lib_geom/util.d to conflict, then the use both lib_algo and lib_geom as package names in module declarations. How else would you propose resolving the ambiguity?


Moreover, we saw earlier that this modification of the import done by "lib_algo/test.d" had consequences on the directory structure of lib_algo. In order to be able to build the test executable for lib_algo, I now need to
have the following structure:
$ find lib_algo
lib_algo/lib_algo/options.d
lib_algo/lib_algo/....
lib_algo/lib_algo/array2d.d
lib_algo/test.d
(test.d can be put inside the inner "lib_algo")

Am I the only one to find this counterintuitive - and probably wrong?
What am I missing there?

No, you don't have to set it up that way. If your top-level directory is always named the same as your top-level package name, then you can just use its parent directory.

mylibs/lib_algo/*.d
mylibs/lib_geom/*.d

dmd -Imylibs main.d

Done. Does not the same issue exist in C++? You either have to keep all of your headers in a single directory or pass multiple directories on the command line with -I.

What I used to do before I started using DUB exclusively was model the system I used for C and C++ projects. For every new project I created, I had created an imports subdirectory in the project, then ran a script (written in D) to copy over the source tree of the specific version of each library I wanted to use. Then I added -Iimport on the command line when compiling. Done.

The package and module system is very intuitive to me and has been from the beginning, so I'm still not quite sure what it is about it that bothers you. The two major issues you bring up here, the need to import package.module and how to structure your projects, are easily resolved. Am I misunderstanding something?

Reply via email to