FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

unix pragma(link bug
Goto page 1, 2  Next
 
Post new topic   Reply to topic     Forum Index -> Build
View previous topic :: View next topic  
Author Message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Sat Mar 12, 2005 5:07 pm    Post subject: unix pragma(link bug Reply with quote

When I put:
Code:
pragma(link, dl);


In my code, build simply adds dl.a to my list of files to link. This is very wrong. What it should do is add -ldl to tell the linker to link with the library dl. If that library is in my current dir, then it also needs to add a -L. .(The second period was to end the sentence, the first one is to specify the CWD)

Build seems to be works pretty well so far. Good work!

John
Back to top
View user's profile Send private message Send e-mail AIM Address
Derek Parnell



Joined: 22 Apr 2004
Posts: 408
Location: Melbourne, Australia

PostPosted: Tue Mar 15, 2005 7:50 pm    Post subject: Re: unix pragma(link bug Reply with quote

teqDruid wrote:
When I put:
Code:
pragma(link, dl);


In my code, build simply adds dl.a to my list of files to link. This is very wrong. What it should do is add -ldl to tell the linker to link with the library dl. If that library is in my current dir, then it also needs to add a -L. .(The second period was to end the sentence, the first one is to specify the CWD)


This one may take little while. Currently, build assumes that 'dmd' will take care of invoking the linker and passing the appropriate switches and parameters to it. In other words, build does not directly call the linker. To fix this hassle, I'd have to call the compiler and then, if appropriate, call the linker seperately. I'll add it ot the list and work out if I can do it without losing anything.

teqDruid wrote:
Build seems to be works pretty well so far. Good work!


Thanks. It's been a great way to learn D in a practical sense.
_________________
--
Derek
skype name: derek.j.parnell
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Tue Mar 15, 2005 8:06 pm    Post subject: Reply with quote

Quote:
This one may take little while. Currently, build assumes that 'dmd' will take care of invoking the linker and passing the appropriate switches and parameters to it. In other words, build does not directly call the linker. To fix this hassle, I'd have to call the compiler and then, if appropriate, call the linker seperately. I'll add it ot the list and work out if I can do it without losing anything.


Actually, you can pass arguments to DMD for it to pass to the linker by giving it -L first Ex:
Code:
dmd -L-ldl mycode.d


I was able to coerce build to do some of the things I wanted.... I'm not sure what else I did to it, and it's probably not the best way to do it, but here's the patch.

Code:
Index: Makefile.unix
===================================================================
--- Makefile.unix       (revision 18)
+++ Makefile.unix       (working copy)
@@ -1,5 +1,5 @@
 DMD=dmd
-DFLAGS=-op -release -inline
+DFLAGS=-op -g
 SOURCES=build.d util/pathex_bn.d util/pathex.d source_bn.d util/str.d build_bn.d util/fdt_bn.d util/str_bn.d source.d util/fdt.d

 all: build
Index: build.d
===================================================================
--- build.d     (revision 18)
+++ build.d     (working copy)
@@ -638,6 +638,11 @@
     }
     vCompilerArgs ~= vUnitTest;

+    /+    foreach(char[] lRoot; vImportRoots)
+    {
+        vCompilerArgs ~= vImportPathSwitch ~ lRoot;
+    }+/
+
     char[] lResponseFileName;
     char[] lOutText;
     char[] command;
@@ -854,6 +859,15 @@
 }

 // -------------------------------------------
+void AddLib(char[] lLib)
+// -------------------------------------------
+{
+  if (lLib.length > 0) {
+    vDefaultCompArgs ~= "-L-l" ~ lLib;
+  }
+}
+
+// -------------------------------------------
 void AddLink(char[] pPath)
 // -------------------------------------------
 {
@@ -1191,7 +1205,7 @@
     */
     source.AddRoot          = &AddRoot;
     source.ModulesToIgnore  = &ModulesToIgnore;
-    source.AddLink          = &AddLink;
+    source.AddLink          = &AddLib;
     source.AddBuildDef      = &AddBuildDef;
     source.ActivateVersion  = &ActivateVersion;
     source.IsActiveVersion  = &IsActiveVersion;
@@ -1483,6 +1497,7 @@
                     {
                         char [] lRoot;
                         lRoot = AddRoot(pArg[2..length]);
+                       vDefaultCompArgs ~= vImportPathSwitch ~ lRoot;
                         if(vVerbose) {
                             if (lRoot.length > 0){
                                 writefln("Added root from command line = ?s",lRoot);
@@ -1490,7 +1505,16 @@
                         }
                         break;
                     }
-
+
+                   if (pArg[0..2] == "-l")
+                    {
+                       vDefaultCompArgs ~= "-L" ~ pArg;
+                        if(vVerbose) {
+                                writefln("Added extra link option from command line = ?s",pArg);
+                        }
+                        break;
+                    }
+
                     if (util.str.IsLike(pArg,  cast(dchar[])"-X*"))
                     {
                         // Modules to ignore (eg. -Xmylib)
Index: source.d
===================================================================
--- source.d    (revision 18)
+++ source.d    (working copy)
@@ -587,7 +587,7 @@
                                 }
                             }
                             lPragmaId = util.str.ReplaceChar(lPragmaId, '.', std.path.sep[0]);
-                            lPragmaId = addExt(lPragmaId, LibExt);
+                            //lPragmaId = addExt(lPragmaId, LibExt);
                         }
                         if (AddLink != null)
                             AddLink(lPragmaId);
@@ -932,4 +932,4 @@
     return lBuildNumber;
 }

