www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Link errors with lib files

reply "John C" <johnch_atms hotmail.com> writes:
Normally I just compile all my source files on the command line, but I'm 
attempting to make a static library and am getting errors at link time. I've 
searched the archives to no avail. Can anyone help?

First, I have a source file called sample.d, as follows:

--------sample.d--------
module sample;

class Test {

    char[] getMessage() {
        return "Hello, World";
    }

}
-------------------------

Next, I generate an .obj file and a .lib file like so:

    dmd sample.d -c
    lib -c sample.lib sample.obj

Which gives me a static library called "sample.lib". Now I want to use it in 
a program, which is where things start going wrong.

Obviously I don't want sample.d to get compiled into my program, rather 
sample.lib, so (taking a leaf out of how phobos is built) I created a 
version of sample.d without definitions to use as an import module:

--------sample2.d--------
module sample;

class Test {

    char[] getMessage();

}
--------------------------

Then, my app's main source file, which imports the "sample" module:

--------program.d--------
module program;

import sample;

int main() {
    Test test = new Test;
    char[] msg = test.getMessage();

    return 0;
}
--------------------------

Finally, I put it all together on the command line:

    dmd program.d sample2.d sample.lib

This results in the following errors:

    Error1: Previous Definition Different : __init_6sample4Test
    Error1: Previous Definition Different : __Class_6sample4Test
    Error1: Previous Definition Different : __vtbl_6sample4Test

Of course, if I substitute "sample2.d" with "sample.d" on the cmd line the 
errors are eliminated, but the source is compiled into my program, which is 
not what I want.

So, what's going on? Does anyone have a solution?

Cheers, John. 
Nov 15 2005
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"John C" <johnch_atms hotmail.com> wrote in message 
news:dlceog$1gqq$1 digitaldaemon.com...
 So, what's going on? Does anyone have a solution?
Don't compile sample2.d. Just import it from program.d. ;)
Nov 15 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 15 Nov 2005 10:54:07 -0000, John C wrote:

 Normally I just compile all my source files on the command line, but I'm 
 attempting to make a static library and am getting errors at link time. I've 
 searched the archives to no avail. Can anyone help?
 
 First, I have a source file called sample.d, as follows:
 
 --------sample.d--------
 module sample;
 
 class Test {
 
     char[] getMessage() {
         return "Hello, World";
     }
 
 }
 -------------------------
 
 Next, I generate an .obj file and a .lib file like so:
 
     dmd sample.d -c
     lib -c sample.lib sample.obj
 
 Which gives me a static library called "sample.lib". Now I want to use it in 
 a program, which is where things start going wrong.
 
 Obviously I don't want sample.d to get compiled into my program, rather 
 sample.lib, so (taking a leaf out of how phobos is built) I created a 
 version of sample.d without definitions to use as an import module:
 
 --------sample2.d--------
 module sample;
 
 class Test {
 
     char[] getMessage();
 
 }
 --------------------------
 
 Then, my app's main source file, which imports the "sample" module:
 
 --------program.d--------
 module program;
 
 import sample;
 
 int main() {
     Test test = new Test;
     char[] msg = test.getMessage();
 
     return 0;
 }
 --------------------------
 
 Finally, I put it all together on the command line:
 
     dmd program.d sample2.d sample.lib
 
 This results in the following errors:
 
     Error1: Previous Definition Different : __init_6sample4Test
     Error1: Previous Definition Different : __Class_6sample4Test
     Error1: Previous Definition Different : __vtbl_6sample4Test
 
 Of course, if I substitute "sample2.d" with "sample.d" on the cmd line the 
 errors are eliminated, but the source is compiled into my program, which is 
 not what I want.
 
 So, what's going on? Does anyone have a solution?
You've almost got it right. First, rename sample2.d to sample.d, obviously keeping the original sample.d (the one with the implementation code) in a separate directory for safe keeping. Next, compile as dmd program.d sample.lib This will get the compiler to import sample.d (just declarations) but not compile it, and the linker will look into sample.lib to resolve reference to the implementation details. -- Derek Parnell Melbourne, Australia 16/11/2005 12:49:14 AM
Nov 15 2005
next sibling parent "John C" <johnch_atms hotmail.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message 
news:1gx6rumzbj97o$.17079cha22x9a.dlg 40tude.net...
 On Tue, 15 Nov 2005 10:54:07 -0000, John C wrote:

 Normally I just compile all my source files on the command line, but I'm
 attempting to make a static library and am getting errors at link time. 
 I've
 searched the archives to no avail. Can anyone help?

 First, I have a source file called sample.d, as follows:

 --------sample.d--------
 module sample;

 class Test {

     char[] getMessage() {
         return "Hello, World";
     }

 }
 -------------------------

 Next, I generate an .obj file and a .lib file like so:

     dmd sample.d -c
     lib -c sample.lib sample.obj

 Which gives me a static library called "sample.lib". Now I want to use it 
 in
 a program, which is where things start going wrong.

 Obviously I don't want sample.d to get compiled into my program, rather
 sample.lib, so (taking a leaf out of how phobos is built) I created a
 version of sample.d without definitions to use as an import module:

 --------sample2.d--------
 module sample;

 class Test {

     char[] getMessage();

 }
 --------------------------

 Then, my app's main source file, which imports the "sample" module:

 --------program.d--------
 module program;

 import sample;

 int main() {
     Test test = new Test;
     char[] msg = test.getMessage();

     return 0;
 }
 --------------------------

 Finally, I put it all together on the command line:

     dmd program.d sample2.d sample.lib

 This results in the following errors:

     Error1: Previous Definition Different : __init_6sample4Test
     Error1: Previous Definition Different : __Class_6sample4Test
     Error1: Previous Definition Different : __vtbl_6sample4Test

 Of course, if I substitute "sample2.d" with "sample.d" on the cmd line 
 the
 errors are eliminated, but the source is compiled into my program, which 
 is
 not what I want.

 So, what's going on? Does anyone have a solution?
