www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1830] New: duplicated constants + extern(Windows) = Link error: Previous Definition Different

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1830

           Summary: duplicated constants + extern(Windows) =  Link error:
                    Previous Definition Different
           Product: D
           Version: 1.025
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Keywords: link-failure
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: wbaxter gmail.com


If two modules define the same constants it's usually OK.  But if those
constants are extern(windows) then they will create linker errors.

---link_main.d---
module link_main;
import link_a;
import link_b;
void main()
{
}

---link_a.d---
module link_a;

extern(Windows):
const uint FOO = cast(uint)-1;


---link_b.d---
module link_b;

extern(Windows):
const uint FOO = cast(uint)-1;

---

Build with 
  dmd link_main link_a link_b

And you get:
"""
f:\usr\pkg\d\dmd\bin\..\..\dm\bin\link.exe
link_main+link_a+link_b,,,user32+kernel32/noi;
OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

link_b.obj(link_b)  Offset 000E0H Record Type 0091
 Error 1: Previous Definition Different : _FOO
--- errorlevel 1
"""

If you remove the extern(Windows) lines, it links fine.

This is causing trouble when linking apps that import more than one Windows API
wrapper since most of them stick an extern(Windows): at the top of the file,
which ends up covering all the constants as well as functions.   I'm not even
sure if extern(Windows) has meaning for constants like that, but it certainly
appears to influence how the linker handles them.


-- 
Feb 12 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1830





------- Comment #1 from wbaxter gmail.com  2008-02-12 23:58 -------
Issue 1629 may be related.


-- 
Feb 12 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1830


torhu yahoo.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID




------- Comment #2 from torhu yahoo.com  2008-02-13 17:04 -------
I believe this has to be fixed in the libraries that define constants as
'extern (Windows)'.  Either don't use 'extern (Windows):', or use enums instead
for manifest constants.  If the whole file is 'extern (Windows):', another
option might be to put the constants in 'extern (D)' blocks.

'extern (Windows)' gives the variables C name mangling.  Which I believe is
correct.  Also see issue 1306.


-- 
Feb 13 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1830


wbaxter gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |




------- Comment #3 from wbaxter gmail.com  2008-02-13 17:12 -------
A) Why should the name mangling affect whether the linker says it is a
multiply-defined symbol?  

B) The error message says specifically "previous definition different" which is
simply untrue.  The previous definition was identical.

C) Your workaround #1 is self-contradictory - you say change extern(Windows) to
extern(D), but then later say extern(Windows) is correct for these symbols.

D) Your workaround #2 (change const to enum) requires a change to Phobos,
meaning that at the very least this is a bug against Phobos whose
std.c.windows.windows module uses const rather than enum.


-- 
Feb 13 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1830





------- Comment #4 from torhu yahoo.com  2008-02-13 17:52 -------
(In reply to comment #3)
 A) Why should the name mangling affect whether the linker says it is a
 multiply-defined symbol?  

The regular D name mangling convention adds the module name to the beginning of the mangled symbol, and the type at the end. If FOO in your module was extern (D), it would be mangled as '_D6link_a3FOOk'. For the other module, _D6link_b3FOOk. So there is no conflict when linking. With C name mangling on Windows, it's just _FOO in both cases. That's why the linker complains. To work around this, you can avoid linking with both modules. Since they only define an integer constant, you don't even need to link with any of them. Try it. :) Compiling one or both module into .lib files will work too, at least for your sample and other simple cases.
 
 B) The error message says specifically "previous definition different" which is
 simply untrue.  The previous definition was identical.
 

Might be a linker bug, I don't know. I doesn't matter if they identical or not, they can't have the same mangled name.
 C) Your workaround #1 is self-contradictory - you say change extern(Windows) to
 extern(D), but then later say extern(Windows) is correct for these symbols.
 

 D) Your workaround #2 (change const to enum) requires a change to Phobos,
 meaning that at the very least this is a bug against Phobos whose
 std.c.windows.windows module uses const rather than enum.
 

I'll agree with that. The title is probably wrong then. --
Feb 13 2008
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1830


bugzilla digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |WONTFIX




------- Comment #5 from bugzilla digitalmars.com  2008-03-04 01:57 -------
The problem is that the names for link_a.FOO and link_b.FOO are mangled the
same when using extern(Windows), and are mangled differently when using
extern(D), as the module name is part of the mangled name for D mangling.

This is not fixable, as it is inherent with how Windows name mangling must
work.

The linker message means that there are two definitions of FOO. It doesn't
matter to the linker that they have the same contents - the linker doesn't know
that. The names collide.


-- 
Mar 03 2008