26

Is there any way to force visual studio to link all symbols from a lib file into the dll as atm it is optimizing "unused" functions which are needed by the program using the dll at run time.

I tried using the /OPT:NOREF and /OPT:NOICF but they dont seem to work.

The reason i need them is because they are global class which register them selves with a controller and they are not being linked in the dll.

Lodle
  • 31,277
  • 19
  • 64
  • 91

6 Answers6

23

I don't know if there's a more elegant way in Visual Studio, but the cross-platform solution we use it to have two macros that force the problamatic object file to be linked.

One is placed in the source file of functions that are being excluded, the other is placed in a function that the linker knows will be called.

Something like;

#define FORCE_LINK_THIS(x) int force_link_##x = 0;

#define FORCE_LINK_THAT(x) { extern int force_link_##x; force_link_##x = 1; }

It's not exactly elegant, but we haven't found a better solution that works across platforms.

Andrew Grant
  • 58,260
  • 22
  • 130
  • 143
  • 1
    `__declspec(dllexport)` and `__declspec(dllimport)` aren't enough because they declare (to the compiler) that code is in a DLL. This makes thunk-functions and .DEF-files unnecessary. Just a minor optimization: `#define FORCE_LINK_THAT(x) void force_link_function_##x(void) { extern int force_link_##x; force_link_##x = 1; }` allows the macro to be placed at the top of a file from which you know it will be linked. It makes no difference BTW that the dummy-function is never called. – Andreas Spindler Apr 26 '12 at 16:52
  • 1
    Also seems to work with a function with an empty body. Just call it someplace in the executable or dll that you are linking the lib into. – BigSandwich Jul 31 '13 at 15:21
9

There is actually a half-official solution to it, and here it is.

TL;DR:

'Use library dependency inputs'.

In VS lingo 'library dependency inputs' is a name for the obj files that constitute a library. You can actually control this behaviour in two scopes:

  1. Per refernce: by the 'use library dependency inputs' combo in the reference properties. This is the solution I used personally, and the one mentioned in the post. Use Library Dependency Inputs

  2. Per the entire executable: in the exe project properties /C++/Linker/General/ Use library dependency inputs -> Yes

The historical motivation for these arcane settings is enabling incremental linking in places it wasn't available before, but it has the useful side effect of linking directly against the obj files that are packaged in a lib, thereby constructing also unreferenced global objects.

Ofek Shilon
  • 14,734
  • 5
  • 67
  • 101
1

I had the same problem with a plugin system where factories in various DLLs were using a common main factory, everything registering at startup when loading libraries, without having to hard compile the list of plugins to use. This was working very well under Linux but had two problems under Windows:

  1. factories were not common between DLLs. This is not your problem but it is related. I got a solution here: Ensuring to use common fatories. Look at the answer by James with the set_the_global function.
  2. they were not setup at startup if no symbol of the DLL were used in the main. I think it is your problem. The only solution I found were to use configuration files (one by subproject) listing the names of the plugins (DLLs) available and force their linking using, in my case, QLibrary. Using cmake, a default version of a configuration file for each subproject is generated at build time using the following macro, called instead of add_library in each plugin dir:

    file(WRITE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-plugins "")
    macro (DECLARE_AMOSE_PLUGIN _plugin)
      file (APPEND ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-plugins "${_plugin}\n")
      add_library(${_plugin} SHARED ${${_plugin}_LIB_SRCS})
    endmacro (DECLARE_AMOSE_PLUGIN)
    
Community
  • 1
  • 1
Kleag
  • 642
  • 7
  • 14
0

I used a pragma, it seems to work, but doesn't choke if you don't include the line.

#include "library1.h"
#include <QApplication>
#pragma comment(lib, "C:\\Qt\\5.5\\msvc2013_64\\lib\\Qt5Guid.lib")
PHI_STATUS PHI_EXP_CONV PHI_ShowGUI(size_t reserved)
{
    QApplication app(none, nullptr);
    ...
}

You can also link them via the Additional Dependencies field in the Librarian tab.

Mikhail
  • 7,749
  • 11
  • 62
  • 136
-1

Tested in MSVC2k17...

__pragma(comment(linker,"/export:REGISTERfunc"));
void REGISTERfunc() { printf("I'm linked!\n" ); }

Totally works. This can even be inside a statically linked .lib and will carry through all the way to the output executable and beyond!

EDIT: You can even put it in a macro for bonus awesome points!

EDIT: Another note: You must link-time code generation enabled. /LTCG ... something

Charles Lohr
  • 695
  • 1
  • 8
  • 23
-1

How is the DLL going to call the functions from your lib at runtime? That sounds a bit hard to believe.

Now if users of the DLL are going to call your library functions, your question makes sense. Windows compilers (unlike Unix compilers) only export functions from a DLL if explicitly requested. The most common way to do this is to declare the function "dllexport", but you can also name the functions in a .DEF file as pass it to the linker. Note that you need to list the C++ mangled name in the .DEF file.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • because they are global class which reg them selves with a controller and they are not being linked in the dll. – Lodle Mar 02 '09 at 12:06
  • Would be useful to put that in the question, then. It's a good question, with that addition, but different from what you asked now. – MSalters Mar 03 '09 at 12:08