www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Linking to libraries with D

reply Jarrod <gigantic.midget gmail.com> writes:
Well I know this sounds a rather mundane question to all you code buffs out
there, but I'm wondering how I would use C libraries with D.

I've already somewhat figured it out, but I guess I'm still confused a little
because unlike C, D doesn't have header files, and unlike perl, D doesn't seem
to 'add' your imported modules into your code.

See, what I've done is I've converted the curl C headers to D, which leaves me
with two .d files. Now at first, with my perl experience I expected to be able
to just import the module, and the compiler would include the necessary
'header' code into the finished object. However this is not the case. I had to
compile the 'header' into an object, and then link it. This is all well and
good, but it feels.. rather 'unclean' I guess. I mean I expect I'll be using
curl for multiple applications, so am I going to have to make a static
library, just for my D applications to link to.. another library?

I guess the question I'm getting at is, would there a better way to do this?
Is there a way to make the compiler actually compile and include the code you
import? I would rather not have to make a static library just to use code I'm
importing from another library, but I also don't want to have to manually
build and link the code I'm importing every time either. Am I missing
something here?

Any advice much appreciated,
Jarrod.
Nov 16 2007
next sibling parent Alexander Panek <alexander.panek brainsware.org> writes:
On Fri, 16 Nov 2007 12:28:33 +0000 (UTC)
Jarrod <gigantic.midget gmail.com> wrote:

 Well I know this sounds a rather mundane question to all you code
 buffs out there, but I'm wondering how I would use C libraries with D.

Flattering. :P
 I guess the question I'm getting at is, would there a better way to
 do this? Is there a way to make the compiler actually compile and
 include the code you import? I would rather not have to make a static
 library just to use code I'm importing from another library, but I
 also don't want to have to manually build and link the code I'm
 importing every time either. Am I missing something here?

May I suggest taking a look at DSSS and/or Rebuild? It might do exactly what you want. -- Alexander Panek <alexander.panek brainsware.org>
Nov 16 2007
prev sibling next sibling parent reply torhu <no spam.invalid> writes:
Jarrod wrote:
 Well I know this sounds a rather mundane question to all you code buffs out
 there, but I'm wondering how I would use C libraries with D.
 
 I've already somewhat figured it out, but I guess I'm still confused a little
 because unlike C, D doesn't have header files, and unlike perl, D doesn't seem
 to 'add' your imported modules into your code.
 
 See, what I've done is I've converted the curl C headers to D, which leaves me
 with two .d files. Now at first, with my perl experience I expected to be able
 to just import the module, and the compiler would include the necessary
 'header' code into the finished object. However this is not the case. I had to
 compile the 'header' into an object, and then link it. This is all well and
 good, but it feels.. rather 'unclean' I guess. I mean I expect I'll be using
 curl for multiple applications, so am I going to have to make a static
 library, just for my D applications to link to.. another library?
 
 I guess the question I'm getting at is, would there a better way to do this?
 Is there a way to make the compiler actually compile and include the code you
 import? I would rather not have to make a static library just to use code I'm
 importing from another library, but I also don't want to have to manually
 build and link the code I'm importing every time either. Am I missing
 something here?
 
 Any advice much appreciated,
 Jarrod.

If you've only translated the C headers to D, you need to link with the actual C library too: dmd yourapp.d curl.lib (or probably -L-lcurl on linux?) The .d files work as both headers and implementation files, as needed. If you have an app that contains two files, main.d and tools.d, and uses the library stuff.lib, you compile and link like this: dmd main.d tools.d stuff.lib Lets assume that main.d imports tools.d. When the compiler compiles main.d, it uses tools.d just as a header, to see that the correct declarations are there. But unless you put it on the compiler's command line, tools.d itself won't actually be compiled and linked. You can use the bud tool from dsource.org/projects/build to automate this. Then you only need to include the main source file, plus libraries to get the same effect: bud main.d stuff.lib There's also a similar tool called dsss that linux users seem to prefer: http://www.dsource.org/projects/dsss
Nov 16 2007
parent reply Jarrod <gigantic.midget gmail.com> writes:
== Quote from torhu
 Lets assume that main.d imports tools.d.  When the compiler compiles
 main.d, it uses tools.d just as a header, to see that the correct
 declarations are there.  But unless you put it on the compiler's command
 line, tools.d itself won't actually be compiled and linked.

system as a means of actually including the code itself. I guess its not a huge setback but it does sure feel a bit 'broken' to implement such a system. It would seem more intuitive to have the imported modules.. well, imported, instead of just used as a header.
 You can use the bud tool from dsource.org/projects/build to automate
 this.  Then you only need to include the main source file, plus
 libraries to get the same effect:
 bud main.d stuff.lib
 There's also a similar tool called dsss that linux users seem to prefer:
 http://www.dsource.org/projects/dsss

Alexanders reply also suggested dsss, so I guess I'll look into its usage. Thanks to you both for the quick reply, Jarrod.
Nov 16 2007
parent reply torhu <no spam.invalid> writes:
Jarrod wrote:
 I have dsss, but I wasn't aware that it could be used to automate this process.
 Alexanders reply also suggested dsss, so I guess I'll look into its usage.

To get started, just replace 'dmd' in your command line with 'rebuild', but leave out all .d files except the one with your main function in it. Rebuild comes with dsss, and is what dsss uses for the actual building. Later, you can have a look at what features dsss adds on top of rebuild.
Nov 16 2007
parent reply Jarrod <gigantic.midget gmail.com> writes:
== Quote from torhu
 To get started, just replace 'dmd' in your command line with 'rebuild',
 but leave out all .d files except the one with your main function in it.
   Rebuild comes with dsss, and is what dsss uses for the actual
 building.  Later, you can have a look at what features dsss adds on top
 of rebuild.