You've almost got it right. First, rename sample2.d to sample.d, obviously keeping the original sample.d (the one with the implementation code) in a separate directory for safe keeping. Next, compile as dmd program.d sample.lib
Thanks Derek and Jarrett. Now I also realise the usefulness of the -I import path.
 This will get the compiler to import sample.d (just declarations) but not
 compile it, and the linker will look into sample.lib to resolve reference
 to the implementation details.

 -- 
 Derek Parnell
 Melbourne, Australia
 16/11/2005 12:49:14 AM 
Nov 15 2005
prev sibling parent reply "John C" <johnch_atms hotmail.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message 
news:1gx6rumzbj97o$.17079cha22x9a.dlg 40tude.net...
 On Tue, 15 Nov 2005 10:54:07 -0000, John C wrote:

 Normally I just compile all my source files on the command line, but I'm
 attempting to make a static library and am getting errors at link time. 
 I've
 searched the archives to no avail. Can anyone help?

 First, I have a source file called sample.d, as follows:

 --------sample.d--------
 module sample;

 class Test {

     char[] getMessage() {
         return "Hello, World";
     }

 }
 -------------------------

 Next, I generate an .obj file and a .lib file like so:

     dmd sample.d -c
     lib -c sample.lib sample.obj

 Which gives me a static library called "sample.lib". Now I want to use it 
 in
 a program, which is where things start going wrong.

 Obviously I don't want sample.d to get compiled into my program, rather
 sample.lib, so (taking a leaf out of how phobos is built) I created a
 version of sample.d without definitions to use as an import module:

 --------sample2.d--------
 module sample;

 class Test {

     char[] getMessage();

 }
 --------------------------

 Then, my app's main source file, which imports the "sample" module:

 --------program.d--------
 module program;

 import sample;

 int main() {
     Test test = new Test;
     char[] msg = test.getMessage();

     return 0;
 }
 --------------------------

 Finally, I put it all together on the command line:

     dmd program.d sample2.d sample.lib

 This results in the following errors:

     Error1: Previous Definition Different : __init_6sample4Test
     Error1: Previous Definition Different : __Class_6sample4Test
     Error1: Previous Definition Different : __vtbl_6sample4Test

 Of course, if I substitute "sample2.d" with "sample.d" on the cmd line 
 the
 errors are eliminated, but the source is compiled into my program, which 
 is
 not what I want.

 So, what's going on? Does anyone have a solution?
You've almost got it right. First, rename sample2.d to sample.d, obviously keeping the original sample.d (the one with the implementation code) in a separate directory for safe keeping. Next, compile as dmd program.d sample.lib This will get the compiler to import sample.d (just declarations) but not compile it, and the linker will look into sample.lib to resolve reference to the implementation details.
Now I'm running into all sorts of problems with templates not getting compiled properly into my lib file. I've read around the issue, tried to apply the kludge from http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/23701 but that had no effect. In "collections.d" I have a couple of classes: interface IComparer(T) { ... } class Comparer(T) : IComparer!(T) { ... } // a default implementation of IComparer(T) interface IDictionary(TKey, TValue) { ... } class Dictionary(TKey, TValue) : IDictionary!(TKey, TValue) { this(IComparer comparer = null) { // null by default, so users can supply their own specialised comparer if (comparer is null) comparer = new Comparer!(TKey); ... } } In "dom.d" I have a specialisation of IComparer(T) and a class that instantiates it. import collections, msxml; class InterfaceComparer(T) : IComparer!(T) { ... } class XmlNode { ... } class XmlNodeFactory { static IDictionary!(IXMLDOMNode, XmlNode) nodeTable_; // msxml defines interface IXMLDOMNode. static this() { nodeTable_ = new Dictionary!(IXMLDOMNode, XmlNode)(new InterfaceComparer!(IXMLDOMNode)); } ... } These then are compiled to msxml.obj, collections.obj and dom.obj, which are in turn compiled into dom.lib, without errors. But when I link with dom.lib I'm told: Symbol Undefined __Class_11collections29Comparer_C5msxml11IXMLDOMNode8Comparer I've narrowed the issue down to collections.d, and this line: if (comparer is null) comparer = new Comparer!(TKey); which translates to if (comparer is null) comparer = new Comparer!(IXMLDOMNode); If I comment out the above line, everything links fine. But my Dictionary class relies on it (unless the user passes their own specialised comparer). I thought perhaps it needed a definition of IXMLDOMNode, but importing the appropriate module didn't help. The suggested workaround is to add something like "int foo;" to one file, and "int* pfoo = &foo;" to another. Which should go where? msxml.d, collections.d or dom.d? I've tried all variations, without success.
 -- 
 Derek Parnell
 Melbourne, Australia
 16/11/2005 12:49:14 AM 
Nov 17 2005
next sibling parent Carlos Santander <csantander619 gmail.com> writes:
John C escribió:
 
 Now I'm running into all sorts of problems with templates not getting 
 compiled properly into my lib file. I've read around the issue, tried to 
 apply the kludge from 
 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/23701 but that had 
 no effect.
 
 ...
 
 The suggested workaround is to add something like "int foo;" to one file, 
 and "int* pfoo = &foo;" to another. Which should go where? msxml.d, 
 collections.d or dom.d? I've tried all variations, without success.
 
Same here with dcouple 0.2 on Windows. I don't know where to put what. Any help? -- Carlos Santander Bernal
Nov 19 2005
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
My first suggestion is you have too many files and too much code in the
files to figure out what's going wrong. Try to cut things down as far as
possible.
Nov 24 2005