1
votes

We use VS2012, and have a dll built with a dependency on runtime DLL (/MD). This dll is used in many different projects, and cannot be changed easily.

We also have a small launcher executable that has to able to run on freshly installed systems, hence with no runtime installed. It is linked statically against the runtime (/MT).

Now this exe depends on the above dll.

As is, the exe does not built [1]. I have observed that building it by ignoring MSVCRT (/NODEFAULTLIB:"MSVCRT.lib") solves [1], but produces [2]. Adding the few symbols reported as errors in "force symbol references" (e.g. /INCLUDE:"_strncpy") makes the build succeed.

However checking the generated exe with Dependency Walker shows the dependency to the runtime DLLs [3] through our dll. I confirmed that the strings [3] are present in it. Trying to run the exe on a clean install of Vista fails (the error says a DLL from [3] is missing). I fear that this is not possible, and I have not found any information that suggests that it is.

Can a statically linked exe provide runtime functions to a dynamically linked dll? If yes, how?

Thanks

Refs:

  1. 1>MSVCRT.lib(MSVCR110.dll) : error LNK2005: _sprintf already defined in libcmt.lib(sprintf.obj)
  2. error LNK2001: unresolved external symbol __imp__strncpy
  3. MSVCP110.dll, MSVCR110.dll
4

4 Answers

1
votes

Yes, a statically linked exe can provide functions to a DLL. However doing so with the Standard Library functions is more trouble than it is worth.

You'd need to stop the DLL from building using its own copy of the runtime, using /NODEFAULTLIB. That will get you a bunch of link errors, since every part of the Standard library, as well as some vendor extensions, used by the DLL is now an unresolved external.

Each of these would need to be added to the EXE exports tables, using a module definition file. An import library would be generated during EXE linking. And then that import library would be supplied to the DLL to satisfy its externals, resolving them.

In the end, you would have only one copy of the runtime library, allowing your EXE and DLL to share library objects such as FILE* and the heap (so you could allocate in one and free in the other). But the DLL and EXE would be extremely closely coupled. Almost any change to the DLL could break the build, and require new exports from the EXE to fix it. You definitely could not ship updates to the DLL separately from updates to the EXE.

A much easier approach, that still keeps the DLL size down, would be to use delay-loading. This way, although the DLL still cannot load without the runtime redistributable installed first, the failure would not occur during process startup, and the EXE would have a chance to check for the presence of the runtime and install the redistributable. Or diagnose and handle failure of the DLL to load.

In an extreme case, the EXE could avoid using the Standard library at all, ensure the presence of the redistributable components, and then invoke the delay-load DLL for all complex logic requiring the Standard library runtimes.

In these latter cases because the EXE is not using the DLL version of the runtime, you can't share Standard library objects between EXE and DLL. But the coupling is much much looser. I think it's a tradeoff worth making.

0
votes

We eventually changed our dll build settings to /MT. I don’t know of any other way to solve the problem.

0
votes

If your .exe needs to run on a clean OS, it can't depend on any DLL's that are dynamically linked because these DLL's (and thus the .exe) can't load without the runtime DLL's. Have you considered an app-local deployment? Then both the .exe and dll can be built with /MD.

0
votes

It is possible to create a project that can build as either a DLL or a static library. The small launcher executable should link with the static library configuration of the DLL project.