Holy crap, it uses the power of black magic and just makes it all work. Wow this tool is fantastic. Thanks a lot! Jarrod.
Nov 16 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrod wrote:
 == Quote from torhu
 To get started, just replace 'dmd' in your command line with 'rebuild',
 but leave out all .d files except the one with your main function in it.
   Rebuild comes with dsss, and is what dsss uses for the actual
 building.  Later, you can have a look at what features dsss adds on top
 of rebuild.

Holy crap, it uses the power of black magic and just makes it all work. Wow this tool is fantastic. Thanks a lot! Jarrod.

Also try out the -oqcruft switch on rebuild. That puts intermediate build products into the 'cruft' subdirectory so you don't have to look at them in your main directory. DSSS does that automatically. To use dsss, in the simplest case, just make a one line file called dsss.conf containing the name of your main .d file in brackets. Like so: #--------dsss.conf [main.d] #--------end dsss.conf Then "dsss build" will build an exe called main.exe from main.d and all its dependencies. --bb
Nov 16 2007
prev sibling next sibling parent reply "Anders Bergh" <anders1 gmail.com> writes:
On Nov 16, 2007 1:28 PM, Jarrod <gigantic.midget gmail.com> wrote:
 Well I know this sounds a rather mundane question to all you code buffs out
 there, but I'm wondering how I would use C libraries with D.

If you use DSSS, you could add this to your curl.d: version(build) pragma(link, "curl"); This will work on both Windows and Linux. I'm not actually 100% sure this is the proper "DSSS way", but it works for me. Anders
Nov 16 2007
parent reply Jarrod <gigantic.midget gmail.com> writes:
== Quote from Anders Bergh
 If you use DSSS, you could add this to your curl.d:
 version(build) pragma(link, "curl");
 This will work on both Windows and Linux. I'm not actually 100% sure
 this is the proper "DSSS way", but it works for me.
 Anders

Anders, I think I worded the topic a bit wrong. My issue is not that I can't link with the C library, it's more that I can't link with the C library without having to compile curl.d. I guess it just seems redundant to me that I have to compile what should only really be a header file. And I'll be compiling it into a static library no less, meaning I needed to make a library just to interface with another library. Not exactly seamless. Oh well, just a few more minutes of effort anyway. Thanks for the reply, Jarrod.
Nov 16 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrod wrote:
 == Quote from Anders Bergh
 If you use DSSS, you could add this to your curl.d:
 version(build) pragma(link, "curl");
 This will work on both Windows and Linux. I'm not actually 100% sure
 this is the proper "DSSS way", but it works for me.
 Anders

Anders, I think I worded the topic a bit wrong. My issue is not that I can't link with the C library, it's more that I can't link with the C library without having to compile curl.d. I guess it just seems redundant to me that I have to compile what should only really be a header file. And I'll be compiling it into a static library no less, meaning I needed to make a library just to interface with another library.

Ever heard of "precompiled headers" in C++ land. Do they give you the shivers just hearing the word? They do me. Because precompiled headers are an awful collection of vendor specific kludges to try to fix the terrible performance that comes from the C++ way of textually including every header file. Because #include just pastes the text in, it means for every .c/.cpp file the compiler comes across it re-parses and re-compiles *all* the headers that that .c file depends on in any way. Doing it the D way with modules means that every file only needs to be parsed and compiled once. That's part of the reason why D complies so darn fast compared to C++. It's like "precompiled headers" are always on.
 Not exactly seamless.
 Oh well, just a few more minutes of effort anyway.

Yes, well many folks have complained that bud or dsss-like functionality should be part of the compiler. That is, dmd should have a way to recursively compile all imports included from the modules listed on the compile line. For some reason Walter just doesn't go for it though. I don't really know why. A lot about D's module system seems to be inspired by how Java's modules work. But javac does do recursive imports as far as I recall. I remember it being one of Sun's marketing points originally: "With java you don't need makefiles! 'javac main.java' is all you need!" Of course, after people got past writing little dancing duke applets they realized that a build tool *was* still needed, so now they have Ant, make redone in XML for some godawful reason. So maybe I answered my own question. Ant may be why Walter decided not to bother putting build-tool functionality into dmd. Perhaps he felt people would inevitably be unsatisfied with whatever limited build tool functionality is built into the compiler. So best just to keep the compiler lean and let external tools take care of it from the beginning. Walter did add one feature to dmd to help writers of such tool, though. "dmd -v main.d" will list all the imports required by main in an easy-to-parse format. --bb
Nov 16 2007
prev sibling parent Alexander Panek <alexander.panek brainsware.org> writes:
On Fri, 16 Nov 2007 13:33:17 +0000 (UTC)
Jarrod <gigantic.midget gmail.com> wrote:

 You can use the bud tool from dsource.org/projects/build to automate
 this.  Then you only need to include the main source file, plus
 libraries to get the same effect:
 bud main.d stuff.lib
 There's also a similar tool called dsss that linux users seem to
 prefer: http://www.dsource.org/projects/dsss


 I have dsss, but I wasn't aware that it could be used to automate
 this process. Alexanders reply also suggested dsss, so I guess I'll
 look into its usage.

Well, that's one of the major reasons why Rebuild (and also bud) has been created. :) -- Alexander Panek <alexander.panek brainsware.org>
Nov 16 2007