I'm trying to compile Python on Windows in an unusual context, and running into this problem:
a.o : error LNK2019: unresolved external symbol strnicmp referenced in function connection_clear
Okay, so I'm not linking in the proper library containing strnicmp
, which one is that? Couldn't find it, so I wrote a script to search through every .lib
file on my entire hard disk, run dumpbin /exports
on all of them, and collect the results.
And the result was that as far as this process could tell, there is no library containing strnicmp
.
A bit more searching led me to https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strnicmp-wcsnicmp?view=msvc-170
The Microsoft-specific function names strnicmp and wcsnicmp are deprecated aliases for the _strnicmp and _wcsnicmp functions.
On the face of it, that would seem to be the beginning of an explanation. Neither the linker nor I nor my search script can find strnicmp
because at the object code level, it doesn't exist; it's probably just a #define
in some header file, though that raises the question of why this was not working on the source file containing connection_clear
.
Just to make sure, I wrote a test program.
(c1) R:\>type call-strnicmp.c
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc == 2 && !strnicmp(argv[1], "foo", 3)) puts("you said foo");
else
puts("you did not say foo");
return 0;
}
(c1) R:\>cl call-strnicmp.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.31.31104 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
call-strnicmp.c
Microsoft (R) Incremental Linker Version 14.31.31104.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:call-strnicmp.exe
call-strnicmp.obj
(c1) R:\>call-strnicmp.exe foo
you said foo
Okay, so strnicmp
is being called correctly, presumably via the aforementioned header. Just to make doubly sure:
(c1) R:\>dumpbin /symbols call-strnicmp.obj
Microsoft (R) COFF/PE Dumper Version 14.31.31104.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file call-strnicmp.obj
File Type: COFF OBJECT
COFF SYMBOL TABLE
000 01047980 ABS notype Static | @comp.id
001 80010190 ABS notype Static | @feat.00
002 00000002 ABS notype Static | @vol.md
003 00000000 SECT1 notype Static | .drectve
Section length 2F, #relocs 0, #linenums 0, checksum 0
005 00000000 SECT2 notype Static | .debug$S
Section length 68, #relocs 0, #linenums 0, checksum 0
007 00000000 SECT3 notype Static | .text$mn
Section length 5D, #relocs 6, #linenums 0, checksum D202F0CD
009 00000000 UNDEF notype () External | puts
00A 00000000 UNDEF notype () External | strnicmp
00B 00000000 SECT3 notype () External | main
00C 00000000 SECT3 notype Label | $LN5
00D 00000000 SECT4 notype Static | .xdata
Section length 8, #relocs 0, #linenums 0, checksum E7553388
00F 00000000 SECT4 notype Static | $unwind$main
010 00000000 SECT5 notype Static | .pdata
Section length C, #relocs 3, #linenums 0, checksum CE23E617
012 00000000 SECT5 notype Static | $pdata$main
013 00000000 SECT6 notype Static | .data
Section length 2C, #relocs 0, #linenums 0, checksum C7B9A925
015 00000000 SECT6 notype Static | $SG10717
016 00000008 SECT6 notype Static | $SG10718
017 00000018 SECT6 notype Static | $SG10719
018 00000000 SECT7 notype Static | .chks64
Section length 38, #relocs 0, #linenums 0, checksum 0
String Table Size = 0x1D bytes
Summary
38 .chks64
2C .data
68 .debug$S
2F .drectve
C .pdata
5D .text$mn
8 .xdata
... er? strnicmp
is being imported, but not with the prepended underscore suggested by the Microsoft documentation. The reference is to the unadorned name.
So what's going on? Presumably I am misunderstanding something in the chain here. Is there a way for a function to be exported such that it does not show up in the dumpbin /exports
output of any library?
It's in oldnames.lib
. It didn't show up in the listing because it turns out that for a static library, you need to use dumpbin /symbols
instead of /exports
, otherwise it silently gives no output.