24

I have a set of statically-compiled libraries, with fairly deep-running dependencies between the libraries. For example, the executable X uses libraries A and B, A uses library C, and B uses libraries C and D:

X -> A
     A -> C
X -> B
     B -> C
     B -> D

When I link X with A and B, I don't want to get errors if C and D were not also added to the list of libraries—the fact that A and B use these libraries internally is an implementation detail that X should not need to know about. Also, when new dependencies are added anywhere in the dependency tree, the project file of any program that uses A or B would have to be reconfigured. For a deep dependency tree, the list of required libraries can become really long and hard to maintain.

So, I am using the "Additional Dependencies" setting of the Librarian section in the A project, adding C.lib. And in the same section of B's project, I add C.lib and D.lib. The effect of this is that the librarian bundles C.lib into A.lib, and C.lib and D.lib into B.lib.

When I link X, however, both A.lib and B.lib contain their own copy of C.lib. This leads to tons of warnings along the lines of

A.lib(c.obj) : warning LNK4006 "symbol" (_symbol) already defined in B.lib(c.obj); second definition ignored.

How can I accomplish this without getting warnings? Is there a way to simply disable the warning, or is there a better way?

EDIT: I have seen more than one answer suggesting that, for the lack of a better alternative, I simply disable the warning. Well, this is part of the problem: I don't even know how to disable it!

abatishchev
  • 98,240
  • 88
  • 296
  • 433
flodin
  • 5,215
  • 4
  • 26
  • 39

9 Answers9

15

As far as I know you can't disable linker warnings. However, you can ignore some of them, using command line parameter of linker eg. /ignore:4006