-
\ No newline at end of file
+
Back to top
View user's profile Send private message Send e-mail AIM Address
funisher



Joined: 09 Mar 2005
Posts: 4

PostPosted: Sat Mar 19, 2005 4:22 am    Post subject: Reply with quote

I implemented this quite easy.

I added a new pragma...

version(build) pragma(lib, GL);

to do this, I just added the following to source.d @ about line 610

Code:
if (lCurrentToken == "lib"){
                lPragmaId = "";
                while ( (lCurrentToken = GetNextToken(pFileText,pPos)) !== null)
                {
                    if ((lCurrentToken != ",") && (lCurrentToken != ")")) {
                        lPragmaId ~= lCurrentToken;
                    }
                    else if (lPragmaId.length > 0) {
                        version(Windows) {
                            // nothing for now
                        }
                        version(Posix) {
                            lPragmaId = "-L-l" ~ lPragmaId;
                        }
                        if (AddLink != null)
                            AddLink(lPragmaId);
                        lPragmaId = "";
                        if (lCurrentToken == ")"){
                            break;}
                    }
                }
            }


easy. Hope that helps.

EDIT: I just realized. I should probably thank you for build! It's quite a wonderful program! Seriously, it is...

Also, the reason why I added a new pragma is because my program usues both external libs -lGL, etc. and local libs as well ODE.a -- so both are needed.
Back to top
View user's profile Send private message
Derek Parnell



Joined: 22 Apr 2004
Posts: 408
Location: Melbourne, Australia

PostPosted: Sat Mar 19, 2005 6:36 pm    Post subject: Reply with quote

funisher wrote:
I implemented this quite easy.

I added a new pragma...

version(build) pragma(lib, GL);


I've upgraded the pragma 'link' and it should cater for what you guys are doing. If I've still missed the idea, just let me know and I'll see what I can do.

New release should be out in 48 hours. I'm adding a few new pragmas so I can build 'empire'. Currently it has a complex makefile that I'm sure I can do better Very Happy
_________________
--
Derek
skype name: derek.j.parnell
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Sat May 21, 2005 12:17 pm    Post subject: Reply with quote

So I've just downloaded the latest Build (2.07) since posting about this (I've just been using an old one with my patches) and this is still an issue. I'm not sure if it wasn't an issue at some point, but now when I put:
Code:
version(build) { pragma(lib, dl); }

in my code, it still just puts dl.a in my list of link files.

As I've said before, this is very wrong. Whenever build encounters a link pragma, it should add the following to the dmd call:
Code:
-L-ldl -L-L.


This way, dl is added as a library, and the current directory is added to the search path, so if dl.a is in the current path, it will be used.
Back to top
View user's profile Send private message Send e-mail AIM Address
Derek Parnell



Joined: 22 Apr 2004
Posts: 408
Location: Melbourne, Australia

PostPosted: Sat May 21, 2005 11:51 pm    Post subject: Reply with quote

