Resolving linker warning LNK4221

While cleaning up code warnings I came across LNK4221: “xxx.obj: no public symbols found; archive member will be inaccessible.”. The message does point out the culprit obj file, but not much more. both the documentation and a knowledge base article don’t shed much additional light.  Generally, it seems i’m not the only one who couldn’t readily identify the problem source.  although useful discussions do exist, they’re hidden deep below other search results –  so I figured the issue is worth a post.

‘Public symbols’ basically means stuff that the linker can use: functions that can be called, classes that can be instantiated or variables to referenced.   (note, we mean compiled functions or classes, as the linker doesn’t  do compilation). So far I came across two scenarios that result in compilation units lacking any of those:

(1) A template-only file, typically a header file (since VC++ does not conform to the standard regarding the export keyword).    Maybe a class-wizard created a stub cpp for you, or maybe – out of habit – you did it yourself, but there’s really nothing to compile here. All you want is the header to be included wherever the templates are used – the right solution is to discard the cpp altogether.

(2) A cpp that contains real stuff, but one that is compiled only in certain configurations – e.g. debugging facilities, surrounded by #ifdef _DEBUG’s.    Can’t say I have an elegant solution for this one – if you’re obliged to zero-warning compilation, you can add to the file a dummy variable (or other symbol) that’s not conditionally compiled.  While it may add some miliseconds to link time, rest assured it would be optimized away and have zero effect in production builds.

Advertisements
This entry was posted in VC++ and tagged . Bookmark the permalink.

2 Responses to Resolving linker warning LNK4221

  1. khurram says:

    Hey I really need your help. I have a situation where i have a static lib that i am making in vs2008. I have a bare bones .h file and .cpp file that has all my code. In there are make reference to some third party lib that i am using functions from. I used the lib.exe to strip all uneeded obj files and made a new smaller lib file that i am using in my static lib project. However i can’t seem to get rid of those 4221 or 4006 linker warnings. I also added that lib under the librarian. At this point I am at a total loss. I have no idea what else to do. any help would be greatly appreciated.

  2. Ofek Shilon says:

    Khurram, not sure I completely understand the situation yet but here are my 2c:
    If i understand correctly the 4221 warning comes from the compilation of your own library (which references a 3rd party one). So :
    (1) if you want to cut away unused functions there’s no need to use external tools: compile with /Gy (http://msdn.microsoft.com/en-us/library/xsa71f43%28VS.80%29.aspx) and link with /OPT:REF (http://msdn.microsoft.com/en-us/library/bxwfs976%28VS.80%29.aspx). That would do much better than removing redundant obj files – that would remove single redundant functions.
    (2) This decimation probably has nothing to do with the warnings you receive. The 4221 warning should come with a file name – have you inspected it? Are you absolutely *certain* you’re actually using these functions? try commenting some of them and see if it still links. if it does – the linker resolves the definitions elsewhere – you should find where.
    (3) same process essentially goes for warning 4006.
    Hope this helps.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s