A suggestion for modules names / sharing code between projects

Mike Parker via Digitalmars-d digitalmars-d at puremagic.com
Wed Mar 2 17:47:08 PST 2016


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?


More information about the Digitalmars-d mailing list