更新时间:2023-09-12 14:19:40
您做错了(或至少没有按照问题中的描述进行操作).当然,您在答案中发布的内容也可以使用,但这只是一种解决方法,因为常规"方式应该可以使用.
这是一个小例子.
You're doing something wrong (or at least not as you describe in the question). Of course, what you posted in your answer works as well, but that's only a workaround, as the "regular" way should work.
Here's a small example.
lib.cpp :
extern "C" __declspec(dllexport) bool foo() {
return true;
}
dll.cpp :
extern "C" __declspec(dllexport) bool bar() {
return false;
}
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\***\q056330888]> sopr.bat
*** Set shorter prompt to better fit when pasted in *** (or other) pages ***
[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.13
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
[prompt]> dir /b
dll.cpp
lib.cpp
[prompt]> cl /c /nologo /D_LIB /DSTATIC /Folib.obj lib.cpp
lib.cpp
[prompt]> lib /nologo /out:lib.lib lib.obj
[prompt]>
[prompt]> cl /c /nologo /DDLL /Fodll.obj dll.cpp
dll.cpp
[prompt]> link /nologo /dll /out:dll.dll dll.obj lib.lib
Creating library dll.lib and object dll.exp
[prompt]> dir /b
dll.cpp
dll.dll
dll.exp
dll.lib
dll.obj
lib.cpp
lib.lib
lib.obj
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001000 bar
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text
[prompt]>
[prompt]> :: ----- Re-link dll, instructing it to include foo -----
[prompt]>
[prompt]> link /nologo /dll /include:foo /out:dll.dll dll.obj lib.lib
Creating library dll.lib and object dll.exp
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001000 bar
2 1 00001010 foo
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text
注释:
#pragma comment(linker, "/include:foo")
(在 dll.cpp 中-或直接传递到链接器的任何文件)相同#pragma comment(linker, "/include:foo")
(in dll.cpp - or any file that is being directly passed to the linker)
您可能根本没有做错任何事情.但是请记住,它不可扩展(如果您有数百个这样的符号).查看 [MS.Docs]:LIB概述,它在导出内容方面提供与 link 相同的选项.但是它们似乎被忽略了.
You might not be doing things wrong after all. But bear in mind that it's not scalable (if you have hundreds of such symbols). Looking at [MS.Docs]: Overview of LIB, it provides the same options as link in regards to exporting stuff. But they seem to be ignored.
在构建lib时,当构建时,可能希望指定链接时要包含的所有符号(通过选项或通过 #pragma注释). .lib ,而不是链接时.显然,它们会被忽略(我已经对其进行了测试),除非在直接传递给链接器的 .obj 文件(或选项)中指定了内容.这是因为 [ MS.Docs]:构建导入库和导出文件(重点是我的):
When building a lib, maybe one would like to specify all the symbols to be included at link time (either via option or via #pragma comment), when building the .lib, and not when linking. Apparently, they are ignored (I've tested it), unless stuff is specified in .obj files (or options) passed directly to the linker. This is because [MS.Docs]: Building an Import Library and Export File (emphasis is mine):
请注意,如果在准备步骤中创建导入库,则在创建.dll之前,在构建.dll时必须传递与在构建导入库时传递的对象文件集相同的对象文件 strong>.
Note that if you create your import library in a preliminary step, before creating your .dll, you must pass the same set of object files when building the .dll, as you passed when building the import library.
因此,将 .obj 文件传递到链接器时会有所不同:
So there's a difference when passing an .obj file to the linker:
这完全有道理,因为lib只是 .obj 文件的集合(存档)(在 Nix 上,存档器是 ar (以前称为 ranlib )).一个例子:
This totally makes sense as a lib is just a collection (archive) of .obj files (on Nix the archiver is ar (formerly known as ranlib)). An example:
输出:
[prompt]> del *.obj *.exp *.lib *.dll
[prompt]> dir /b
dll.cpp
lib.cpp
[prompt]> cl /c /nologo /D_LIB /DSTATIC /Folib.obj lib.cpp
lib.cpp
[prompt]> cl /c /nologo /DDLL /Fodll.obj dll.cpp
dll.cpp
[prompt]> :: Pass lib.obj directly to linker
[prompt]> link /nologo /dll /out:dll.dll dll.obj lib.obj
Creating library dll.lib and object dll.exp
[prompt]> lib /nologo /out:lib.lib lib.obj
[prompt]>
[prompt]> dir
Volume in drive E is SSD0-WORK
Volume Serial Number is AE9E-72AC
Directory of e:\Work\Dev\***\q056330888
20/04/08 14:28 <DIR> .
20/04/08 14:28 <DIR> ..
19/06/30 20:03 114 dll.cpp
20/04/08 14:27 88,576 dll.dll
20/04/08 14:27 729 dll.exp
20/04/08 14:27 1,764 dll.lib
20/04/08 14:27 604 dll.obj
20/04/08 14:04 68 lib.cpp
20/04/08 14:28 822 lib.lib
20/04/08 14:27 604 lib.obj
8 File(s) 93,281 bytes
2 Dir(s) 83,419,111,424 bytes free
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001000 bar
2 1 00001010 foo
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text
[prompt]> :: Now do the same with the one from inside the .lib
[prompt]> del lib.obj
[prompt]> lib lib.lib /extract:lib.obj
Microsoft (R) Library Manager Version 14.16.27038.0
Copyright (C) Microsoft Corporation. All rights reserved.
[prompt]> dir lib.obj
Volume in drive E is SSD0-WORK
Volume Serial Number is AE9E-72AC
Directory of e:\Work\Dev\***\q056330888
20/04/08 14:28 604 lib.obj
1 File(s) 604 bytes
0 Dir(s) 83,419,107,328 bytes free
[prompt]> link /nologo /dll /out:dll.dll dll.obj lib.obj
Creating library dll.lib and object dll.exp
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001000 bar
2 1 00001010 foo
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .tex
我简短地玩过 [MS.Docs]:链接器选项( /INCLUDE 和 /EXPORT ).添加了一些复杂性.
I played briefly with [MS.Docs]: Linker options (/INCLUDE and /EXPORT). Added a bit of complexity into the mix.
lib0.cpp :
//#pragma comment(linker, "/include:foo1") // Apparently, has no effect in an .obj contained by a .lib
#pragma comment(linker, "/export:foo01")
#if defined(__cplusplus)
extern "C" {
#endif
__declspec(dllexport) bool foo00() {
return true;
}
bool foo01() {
return true;
}
bool foo02() {
return true;
}
#if defined(__cplusplus)
}
#endif
lib1.cpp :
#pragma comment(linker, "/export:foo11")
#if defined(__cplusplus)
extern "C" {
#endif
__declspec(dllexport) bool foo10() {
return true;
}
bool foo11() {
return true;
}
bool foo12() {
return true;
}
#if defined(__cplusplus)
}
#endif
输出:
[prompt]> del *.obj *.exp *.lib *.dll
[prompt]> cl /c /nologo /D_LIB /DSTATIC /Folib0.obj lib0.cpp
lib0.cpp
[prompt]> cl /c /nologo /D_LIB /DSTATIC /Folib1.obj lib1.cpp
lib1.cpp
[prompt]> lib /nologo /out:lib.lib lib0.obj lib1.obj
[prompt]> cl /c /nologo /DDLL /Fodll.obj dll.cpp
dll.cpp
[prompt]> :: ----- "Regular" behavior -----
[prompt]> link /nologo /dll /out:dll.dll dll.obj lib.lib
Creating library dll.lib and object dll.exp
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001000 bar
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text
[prompt]>
[prompt]> :: ----- /export a symbol -----
[prompt]> link /nologo /dll /out:dll.dll /export:foo02 dll.obj lib.lib
Creating library dll.lib and object dll.exp
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001000 bar
2 1 0000BB60 foo02
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text
[prompt]>
[prompt]> :: ----- /include a symbol -----
[prompt]> link /nologo /dll /out:dll.dll /include:foo02 dll.obj lib.lib
Creating library dll.lib and object dll.exp
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
3 number of functions
3 number of names
ordinal hint RVA name
1 0 00001000 bar
2 1 00001010 foo00
3 2 00001020 foo01
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text
所见(就像在 doc s中一样):
As seen (just like in the docs):
深入了解并发现 [MS.Docs]:/WHOLEARCHIVE(包括所有库对象文件) ,其中指出(强调是我的):
Took a deeper look and found [MS.Docs]: /WHOLEARCHIVE (Include All Library Object Files) which states (emphasis is mine):
/WHOLEARCHIVE选项强制链接器从指定的静态库中包括每个目标文件,或者,如果未指定库,则从所有静态库中 LINK命令.
...
/WHOLEARCHIVE选项是Visual Studio 2015 Update 2中引入的.
The /WHOLEARCHIVE option forces the linker to include every object file from either a specified static library, or if no library is specified, from all static libraries specified to the LINK command.
...
The /WHOLEARCHIVE option was introduced in Visual Studio 2015 Update 2.
输出:
[prompt]> :: ----- YAY ----- /wholearchive ----- YAY -----
[prompt]> link /nologo /dll /out:dll.dll /wholearchive:lib.lib dll.obj lib.lib
Creating library dll.lib and object dll.exp
[prompt]> dumpbin /nologo /exports dll.dll
Dump of file dll.dll
File Type: DLL
Section contains the following exports for dll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
5 number of functions
5 number of names
ordinal hint RVA name
1 0 00001000 bar
2 1 00001040 foo00
3 2 00001050 foo01
4 3 00001010 foo10
5 4 00001020 foo11
Summary
2000 .data
1000 .pdata
9000 .rdata
1000 .reloc
B000 .text