www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Strategy to link/include library

reply "o3o" <orfeo.davia gmail.com> writes:
Suppose I have the following library structure (from Andrei
Alexandrescu 'The D Programming Language' pag. 352)

acme
├── algebra.d
└── io
      └── file.d

// acme/algebra.d
module algebra;
import std.stdio;

public void gun() {
     writeln("algebra->gun");
}

// acme/io/file.d
import std.stdio;
public void fun() {
     writeln("file->fun");
}

and suppose I want to use it in this client

acmeClient
├── acme.a
└── client.d


// acmeClient/client.d
import std.stdio;
import algebra;
import io.file;
void main(string[] args) {
     algebra.gun();
     gun();
     fun();
}

I want link acme.a to my client, so Andrei wrote:
-----
The syntax for building a library depends on the implementation;
on the
reference implementation, you’d do something like this:

% cd /path/to/acme_impl
% dmd -lib -ofacme algebra.d gui.d io/file.d io/network.d

The switch -lib instructs the compiler to build a library, and
the switch
-of (“output file”) directs the output to a file called acme.lib
(Windows)
or acme.a (various Unix-derived systems). With that library in
tow, all
you have to do now to get client code running is something like

% dmd client.d acme.lib
-----

So I write (in acme)
    $ cd acme
    $ dmd -lib -ofacme algebra.d io/file.d

in acmeClient
    $ cd ../acmeClient
    $ cp ../acme/acme.a .
    $ dmd client.d acme.a -ofclient
     app.d(2): Error: module algebra is in file 'algebra.d' which
cannot be read

instead if I write
    $ dmd -I../acme acme.a app.d
it works.

So, if I want to use acme library in my client project I need to
know
the entire acme source code. is that correct? Is there an easier
way?

I am a C# programmer and with Mono dmcs compiler I can do:

(in acme)
$ dmcs  -out:acme.a -target:library *.cs

(in acmeClient)
$ cp ../acme/acme.a .
$ dmcs -out:client -target:exe -reference:acme.a *.cs

(..to be honest it easy because mono assembly contains metadata
and
reference options imports that metadata)

