(Update: As per Hans' suggestion, here's a suggestion to improve link.exe's behaviour, and you can vote for it if you have an account over there.)
Okay, I'm a fool. In January I installed Oracle on my computer, Win7 Pro 64 Bit. I installed the 64 Bit version. Yesterday, using MSVC Express, I tried to compile and link a small test programm oci1.c against oci.h and oci.lib.
cl /nologo /c /I%ORACLE_HOME%\oci\include oci1.c
link /nologo oci1.obj /LIBPATH:%ORACLE_HOME%\oci\lib\msvc oci.lib
My attempts kept failing with LNK2019, which means unresolved external symbol 'symbol' referenced in function 'function'. The symbol in question (_OCIEnvCreate) is, of course, provided by oci.lib, so the linker should be able to resolve it.
It finally dawned on me that it couldn't work because my compiler is 32 bit only, and the import library is 64 bit. If you're a fool and you don't know or remember, then you can see it using the dumpbin utility:
$ dumpbin /headers %ORACLE_HOME%\oci\lib\msvc\oci.lib | head
File Type: LIBRARY
FILE HEADER VALUES
8664 machine (x64)
$ dumpbin /headers oci1.obj | head
File Type: COFF OBJECT
FILE HEADER VALUES
14C machine (x86)
So far, so good. But I wasted some time and would like to avoid repeating that experience.
While not incorrect, the LNK2019 error message doesn't lead you straight in the right direction. There's no warning that you're attempting to link binaries for different CPU architectures.
Note that when you specify the X64 architecture, you are alerted to the fact that you specified X86 binaries:
$ link /machine:x64 /nologo oci1.obj /LIBPATH:%ORACLE_HOME%\oci\lib\msvc oci.lib
oci1.obj : fatal error LNK1112:
Modul-Computertyp "X86" steht in Konflikt mit dem Zielcomputertyp "x64".
But there is no such precise warning when you specify the X86 architecture, explicitly or implicitly:
$ link /machine:x86 /nologo oci1.obj /LIBPATH:%ORACLE_HOME%\oci\lib\msvc oci.lib
oci1.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol
"_OCIEnvCreate" in Funktion "_main".
oci1.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
I just found the /VERBOSE switch to link.exe, which when used hints that no symbols are found in my 64 bit oci.lib.
Are there other options you can turn on to make the linking process more, eh, fool-proof?
Update: As per Hans' answer, I ran dumpbin on a 32 bit import library, and the names appear as follows:
$ dumpbin /exports D:\Opt\MySQL5.5\lib\libmysql.lib
_load_defaults
_myodbc_remove_escape@8
_mysql_affected_rows@4
_mysql_autocommit@8
_mysql_change_user@16
_mysql_character_set_name@4
Whereas the names in the 64 bit OCI import library that I'm dealing with here appear undecorated:
OCIXmlDbFreeXmlCtx
OCIXmlDbInitXmlCtx
ORLRconNativeInt
ORLRvalNativeInt
OraCoreIsPhysicalRawFile
OraMemAlloc
When compiling for the x64 architecture in a Windows context (whether
using Microsoft or non-Microsoft tools), there is only one calling
convention — the one described here, so that stdcall, thiscall, cdecl,
fastcall, etc., are now all one and the same.
Makes sense to me now. One and only calling convention, hence no name mangling necessary, hence no leading underscore as per cdecl when compiling for X86.
解决方案
I think it simply complains about the missing symbol before getting around to checking the binary compatibility. That will commonly happen first, x64 symbols don't have the leading underscore since x64 doesn't have any calling conventions. Unless you use Microsoft import libraries, they don't decorate the symbols at all.
But I very much agree, getting the compatibility error first would be much more productive. No idea how hard that is to implement. Ask the guys who know and can make it work like that, post a feature request to connect.microsoft.com