1

I am writing a C++ DLL (Plugin.dll) which depends on a static library (lib_a.lib).

I also maintain lib_a, which has a source file Stuff.cpp. In stuff.cpp two functions are implemented:

#include <third_party_library/MyHeader.h>
...

//This function depends on third_party_library
bool Stuff::Foo(MyType* arg1)
{
    bool success = ThirdPartyLib::Bar(arg1); //Declared in third_party_library/MyHeader.h
    if (!success) { return false; }
}

//This function does not depend on third_party_library
bool Stuff::Foo(MyType* arg1, MyType2* arg2)
{
    bool success = Stuff::SomeOtherFunc(arg1, arg2);
    if (!success) { return false; }
}

...

In Plugin.dll, there is a call to the second function, which does not depend on third_party_library. There are no calls to the first function in Plugin.dll (and I have traced every possible call stack to verify that there can be no downstream calls to the first function). Therefore, Plugin functions do not actually call anything depending on third_party_library (none of Plugin's other dependencies depend on third_party_library; the only way for this dependency to occur would be through lib_a as described).

When I build Plugin in the release configuration, then check dependencies in the Visual Studio terminal window using the command dumpbin /DEPENDENTS C:\path\to\build\x64\Release\Plugin.dll, third_party_library.dll is not listed as a dependency. However, when I build Plugin in the debug configuration and check the dependencies of Plugind.dll, third_party_libraryd.dll (the debug version of third_party_library) is listed as a dependency. I know that this dependency comes from Plugin's call to Stuff:Foo(MyType* arg1) because the dependency is eliminated if I comment out this call and rebuild.

I assumed this discrepancy was due to linker optimizations (/OPT:REF) being enabled for the release configuration and not the debug configuration, but enabling linker optimizations in the debug configuration did not solve the problem.

In fact, I even started from scratch and made a new debug configuration that was an exact copy of my release configuration except for the following:

  1. Debug has the preprocessor definition _DEBUG, Release has NDEBUG
  2. In 'Linker options->Additional Dependencies,' the Debug configuration lists the debug version of each library while the Release configuration lists the release version of each library
  3. Debugger information is generated in the Debug build (/Debug/Zi)

(This configuration is not so useful for actual debugging, I just made it to get to the bottom of the problem).

Yet I still get a dependency on third_party_libraryd.dll in my debug build. I would really like to eliminate this unused dependency so I don't have to keep this dll in my repo (I have this same problem with several third party libraries, so they are sizable all put together) or distribute it on the occasion I have to deploy a debug build internally.

So my question is, why might Plugind.dll still depend on third_party_libraryd.dll and is there a way for me to eliminate this dependency?

The compiler command line options in the Debug configuration are:

/JMC /GS /GL /W3 /Gy /Zc:wchar_t /I"C:\our\include\paths" /Zi /Gm- /O2 /sdl /Fd"x64\Debug\vc141.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_WINDOWS" /D "CV4" /D "G3D9" /D "_USRDLL" /D "SIMPLENATIVELIBRARY_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /D "_AFXDLL" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MDd /FC /Fa"x64\Debug" /EHsc /nologo /Fo"x64\Debug" /Fp"x64\Debug\Plugind.pch" /diagnostics:classic

The compiler command line options in the Release configuration are:

/JMC /GS /GL /W3 /Gy /Zc:wchar_t /I"C:\our\include\paths" /Gm- /O2 /sdl /Fd"x64\Release\vc141.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_WINDOWS" /D "CV4" /D "G3D9" /D "_USRDLL" /D "SIMPLENATIVELIBRARY_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /D "_AFXDLL" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /FC /Fa"x64\Release" /EHsc /nologo /Fo"x64\Release" /Fp"x64\Release\Plugin.pch" /diagnostics:classic

The linker command line options in the Debug configuration are:

/OUT:"C:\path\to\build\x64\Debug\Plugind.dll" /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"C:\path\to\build\x64\Debug\Plugind.pdb" /DYNAMICBASE "lib_a_debug.lib" "third_party_libraryd.lib" "other_dependencies_debug.lib" /IMPLIB:"C:\path\to\build\x64\Debug\Plugind.lib" /DEBUG /DLL /MACHINE:X64 /NODEFAULTLIB:"LIBCMT" /OPT:REF /INCREMENTAL:NO /PGD:"C:\path\to\build\x64\Debug\Plugind.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Debug\Plugind.dll.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\our\library_paths" /TLBID:1

The linker command line options in the Release configuration are:

/OUT:"C:\path\to\build\x64\Release\Plugin.dll" /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"C:\path\to\build\x64\Release\Plugin.pdb" /DYNAMICBASE "lib_a.lib" "third_party_library.lib" "other_dependencies.lib" /IMPLIB:"C:\path\to\build\x64\Release\Plugin.lib" /DEBUG /DLL /MACHINE:X64 /NODEFAULTLIB:"LIBCMT" /OPT:REF /INCREMENTAL:NO /PGD:"C:\path\to\build\x64\Release\Plugin.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"x64\Release\Plugin.dll.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\our\library_paths" /TLBID:1

  • That seems to say `third_party_libraryd.lib` was an import library and not a static library. – drescherjm Mar 16 '23 at 17:43
  • @drescherjm correct, third_party_libraryd.lib is in an import library for third_party_libraryd.dll. I don't think I ever said it was a static library? To be clear, lib_a.lib is a static library, which I maintain, that contains some functions that need third_party_library.dll – Margaret Schrayer Mar 16 '23 at 17:57
  • Perhaps the most direct thing is to split your lib into two -- one with the dependency and one without. – Paul Dempsey Mar 16 '23 at 19:37
  • 1
    Or rather, use `#ifdef USE_THIRDPARTY_THING` – Osyotr Mar 16 '23 at 19:41
  • which implies building the lib two different ways, hence creating two libraries. – Paul Dempsey Mar 16 '23 at 20:01

1 Answers1

2

As you already mentioned, the culprit for your dependency difference (in Debug / Release modes) is [MS.Learn]: /OPT (Optimizations) (different settings for the 2 configurations) which states (emphasis is mine):

By default, /OPT:REF is enabled by the linker unless /OPT:NOREF or /DEBUG is specified. To override this default and keep unreferenced COMDATs in the program, specify /OPT:NOREF. You can use the /INCLUDE option to override the removal of a specific symbol.

If /DEBUG is specified, the default for /OPT is NOREF, and all functions are preserved in the image. To override this default and optimize a debug build, specify /OPT:REF.

That was the WHY part.

You mentioned that adding /OPT:REF did not solve the problem, so I created an MCVE ([SO]: How to create a Minimal, Reproducible Example (reprex (mcve))) and it worked on my side (simply setting References option to /OPT:REF and rebuilding, the Plugin.dll equivalent didn't depend on the 3rd-party one).
As it's impossible to demo it from VStudio (GUI - maybe record a video and post it somewhere?), I'm posting the CmdLine (NMake - check the 2nd URL in list at the end) variant.

Note: When building (NMake), I hit the same problem you did. After hours of investigations (went through a couple of options (e.g.: /Zc:inline), I found the culprit: [MS.Learn]: /Gy (Enable Function-Level Linking) - which was automatically enabled (by /ZI - which was set) in VStudio, but not (by /Zi) in NMake)

  • include/common.h:

    #pragma once
    
    #include <iostream>
    
    #define DBG_MSG0() std::cout << "[" << __FILE__ << "] " << __LINE__ << " (" << __FUNCTION__ << ")\n"
    
  • include/dll00.h:

    #pragma once
    
    #if defined(_WIN32)
    #  if defined(DLL00_STATIC)
    #    define DLL00_EXPORT_API
    #  else
    #    if defined(DLL00_EXPORTS)
    #      define DLL00_EXPORT_API __declspec(dllexport)
    #    else
    #      define DLL00_EXPORT_API __declspec(dllimport)
    #    endif
    #  endif
    #else
    #  define DLL00_EXPORT_API
    #endif
    
    
    class DLL00_EXPORT_API Dll00Cls00 {
    public:
        static void meth00();
    };
    
  • dll00/src/dll00.cpp:

    #include <dll00.h>
    #include "common.h"
    
    
    void Dll00Cls00::meth00()
    {
        DBG_MSG0();
    }
    
  • include/lib00.h:

    #pragma once
    
    #if defined(_WIN32)
    #  if defined(LIB00_STATIC)
    #    define LIB00_EXPORT_API
    #  else
    #    if defined(LIB00_EXPORTS)
    #      define LIB00_EXPORT_API __declspec(dllexport)
    #    else
    #      define LIB00_EXPORT_API __declspec(dllimport)
    #    endif
    #  endif
    #else
    #  define LIB00_EXPORT_API
    #endif
    
    
    class LIB00_EXPORT_API Lib00Cls00 {
    public:
        static void meth00();
        static void meth01_use_dll00();
    };
    
  • lib00/src/lib00.cpp:

    #include <lib00.h>
    #include "common.h"
    #include <dll00.h>
    
    
    void Lib00Cls00::meth00()
    {
        DBG_MSG0();
    }
    
    void Lib00Cls00::meth01_use_dll00()
    {
        Dll00Cls00::meth00();
        DBG_MSG0();
    }
    
  • include/dll01.h:

    #pragma once
    
    #if defined(_WIN32)
    #  if defined(DLL01_STATIC)
    #    define DLL01_EXPORT_API
    #  else
    #    if defined(DLL01_EXPORTS)
    #      define DLL01_EXPORT_API __declspec(dllexport)
    #    else
    #      define DLL01_EXPORT_API __declspec(dllimport)
    #    endif
    #  endif
    #else
    #  define DLL01_EXPORT_API
    #endif
    
    
    class DLL01_EXPORT_API Dll01Cls00 {
    public:
        static void meth00();
    };
    
  • dll01/src/dll01.cpp:

    #include <dll01.h>
    #include "common.h"
    #include <lib00.h>
    
    
    void Dll01Cls00::meth00()
    {
        Lib00Cls00::meth00();
        //Lib00Cls00::meth01_use_dll00();
        DBG_MSG0();
    }
    
  • app00/src/app00.cpp:

    #include <dll01.h>
    #include "common.h"
    
    
    int main()
    {
        Dll01Cls00::meth00();
        DBG_MSG0();
    
        return 0;
    }
    
  • Makefile.mak (note that I just created it to quickly build 4 source files - it's not robust at all in terms of dependencies and should not be used in production, also I only ran it (and customized it) for debug builds):

    !include <NtWin32.mak>
    
    RM=del /f /q
    
    DLL00=dll00
    LIB00=lib00
    DLL01=dll01
    APP00=app00
    
    FLAGS_COMPILER=/EHsc /Iinclude /D_DEBUG /Gy
    FLAGS_LINKER=/INCREMENTAL
    !if ("$(OPTREF)" == "")
    OUTD=bin/regular
    !else
    OUTD=bin/optref
    FLAGS_LINKER=$(FLAGS_LINKER) /OPT:REF
    !endif
    FLAGS_LINKER=$(FLAGS_LINKER) /LIBPATH:$(OUTD)
    
    cflags=$(cflags:-c =)
    #cdebug=$(cdebug:-Zi=/ZI)  # Sets /Gy implicitly
    
    all: $(OUTD)/$(APP00).exe
    
    clean:
        -$(RM) "$(OUTD)"\*
        -$(RM) *.lib *.exp *.pdb *.obj *.idb
    
    $(OUTD)/$(APP00).exe: $(APP00)/src/$(APP00).cpp $(OUTD)/$(DLL01).dll
        -@echo --- Building $@ ---
        $(CXX) /nologo $(cdebug) $(cflags) $(cvarsdll) $(FLAGS_COMPILER) $(APP00)/src/$(APP00).cpp  /link /NOLOGO $(ldebug) $(FLAGS_LINKER) $(DLL01).lib $(conlflags) $(conlibsdll) /OUT:$@
    
    $(OUTD)/$(DLL01).dll: $(DLL01)/src/$(DLL01).cpp $(OUTD)/$(LIB00).lib
        -@echo --- Building $@ ---
        $(CXX) /nologo $(cdebug) $(cflags) $(cvarsdll) $(FLAGS_COMPILER) /DDLL01_EXPORTS /DLIB00_STATIC $(DLL01)/src/$(DLL01).cpp  /link /NOLOGO $(ldebug) $(FLAGS_LINKER) $(dlllflags) $(LIB00).lib $(conlibsdll) /OUT:$@
    
    $(OUTD)/$(LIB00).lib: $(LIB00)/src/$(LIB00).cpp $(OUTD)/$(DLL00).dll
        -@echo --- Building $@ ---
        $(CXX) /nologo $(cdebug) $(cflags) $(cvarsdll) $(FLAGS_COMPILER) /DLIB00_STATIC /c $(LIB00)/src/$(LIB00).cpp
        lib /NOLOGO $(ldebug) $(FLAGS_LINKER) $(LIB00).obj $(DLL00).lib /OUT:$@
    
    $(OUTD)/$(DLL00).dll: $(DLL00)/src/$(DLL00).cpp
        -@echo --- Building $@ ---
        $(CXX) /nologo $(cdebug) $(cflags) $(cvarsdll) $(FLAGS_COMPILER) /DDLL00_EXPORTS $?  /link /NOLOGO $(ldebug) $(FLAGS_LINKER) $(dlllflags) $(conlibsdll) /OUT:$@
    

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackExchange\StackOverflow\q075759550]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Auxiliary\Build\vcvarsall.bat" x64 > nul

[prompt]> set INCLUDE=%INCLUDE%;e:\Work\Dev\GitHub\CristiFati\MSSDKFiles\src\Include

[prompt]>
[prompt]> dir /b bin\regular bin\optref

[prompt]>
[prompt]> :: Build "regularly"
[prompt]> nmake /nologo /f Makefile.mak OPTREF= clean all
        del /f /q "bin/regular"\*
        del /f /q *.lib *.exp *.pdb *.obj *.idb
Could Not Find e:\Work\Dev\StackExchange\StackOverflow\q075759550\*.lib*
--- Building bin/regular/dll00.dll ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy /DDLL00_EXPORTS dll00/src/dll00.cpp  /link /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /LIBPATH:bin/regular  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup -dll kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:bin/regular/dll00.dll
dll00.cpp
   Creating library bin\regular\dll00.lib and object bin\regular\dll00.exp
--- Building bin/regular/lib00.lib ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy /DLIB00_STATIC /c lib00/src/lib00.cpp
lib00.cpp
        lib /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /LIBPATH:bin/regular lib00.obj dll00.lib /OUT:bin/regular/lib00.lib
LINK : warning LNK4044: unrecognized option '/DEBUG'; ignored
LINK : warning LNK4044: unrecognized option '/DEBUGTYPE:cv'; ignored
LINK : warning LNK4044: unrecognized option '/INCREMENTAL'; ignored
--- Building bin/regular/dll01.dll ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy /DDLL01_EXPORTS /DLIB00_STATIC dll01/src/dll01.cpp  /link /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /LIBPATH:bin/regular  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup -dll lib00.lib kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:bin/regular/dll01.dll
dll01.cpp
   Creating library bin\regular\dll01.lib and object bin\regular\dll01.exp
--- Building bin/regular/app00.exe ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy app00/src/app00.cpp  /link /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /LIBPATH:bin/regular dll01.lib  /INCREMENTAL:NO /NOLOGO -subsystem:console,6.0 kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:bin/regular/app00.exe
app00.cpp

[prompt]>
[prompt]> :: Build with /OPT:REF
[prompt]> nmake /nologo /f Makefile.mak OPTREF=NONempty clean all
        del /f /q "bin/optref"\*
        del /f /q *.lib *.exp *.pdb *.obj *.idb
--- Building bin/optref/dll00.dll ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy /DDLL00_EXPORTS dll00/src/dll00.cpp  /link /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /OPT:REF /LIBPATH:bin/optref  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup -dll kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:bin/optref/dll00.dll
dll00.cpp
   Creating library bin\optref\dll00.lib and object bin\optref\dll00.exp
--- Building bin/optref/lib00.lib ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy /DLIB00_STATIC /c lib00/src/lib00.cpp
lib00.cpp
        lib /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /OPT:REF /LIBPATH:bin/optref lib00.obj dll00.lib /OUT:bin/optref/lib00.lib
LINK : warning LNK4044: unrecognized option '/DEBUG'; ignored
LINK : warning LNK4044: unrecognized option '/DEBUGTYPE:cv'; ignored
LINK : warning LNK4044: unrecognized option '/INCREMENTAL'; ignored
LINK : warning LNK4044: unrecognized option '/OPT:REF'; ignored
--- Building bin/optref/dll01.dll ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy /DDLL01_EXPORTS /DLIB00_STATIC dll01/src/dll01.cpp  /link /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /OPT:REF /LIBPATH:bin/optref  /INCREMENTAL:NO /NOLOGO -entry:_DllMainCRTStartup -dll lib00.lib kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:bin/optref/dll01.dll
dll01.cpp
   Creating library bin\optref\dll01.lib and object bin\optref\dll01.exp
--- Building bin/optref/app00.exe ---
        cl /nologo -Zi -Od -DDEBUG -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -D_AMD64_=1 -DWIN64 -D_WIN64  -DWIN32 -D_WIN32 -W4 -D_WINNT -D_WIN32_WINNT=0x0600 -DNTDDI_VERSION=0x06000000 -D_WIN32_IE=0x0700 -DWINVER=0x0600  -D_MT -D_DLL -MDd /EHsc /Iinclude /D_DEBUG /Gy app00/src/app00.cpp  /link /NOLOGO /DEBUG /DEBUGTYPE:cv /INCREMENTAL /OPT:REF /LIBPATH:bin/optref dll01.lib  /INCREMENTAL:NO /NOLOGO -subsystem:console,6.0 kernel32.lib  ws2_32.lib mswsock.lib advapi32.lib /OUT:bin/optref/app00.exe
app00.cpp

[prompt]>
[prompt]> :: Run the executables
[prompt]> bin\regular\app00.exe
[lib00/src/lib00.cpp] 8 (Lib00Cls00::meth00)
[dll01/src/dll01.cpp] 10 (Dll01Cls00::meth00)
[app00/src/app00.cpp] 8 (main)

[prompt]> bin\optref\app00.exe
[lib00/src/lib00.cpp] 8 (Lib00Cls00::meth00)
[dll01/src/dll01.cpp] 10 (Dll01Cls00::meth00)
[app00/src/app00.cpp] 8 (main)

[prompt]>
[prompt]> :: Test dll01.dll (for dll00.dll dependency) in the 2 directories
[prompt]> dumpbin /DEPENDENTS bin\regular\dll01.dll | findstr dll00
    dll00.dll

[prompt]> dumpbin /DEPENDENTS bin\optref\dll01.dll | findstr dll00

[prompt]>

So, it is possible to eliminate the (unused) dependency via compile / link flags.

There are a number of ways to move forward, each with its benefits and drawbacks. It depends very much on your environment (and workflows you have in place):

  • Build system:

    • VStudio (that I assume you're using, based on compile and link commands)

    • NMake

    • CMake

    • Other

  • How large your projects are

  • Whether the static library (with 3rd-party .dll dependency is used in other projects)

  • Many others

Below there are some that I came up with (there may be others). Choose whichever suits you best:

  1. Modify build options:

    • /Gy (compile) for the static library (at least)

    • /OPT:REF (link) for the .dll linking the static library

    Most obvious (and simplest) one

  2. Clean the static library code by removing the 3rd-party .dll references. If there's code that is not used, it's just a pile of garbage, which makes it very hard to maintain.
    The drawback is that it will require more work

  3. Refactor the static library. If for some reason cleaning is not possible (a variant that does use the 3rd-party .dll is required for some other project), it could use some adjustments:

    1. Split it in 2 separate parts (.libs): one that uses the 3rd-party .dll and another that doesn't. In your plugin.dll only link the latter

    2. Do some conditional building (based on some macro). But that's a bit trickier when setting the options from the IDE. [MS.Learn]: comment pragma could come in handy

    Even more work (compared to previous) will be required

Might also worth reading (including referenced URLs):

CristiFati
  • 38,250
  • 9
  • 50
  • 87