So, if I use "Module Summaries" (pag 350 Andrei's book),
$ cd acme
$ dmd -lib -H doitall.d

doitall.di and doitall.d are identical (except for comments).

Is there any "pattern" to use "shared" code inside a project?
(i.e. manually copy all acme source in a client subdirectory, use
git subtree, etc.)
Jan 16 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-01-16 12:25, o3o wrote:
 Suppose I have the following library structure (from Andrei
 Alexandrescu 'The D Programming Language' pag. 352)

 acme
 ├── algebra.d
 └── io
       └── file.d

 // acme/algebra.d
 module algebra;
 import std.stdio;

 public void gun() {
      writeln("algebra->gun");
 }

 // acme/io/file.d
 import std.stdio;
 public void fun() {
      writeln("file->fun");
 }

 and suppose I want to use it in this client

 acmeClient
 ├── acme.a
 └── client.d


 // acmeClient/client.d
 import std.stdio;
 import algebra;
 import io.file;
 void main(string[] args) {
      algebra.gun();
      gun();
      fun();
 }

 I want link acme.a to my client, so Andrei wrote:
 -----
 The syntax for building a library depends on the implementation;
 on the
 reference implementation, you’d do something like this:

 % cd /path/to/acme_impl
 % dmd -lib -ofacme algebra.d gui.d io/file.d io/network.d

 The switch -lib instructs the compiler to build a library, and
 the switch
 -of (“output file”) directs the output to a file called acme.lib
 (Windows)
 or acme.a (various Unix-derived systems). With that library in
 tow, all
 you have to do now to get client code running is something like

 % dmd client.d acme.lib
 -----

 So I write (in acme)
     $ cd acme
     $ dmd -lib -ofacme algebra.d io/file.d

 in acmeClient
     $ cd ../acmeClient
     $ cp ../acme/acme.a .
     $ dmd client.d acme.a -ofclient
      app.d(2): Error: module algebra is in file 'algebra.d' which
 cannot be read

 instead if I write
     $ dmd -I../acme acme.a app.d
 it works.

 So, if I want to use acme library in my client project I need to
 know
 the entire acme source code. is that correct? Is there an easier
 way?
Yes, it needs to have the source or rather the declarations you want to use.
 I am a C# programmer and with Mono dmcs compiler I can do:

 (in acme)
 $ dmcs  -out:acme.a -target:library *.cs

 (in acmeClient)
 $ cp ../acme/acme.a .
 $ dmcs -out:client -target:exe -reference:acme.a *.cs

 (..to be honest it easy because mono assembly contains metadata
 and
 reference options imports that metadata)
The assemblies contains the needed declarations.
 So, if I use "Module Summaries" (pag 350 Andrei's book),
 $ cd acme
 $ dmd -lib -H doitall.d

 doitall.di and doitall.d are identical (except for comments).
It could, and previously did, remove the implementation of all functions and methods. But that will prevent CTFE (Compile Time Function Evaluation) and inlining functions.
 Is there any "pattern" to use "shared" code inside a project?
 (i.e. manually copy all acme source in a client subdirectory, use
 git subtree, etc.)
You usually place it in a common directory. You then use the -I switch to make the compiler aware of this directory. This flag can be but in dmd.conf/dm.ini to avoid repeating. Ideally this should be handled by a package manager and a build tool. -- /Jacob Carlborg
Jan 16 2013
parent reply "o3o" <orfeo.davia gmail.com> writes:
On Wednesday, 16 January 2013 at 12:00:54 UTC, Jacob Carlborg 
wrote:

Thanks for your prompt response.

 [cut]
 You usually place it in a common directory. You then use the -I 
 switch to make the compiler aware of this directory.
Let me play with some scenario: I've a library 'acme' release 1.0 and two client C1 and C2. * scenario 1: acme in common directory + acme ... + C1 ... + C2 ... So, in C1 $dms -I../acme *.d and in C2 $dms -I../acme *.d suppose that C2 need a new feature from acme library, so I modify and recompile acme sources and I get the new acme rel. 2.0. But C1 still uses the old release 1.0, and if I recompile C1 it is linked to new new acme rel. 2.0... * scenario 2: acme in subdirectory If I include acme as subdirectory like this: + C1 ... + acme + C2 ... + acme I resolve the problem on scenario 1. (C1 uses rel. 1.0 and C2 rel. 2.0) but if I fix a bug in acme, I should update C1, C2 and all other clients that use acme. What do you think? what is your way of working?
 Ideally this should be handled by a package manager and a build 
 tool.
which package manager do you suggest? (of course orbit :) ), and which build tool (I use rake)? Thank you very much
Jan 16 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-01-16 16:08, o3o wrote:

 Let me play with some scenario: I've a library 'acme' release 1.0 and
 two client C1 and C2.

 * scenario 1: acme in common directory
 + acme
    ...
 + C1
    ...
 + C2
    ...

 So, in C1
 $dms -I../acme *.d

 and in C2
 $dms -I../acme *.d

 suppose that C2 need a new feature from acme library, so I modify and
 recompile acme sources and I get the new acme rel. 2.0.
 But C1 still uses the old release 1.0, and if I recompile C1 it is
 linked to new new acme rel. 2.0...

 * scenario 2: acme in subdirectory
 If I include acme as subdirectory like this:

 + C1
    ...
    + acme
 + C2
    ...
    + acme

 I resolve the problem on scenario 1. (C1 uses rel. 1.0 and C2 rel. 2.0)
 but if I fix a bug in acme, I should update C1, C2 and all other clients
 that use acme.

 What do you think? what is your way of working?
For my projects I mostly use git submodules. A submodule will be its own repository but included in another repository. They have separate commit histories. A submodule is locked at a given commit from the repository of the submodule.
 which package manager do you suggest? (of course orbit :) ),
Yes :) But currently there is now package manager available specific for D.
 and which build tool (I use rake)?
For executables I use a shell script with rdmd. rdmd will track and compile all dependencies. I usually don't compile libraries, just include them together with the application and compiler everything at once with rdmd. In the end I'm not really happy with any solution available, that's why I'm working on a package manager. -- /Jacob Carlborg
Jan 16 2013
parent "o3o" <orfeo.davia gmail.com> writes:
It's very useful to me ,,,thank you Jacob,
Jan 17 2013