Put it in your project properties under linker->command line setting (don't remember exact location).

Also read this:

Link /ignore

MSDN Forum - hiding LNK warnings

Wacek

Wacek
  • 4,326
  • 2
  • 19
  • 28
  • Cool. I quickly glanced at msdn documentation for link.exe and it was not there. Still, keep in mind that disabling warnings is not a cure. It's a band-aid. Band-aids are certainly useful but... – Tomek Szpakowicz Feb 28 '09 at 11:21
9

Update If you can build all involved project in single solution, try this:

  • Put all project in one sln.
  • Remove all references to static libraries from projects' linker or librarian properties.
  • There is "Project Dependencies..." option in context menu for each project in Solution Explorer. Use it to define dependencies between project.

It should work. It doesn't invalidate anything I said before, the basic model of building C/C++ programs stays the same. VS (at least 2005 and newer) is simply smart enough to add all needed static libraries to linker command line. You can see it in project properties.

Of course this method won't help if you need to use already compiled static libraries. Then you need to add them all to exe or dll project that directly or indirectly uses them.


I don't think you can do anything about that. You should remove references to other static libs from static libs projects and add all needed static libs projects as dependences of exe or dll projects. You will just have to live with fact that any project that includes A.lib or B.lib also needs to include C.lib.

As an alternative you can turn your libraries into dlls which provide a richer model.

Statically compiled libraries simply aren't real libraries with dependency information, etc, like dlls. See how, when you build them, you don't really need to provide libraries they depend on? Headers are all that's needed. See? You can't even really say static libraries depend on something.

Static library is just an archive of compiled and not yet linked object code. It's not consistent whole. Each object file is compiled separately and remains separate entity inside the library. Linking happens when you build exe or dll. That's when you need to provide all object code. That's when all the symbol and dependency resolving happens.

If you add other static libraries to static library dependencies, librarian will simply copy all code together. Then, when building exe, linker will give you lots of warnings about duplicate symbols. You might be able to block those warnings (I don't know how) but be careful. It may conceal real problems like real duplicate symbols with differing definitions. And if you have static data defined in libraries, it probably won't work anyway.

Tomek Szpakowicz
  • 14,063
  • 3
  • 33
  • 55
  • 1
    I understand what you are saying about the technicalities of libraries, but regardless I think I have a real, sensible use case. There are ways of handling it that does not have the problems you describe, such as silently throwing away exact duplicates of obj files. – flodin Feb 26 '09 at 07:47
  • Also, you say I can block the warning, but how? That is also part of my original question. Even if we sidestep the problems you mention, there seems to be just no way of disabling it. Neither lib.exe nor link.exe accept the /Wd:4006 switch. – flodin Feb 26 '09 at 07:52
  • I don't know how to disable those warning. I don't think I've ever needed to do that. As a rule I try to find the real cause of warnings and eliminate it. I updated my answer accordingly. – Tomek Szpakowicz Feb 26 '09 at 22:28
4

Microsoft (R) Incremental Linker Version 9.00.x (link.exe) knows argument /ignore:4006

abatishchev
  • 98,240
  • 88
  • 296
  • 433
3

You could create one library which contains A, B, C & D and then link X against that.

Since it's a library, only object modules which are actually referenced will get linked into the final executable.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • If I do that, the warning is issued when I build that library instead. Neither LINK.EXE nor LIB.EXE appear to take any command-line switches that allow me to disable the warning. – flodin Feb 25 '09 at 07:05
  • When you build the A and B components, are you linking in C and D then? Or are you linking them in only at the final link step to build the library? – Ferruccio Feb 25 '09 at 12:15
  • Yes, that's what the "Additional Dependencies" setting does. Specifying C.lib in that setting in the project configuration for A.lib, causes VC to link C.lib into A.lib. – flodin Feb 26 '09 at 07:37
  • 2
    @flodin: Not "link". Rather "include" or "merge". Linking is an entirely different operation done by LINK.EXE to produce exe or dll. Static libs are not linked in that sense. – Tomek Szpakowicz Mar 12 '09 at 01:34
1

Note that one way of getting this warning is to define a member function in a header without the inline statement:

// Foo.h

class Foo
{
    void someFunction();
};

void Foo:someFunction() // Warning!  - should be "inline void Foo::someFunction()"
{
    // do stuff
}
Mark
  • 11
  • 1
0

The problem is you are not localizing library C's symbols. So you have a ODR violation when you link in A and B. You need to have a way to make these private. By default all symbols are exported. One way to do this is to have a special linker definition file for both A and B that explicitly mention which files need to be exported.

[1] ODR = One Definition Rule.

dirkgently
  • 108,024
  • 16
  • 131
  • 187
0

I think the best course of action here will be to ignore/disable the linker warnings(LNK4006) since C.lib needs to be part of both A.Lib and B.lib and A.Lib does not need to know that B.lib itself uses C.Lib.

Sandeep Datta
  • 28,607
  • 15
  • 70
  • 90
-1

This may not fix your link error, but it might help with your dependency tree issue.

What I do, is just use a #pragma to include a lib in the .cpp file that needs it. For example:

#pragma comment(lib, "wsock32") 

Like I said, I'm not sure it would keep the symbols in that object file, I'd have to whip up an example to try it out.

LarryF
  • 4,925
  • 4
  • 32
  • 40
  • Doing that is pretty much the same as specifying wsock32.lib in the "additional dependencies" section of the library. I don't have a problem getting the dependencies in there, the problem is doing it while simultaneously avoiding the linker warning. – flodin Feb 26 '09 at 07:39
  • Also if you are doing any testing, I don't think wsock32.lib is a good example because it is just a DLL import library that doesn't contain any code. It won't reproduce the warnings. – flodin Feb 26 '09 at 07:54
  • Yea, I was just using it as an example. And yea, this is the same as adding it to the additional dependencies, but you made mention that even that was kind of a nightmare to keep organized, so I thought this might help. – LarryF Feb 26 '09 at 18:47
-4

Poor flodin seems frustrated that nobody will explain how to disable the linker warnings. Well, I've had a similar problem, and for years I have simply lived with the fact that several hundred warnings were displayed. Now, however, thanks to the info from Link /ignore, I figured out how to disable the linker warnings.

I'm using Visual Studio 2008. In Project -> Settings -> Configuration Properties -> Librarian -> Command Line -> Additional Options, I added "/ignore:4006" (without the quotes). Now my warnings are gone!

birch
  • 1