且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在链接到动态库的静态库中导出符号

更新时间: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

注释:

  • 如前所述,我使用了命令行,但是 VStudio IDE
  • 调用了相同的命令(更多参数)
  • 添加 /include:foo (第2 nd link 命令)导出 foo (以及在下一个 dumpbin 输出中看到的):
    • 指定此选项与添加#pragma comment(linker, "/include:foo")(在 dll.cpp 中-或直接传递到链接器的任何文件)相同
    • 不需要
    • /export:foo ,因为该功能已由 __ declspec(dllexport)
    • 导出
    • As noticed, I used command line, but the same commands (more arguments) are invoked by VStudio IDE
    • Adding /include:foo (2ndlink command) exports foo as well (as seen in the next dumpbin output):
      • Specifying this option is identical to adding #pragma comment(linker, "/include:foo") (in dll.cpp - or any file that is being directly passed to the linker)
      • /export:foo is not necessary, as the function is already exported by __declspec(dllexport)


      您可能根本没有做错任何事情.但是请记住,它不可扩展(如果您有数百个这样的符号).查看 [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:

      • 直接(命令行):它包含在 .dll (或 .exe )
      • 间接(通过命令行传递的 .lib 的一部分):它不包含在 .dll 中,仅搜索符号
      • Directly (command line): it is included in the .dll (or .exe)
      • Indirectly (part of a .lib passed via command line): it is not included in the .dll, it is only searched for symbols

      这完全有道理,因为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):

      • /EXPORT :(在 .lib 中)搜索符号( foo02 )并仅导出它
      • /INCLUDE :在 .lib 中搜索符号( foo02 ),获得包含目标文件( lib0.obj ),并将其包含在 .dll 中:
        • 因此,将导出在 .obj 文件中标记为要导出的其他2个符号( foo00 foo01 )
        • >
        • /EXPORT: searches (in the .lib) for the symbol (foo02) and simply exports it
        • /INCLUDE: searches (in the .lib) for the symbol (foo02), gets the containing object file (lib0.obj), and includes it in the .dll:
          • As a consequence, the other 2 symbols (foo00, foo01) marked for export in the .obj file are exported

          深入了解并发现 [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