A suggestion for modules names / sharing code between projects

Sebastien Alaiwan via Digitalmars-d digitalmars-d at puremagic.com
Wed Mar 2 12:40:39 PST 2016


On Wednesday, 2 March 2016 at 08:50:50 UTC, Mike Parker wrote:
> I'm curious what sort of system you have in mind. How does the 
> current system not work for you and what would you prefer to 
> see?

First, you must know that I've been a C++ programmer for way too 
much time ;
and that my way of thinking about modules has probably been - 
badly - shaped accordingly :-).

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.

I'm going to answer your first question, I hope you don't get 
bored before the end ;-)

First some generic stuff:
- The libraries I write are source-only, and I never install them 
system-wide, as many projects might depend on different revisions 
of one library.
- 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).
- I often mix C code with D, sometimes, C++ code. I compile them 
using gcc/g++.
- My build system is composed of simple dependency-aware 
non-recursive makefiles (BTW, this is a great way to keep your 
code decoupled, otherwise you might not get feedback that you're 
making a dependency mess soon enough!)

This is the best way I found to be able to checkout one project, 
type 'make',
and have everything build properly, wether I'm doing it on 
GNU/Linux or on Windows (MSYS).

Everything is under version control using GNU Bazaar (which 
basically is to git what D is to C++).

I have a small library, which I call "lib_algo", containing 
semi-related utilities (containers, topological sort, etc.) which 
I use in many projects.

$ cd myLibs
$ find lib_algo -name "*.d" -or -name "*.mk" -or name "Makefile"
lib_algo/options.d
lib_algo/misc.d
lib_algo/pointer.d
lib_algo/set.d
lib_algo/queue.d
lib_algo/algebraic.d
lib_algo/vector.d
lib_algo/bresenham.d
lib_algo/topological.d
lib_algo/fix_array.d
lib_algo/test.d
lib_algo/pool.d
lib_algo/stack.d
lib_algo/list.d
lib_algo/array2d.d
lib_algo/project.mk
lib_algo/Makefile
(I know, there's some overlap with Phobos today)

The project.mk simply contains the list of source files of the 
library.
The test.d file actually contains a main function, which I use to 
run manual tests of the library functionalities. It's not 
included in the project.mk list. And it obviously must import the 
files needing to be tested.

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).

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.

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" ?

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?

(And please, don't tell me that I need to switch to 
dub+git+dmd+D_source_files_only ; I like my tools to be 
composable)

Thanks for reading!



More information about the Digitalmars-d mailing list