teqdruid wrote:
So I've just downloaded the latest Build (2.07) since posting about this (I've just been using an old one with my patches) and this is still an issue. I'm not sure if it wasn't an issue at some point, but now when I put:
Code:
version(build) { pragma(lib, dl); }

in my code, it still just puts dl.a in my list of link files.

As I've said before, this is very wrong. Whenever build encounters a link pragma, it should add the following to the dmd call:
Code:
-L-ldl -L-L.


This way, dl is added as a library, and the current directory is added to the search path, so if dl.a is in the current path, it will be used.

May I respectfully disagree with you. The names of libraries and the locations of libraries are distinct things and thus there is a mechanism to name which library you need (the pragma) and another mechanism to identify the location of libraries (the LIB environment symbol).

Can I suggest that you add "." to the list of locations in the LIB symbol, or add "CMDLINE=-L-L." to your build configuration file.

I need more evidence that this idea is a good one before I'll incorporate it.
_________________
--
Derek
skype name: derek.j.parnell
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Sun May 22, 2005 12:13 am    Post subject: Reply with quote

Quote:
The names of libraries and the locations of libraries are distinct things and thus there is a mechanism to name which library you need (the pragma) and another mechanism to identify the location of libraries (the LIB environment symbol).


I completely agree with you. The way it works now, only a static library in the current directory can be used. The code I gave was to emulate this behavior in addition to correcting it. I would prefer build just using "-L-ldl" (for the dl library) and not specifying the location. My problem with the current behaviour is that it just adds dl.a to the list of things to link. Because of this, gcc can't find the dl library. I think that we are in agreement, but this is simply a bug.
Back to top
View user's profile Send private message Send e-mail AIM Address
Derek Parnell



Joined: 22 Apr 2004
Posts: 408
Location: Melbourne, Australia

PostPosted: Sun May 22, 2005 5:56 pm    Post subject: Reply with quote

teqdruid wrote:
Quote:
The names of libraries and the locations of libraries are distinct things and thus there is a mechanism to name which library you need (the pragma) and another mechanism to identify the location of libraries (the LIB environment symbol).


I completely agree with you.

Great! Then I don't have do anything.

teqdruid wrote:
The way it works now, only a static library in the current directory can be used.
The way what works now? Build? gdc? gcc? Unix? And this pragma was only ever designed to work with static libraries and not dynamiclly loaded libraries.
teqdruid wrote:
The code I gave was to emulate this behavior in addition to correcting it.
Which behavior? Only working with static libraries?
teqdruid wrote:
I would prefer build just using "-L-ldl" (for the dl library) and not specifying the location. My problem with the current behaviour is that it just adds dl.a to the list of things to link.
Because that's all that is needed. The pragma allows you to list the names of the static libraries you want to have on the linker command line. It is not designed to supply the locations of those libraries as well. To do that you need to use the existing mechanisms.
teqdruid wrote:
Because of this, gcc can't find the dl library.
Because of what? Just adding the name and not the location?
teqdruid wrote:
I think that we are in agreement, but this is simply a bug.
A bug where? In Build? gdc? gcc?

I really don't have a handle on this problem yet. I tried to reproduce this in my Windows environment and I had no troubles. I created a library in the same directory as the application, used the pragma, and it added the name of the library on the linker command line and found the library and linked correctly.
_________________
--
Derek
skype name: derek.j.parnell
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Sun May 22, 2005 6:16 pm    Post subject: Reply with quote

OK... Let's start from scratch. In linux, when I want to use a library, say the dl library, I specify the name of the library to gcc using -ldl. Gcc then takes care of finding this library. Optionally, I can add a path for gcc to search for the library in. As such, when I compile mango with dmd, I have to give dmd the switch -L-ldl, so it passes -ldl to gcc.

It is my understanding that when I put pragma(link, dl) in a program, build is supposed to tell gcc (via dmd) to link in the library dl. In order to do this build needs to run dmd with the same switch that I do by hand: -L-ldl. As of version 2.07 of build, it does not do this. Instead, build simply adds dl.a to the dmd command. In turn, dmd adds dl.a to the gcc command. This is telling gcc to link in the dl.a library in the current directory. As a result, unless I happen to have dl.a in my current directory (and since it is a system library, I do not) gcc is unable to find it. Unless I misunderstand what pragma(link) is supposed to do, this behaviour is clearly wrong.

