添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

LNK4099 warnings can occur when building on Windows during the link phase of a static compilation.

E.g. when building using nmake and VC10 I get a stream of LNK4099 warnings like:

libcurl_a_debug.lib(rc2_cbc.obj) : warning LNK4099: PDB 'lib.pdb' was not found with 'libcurl_a_debug.lib(rc2_cbc.obj)' or at 'C:\dev\scaler\center\dlux\lib.pdb'; linking object as if no debug info

StackOverflow gives a good overview of the problem, but not the detail required to understand it.

Rather than ignore the warning or disable the warning, I would like to fix the makefiles in my build to remove the problem.

How does the problem arise? How do I remove the cause of the warnings?

Understand that the underlying problem is a missing debug symbols file (.pdb) for the library mentioned in the warning. Library files contain a static reference to the .pdb on an object file basis. When a library is used by another library and static compilation is used, Visual Studio collects all the symbols into a single .pdb and the .pdb references in the object files are updated. However, if it cannot find the symbols, it will leave the old path in place.

Fix the warning by recompiling the library mentioned in the warnings, and make sure the compiler has access to the .pdb of every referenced library. This involves determining which .pdb file cannot be found, and then making changes to ensure the .pdb can be found.

Which object file (and thus library) are we missing the symbols (.pdb) for?

@goth provided a blog link explaining where the .pdb reference comes from, but here is my summary:

A library contains a number of object files. Each object file includes a path to the debug symbols. We can use tools extract this information. Based on the object file and path, we can figure out which debug symbols file (.pdb) could not be found.

  • Open the Visual Studio Command Prompt. This creates a command shell with environment variables required to access Visual Studio tools. (Should be under "Visual Studio Tools" buried in the Start Menu, but this varies)

  • Obtain the internal path of the object file in the library using the lib tool's /list option. E.g.

  • C:\dev\libcurl\win\lib>lib /list libcurl_a_debug.lib > list_of_object_files_in_library.txt
    C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>more list_of_object_files_in_library.txt
    Microsoft (R) Library Manager Version 10.00.40219.01
    ..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/file.obj
    ..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/timeval.obj
    ..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/rc2_cbc.obj
    
  • Using the path, extract the object file using the lib tool's /extract option.
  • C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>lib /extract:..\builds\libcurl-vc10-x86-debug-static-ssl-static-ipv6-spnego-obj-lib/timeval.obj libcurl_a_debug.lib
    Microsoft (R) Library Manager Version 10.00.40219.01
    
  • The object file contains a debug section called .debug$T that we can extract using the dumpbin tool. E.g.
  • C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>dumpbin /section:.debug$T /rawdata rc2_cbc.obj > dump_of_object_file_debug_info.txt
    C:\dev\scaler\center\agent\thirdparty\libcurl\win\lib>more dump_of_object_file_debug_info.txt
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
    Dump of file ./rc2_cbc.obj
    File Type: COFF OBJECT
    SECTION HEADER #9
    .debug$T name
           0 physical address
           0 virtual address
          5C size of raw data
        1D53 file pointer to raw data (00001D53 to 00001DAE)
           0 file pointer to relocation table
           0 file pointer to line numbers
           0 number of relocations
           0 number of line numbers
    42100040 flags
             Initialized Data
             Discardable
             1 byte align
             Read Only
    RAW DATA #9
      00000000: 04 00 00 00 56 00 15 15 03 7A 47 A3 3D 4A 8C 4B  ....V....zGú=J.K
      00000010: A2 A5 26 D3 D6 57 15 46 3A 00 00 00 73 3A 5C 73  óÑ&ËÍW.F:...s:\s
      00000020: 63 61 6C 65 78 2E 6E 65 77 5C 63 65 6E 74 72 6F  caler.new\center
      00000030: 5C 6F 70 65 6E 73 73 6C 5C 62 75 69 6C 64 5C 6F  \openssl\build\o
      00000040: 70 65 6E 73 73 6C 2D 31 2E 30 2E 30 62 5C 74 6D  penssl-1.0.0b\tm
      00000050: 70 33 32 5C 6C 69 62 2E 70 64 62 00              p32\lib.pdb.
      Summary
              5C .debug$T
    

    Above, you see that the object file says its debug symbols s:\scaler.new\center\openssl\build\openssl-1.0.0b\tmp32\lib.pdb. Therefore, the problem lies with the .pdb generated when we built the openssl library used by libcurl.

    How do I add the debug symbols to the library generating the warning?

    The /Fd option governs the name and location of the .pdb symbols file. E.g. when compiling libcurl, I used the following flags:

    !IF DEFINED(VC10) NT_MAK_FLAGS = APP_CFLAG="/GX /GZ /MTd /Fdtmp32.dbg/app" LIB_CFLAG="/Zl /Z7 /Fdtmp32.dbg/lib" !ENDIF

    The symbol file name of lib.pdb and its path relative to the build is given by /Fdtmp32.dbg/lib.

    The problem is that the NT_MAK_FLAGS is reused for a number of libraries that are generated when openssl is compiled. As a result, lib.pdb is clobbered (overwritten) for all but the last library. To resolve the problem, each library should be given .pdb with a unique name. To simplify matters further, ensure that the compilation location is in the same tree as the libcurl build.

    Your answer is great and it works! I still have some questions: How to check the required pdb file for EXEs or DLLs iso libs? If multiple static libs are required by the lib or exe, should you see their respective pdb files in the object dump? – jaques-sam Aug 21, 2019 at 13:30

    I think they got misaligned when I imported an old 32 bit VS2010 project into VS2013 and set it up for 64 bits.

    So I end up with this (good) situation:

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.