I apologize if I was unclear before. Are we understanding each other now?
Back to top
View user's profile Send private message Send e-mail AIM Address
Derek Parnell



Joined: 22 Apr 2004
Posts: 408
Location: Melbourne, Australia

PostPosted: Sun May 22, 2005 6:34 pm    Post subject: Reply with quote

teqdruid wrote:
I apologize if I was unclear before. Are we understanding each other now?

I don't think so. Embarassed
It would seem that the Windows tools (dmd,optlink) work differently to the unix tools. In Windows, if I use " pragma(link, dl)" in my source code, Build will add "dl.lib" to the dmd command line and in turn, dmd passes "dl.lib" to optlink and then optlink scans the directories named in the LIB environment symbol and the current directory to find the library.

It seems that you are saying the the unix linker does not use the LIB environment symbol and instead one must explicitly tell it the location of each library on the command line.

Also, it seems that you are saying that what Build needs to do is to pass the library name to dmd as a Linker option and not just a library name to DMD. Also, Build must locate the library and also tell the linker where that library is.

So to summarize, given that Build finds "pragma(link, dl);" you want the following actions to occur (non-Windows only) ...

* scan for the library's directory
* pass -L-ldl to dmd
* pass -L-L<libdir> to dmd

but in Windows versions of Build all I do is ...

* pass dl.lib to dmd

Have I got it now?
_________________
--
Derek
skype name: derek.j.parnell
Back to top
View user's profile Send private message
Carlos



Joined: 19 Mar 2004
Posts: 396
Location: Canyon, TX

PostPosted: Sun May 22, 2005 8:08 pm    Post subject: Reply with quote

Derek Parnell wrote:
So to summarize, given that Build finds "pragma(link, dl);" you want the following actions to occur (non-Windows only) ...

* scan for the library's directory
* pass -L-ldl to dmd
* pass -L-L<libdir> to dmd


How would it work when we're not referring to a system's library? I mean, what if the library I want to link is actually in the current directory? For that specific case, the current behavior is ok.
Back to top
View user's profile Send private message Yahoo Messenger MSN Messenger
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Sun May 22, 2005 8:40 pm    Post subject: Reply with quote

The linux version of Build might support a command-line flag to support this behaviour. For example, I can imagine a -LIBPATH flag or similar. This would be passed to the linker in order to resolve such issues.

If you don't specify the flag, nothing changes in the behaviour.
Back to top
View user's profile Send private message
teqdruid



Joined: 11 May 2004
Posts: 390
Location: UMD

PostPosted: Mon May 23, 2005 12:35 am    Post subject: Reply with quote

Quote:
So to summarize, given that Build finds "pragma(link, dl);" you want the following actions to occur (non-Windows only) ...

* scan for the library's directory
* pass -L-ldl to dmd
* pass -L-L<libdir> to dmd

but in Windows versions of Build all I do is ...

* pass dl.lib to dmd

Have I got it now?


Closer, but not quite. GCC will search for a library, if all you give it is the name (and I'm not talking about the file name). So when build encounters "pragma(link, dl);" all it needs to do is pass -L-ldl to DMD. Since GCC will search for the library, build doesn't need to. So basically scratch off the first and third directions in your above list.

In the specific case that the library you want to link to is in the current directory, all one needs to do is add -L-L. (the dot's for the current dir) to build's command line (or config file), and build will pass it on to dmd, and dmd will pass -L. to gcc, and gcc will add the current dir to it's search path for libraries.

It seems the difference between linkers isn't in behavior but in syntax. Given a file with a .lib extension, the windows linker will search for it. Given a file with a .a extension, gcc won't search- you have to tell it a different way, with the -l switch. The idea behind the way gcc does it is that if you specify a file, you need to actually specify the entire file name and path (or let it assume it's in the current dir.) If you want GCC to find it for you, instead of telling it that you want to include a file, you tell it to link in a library (using the -l switch) and give it the library's name. It's also of note that on linux, the dl library which I've been talking about is not called dl.a. Most libraries are not. The general format is lib<name>.a, so the dl library is a file called libdl.a. The naming scheme gets more complicated with shared objects to support versioning. But because GCC really only wants/needs to know the name, it doesn't really make any difference to the programmer.

<OT> I was totally unaware that this was how the Windows linker worked (I've never done any Windows programming.) The behavior doesn't seem obvious to me, and seems an inconsistent syntax; I don't like it, but then it's things like that keep me away from Windows programming... that and a horrific command line. </OT>
Back to top
View user's profile Send private message Send e-mail AIM Address
Derek Parnell



Joined: 22 Apr 2004
Posts: 408
Location: Melbourne, Australia

PostPosted: Mon May 23, 2005 1:09 am    Post subject: Reply with quote

teqdruid wrote:
Quote:
So to summarize, given that Build finds "pragma(link, dl);" you want the following actions to occur (non-Windows only) ...

* scan for the library's directory
* pass -L-ldl to dmd
* pass -L-L<libdir> to dmd

but in Windows versions of Build all I do is ...

* pass dl.lib to dmd

Have I got it now?


Closer, but not quite.

I must be having a blonde day. Please be patient with my inane questions... Confused

teqdruid wrote:
GCC will search for a library, if all you give it is the name (and I'm not talking about the file name).

When you say "give it the name" do you mean the fully specified path and file name; in other words, one that starts with a "/"? Not a relative path or just the file name itself? If that's the case, why is GCC searching as you just told it exactly where the file is? If that is not the case, what do you really mean by "I'm not talking about the file name"? Please give me some examples to help me understand your terminalogy.

teqdruid wrote:
So when build encounters "pragma(link, dl);" all it needs to do is pass -L-ldl to DMD. Since GCC will search for the library, build doesn't need to. So basically scratch off the first and third directions in your above list.

How does GCC search for the library file called "dl.a"? Does it do an exhustive search of the file system? Is there default locations in which libraries are expected to live? Is there a pre-defined list of directories that it searches through? I don't understand it otherwise.

teqdruid wrote:

In the specific case that the library you want to link to is in the current directory, all one needs to do is add -L-L. (the dot's for the current dir) to build's command line (or config file), and build will pass it on to dmd, and dmd will pass -L. to gcc, and gcc will add the current dir to it's search path for libraries.

Is this an exception to GCC's searching algorithm? In ther words, if the library was somewhere else GCC would find it but if its in the current directory it won't find it unless you tell it to look there. Seems weird to me.
teqdruid wrote:


It seems the difference between linkers isn't in behavior but in syntax.

It seems different to me. To me it sounds like the behaviour is quite different and so is the syntax.
teqdruid wrote:

Given a file with a .lib extension, the windows linker will search for it. Given a file with a .a extension, gcc won't search

Exactly - this is different behavour.
teqdruid wrote:

- you have to tell it a different way, with the -l switch.

The windows linker searches a list of possible locations for libraries. The location list is stored in the LIB environment symbol.

Where does the location list exist for GCC? It sounds like it exists only on the linker command line. This must be inconvenient.

teqdruid wrote:
The idea behind the way gcc does it is that if you specify a file, you need to actually specify the entire file name and path (or let it assume it's in the current dir.)

Hold on, you said before I had to do special processing if the library lives in the current directory. Which is it?
teqdruid wrote:
If you want GCC to find it for you, instead of telling it that you want to include a file, you tell it to link in a library (using the -l switch) and give it the library's name.
Sames as windows, except you don't prefix the library name with "-l".

teqdruid wrote:
It's also of note that on linux, the dl library which I've been talking about is not called dl.a. Most libraries are not. The general format is lib<name>.a, so the dl library is a file called libdl.a. The naming scheme gets more complicated with shared objects to support versioning. But because GCC really only wants/needs to know the name, it doesn't really make any difference to the programmer.

So are you saying that Build doesn't have to worry about the "lib" prefix convention?
teqdruid wrote:

<OT> I was totally unaware that this was how the Windows linker worked (I've never done any Windows programming.) The behavior doesn't seem obvious to me, and seems an inconsistent syntax; I don't like it, but then it's things like that keep me away from Windows programming... that and a horrific command line. </OT>

Huh? What is so horrific about ...
Code:

dmd myapp.d mylib.lib

Oh well, each to their own. It don't matter.
_________________
--
Derek
skype name: derek.j.parnell
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Build All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group