Export All Symbols When Creating a Dll

Export all symbols when creating a DLL

Short answer

You can do it with help of the new version of the CMake (any version cmake-3.3.20150721-g9cd2f-win32-x86.exe or higher).

Currently it's in the dev branch.
Later, the feature will be added in the release version of the cmake-3.4.

Link to the cmake dev:

cmake_dev

Link to an article which describe the technic:

Create dlls on Windows without declspec() using new CMake export all feature

Link to an example project:

cmake_windows_export_all_symbols


Long answer

Caution:
All information below is related to the MSVC compiler or Visual Studio.

If you use other compilers like gcc on Linux or MinGW gcc compiler on Windows you don't have linking errors due to not exported symbols, because gcc compiler export all symbols in a dynamic library (dll) by default instead of MSVC or Intel windows compilers.

In windows you have to explicitly export symbol from a dll.

More info about this is provided by links:

Exporting from a DLL

HowTo: Export C++ classes from a DLL

So if you want to export all symbols from dll with MSVC (Visual Studio compiler) you have two options:

  • Use the keyword __declspec(dllexport) in the class/function's definition.
  • Create a module definition (.def) file and use the .def file when building the DLL.

1. Use the keyword __declspec(dllexport) in the class/function's definition


1.1. Add "__declspec(dllexport) / __declspec(dllimport)" macros to a class or method you want to use. So if you want to export all classes you should add this macros to all of them

More info about this is provided by link:

Exporting from a DLL Using __declspec(dllexport)

Example of usage (replace "Project" by real project name):

// ProjectExport.h

#ifndef __PROJECT_EXPORT_H
#define __PROJECT_EXPORT_H

#ifdef USEPROJECTLIBRARY
#ifdef PROJECTLIBRARY_EXPORTS
#define PROJECTAPI __declspec(dllexport)
#else
#define PROJECTAPI __declspec(dllimport)
#endif
#else
#define PROJECTAPI
#endif

#endif

Then add "PROJECTAPI" to all classes.
Define "USEPROJECTLIBRARY" only if you want export/import symbols from dll.
Define "PROJECTLIBRARY_EXPORTS" for the dll.

Example of class export:

#include "ProjectExport.h"

namespace hello {
class PROJECTAPI Hello {}
}

Example of function export:

#include "ProjectExport.h"

PROJECTAPI void HelloWorld();

Caution: don't forget to include "ProjectExport.h" file.


1.2. Export as C functions.
If you use C++ compiler for compilation code is written on C, you could add extern "C" in front of a function to eliminate name mangling

More info about C++ name mangling is provided by link:

Name Decoration

Example of usage:

extern "C" __declspec(dllexport) void HelloWorld();

More info about this is provided by link:

Exporting C++ Functions for Use in C-Language Executables


2. Create a module definition (.def) file and use the .def file when building the DLL

More info about this is provided by link:

Exporting from a DLL Using DEF Files

Further I describe three approach about how to create .def file.


2.1. Export C functions

In this case you could simple add function declarations in the .def file by hand.

Example of usage:

extern "C" void HelloWorld();

Example of .def file (__cdecl naming convention):

EXPORTS 
_HelloWorld

2.2. Export symbols from static library

I tried approach suggested by "user72260".

He said:

  • Firstly, you could create static library.
  • Then use "dumpbin /LINKERMEMBER" to export all symbols from static library.
  • Parse the output.
  • Put all results in a .def file.
  • Create dll with the .def file.

I used this approach, but it's not very convinient to always create two builds (one as a static and the other as a dynamic library). However, I have to admit, this approach really works.


2.3. Export symbols from .obj files or with help of the CMake


2.3.1. With CMake usage

Important notice: You don't need any export macros to a classes or functions!

Important notice: You can't use /GL (Whole Program Optimization) when use this approach!

  • Create CMake project based on the "CMakeLists.txt" file.
  • Add the following line to the "CMakeLists.txt" file:
    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
  • Then create Visual Studio project with help of "CMake (cmake-gui)".
  • Compile the project.

Example of usage:

Root folder

CMakeLists.txt (Root folder)

cmake_minimum_required(VERSION 2.6)
project(cmake_export_all)

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

set(dir ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${dir}/bin")

set(SOURCE_EXE main.cpp)

include_directories(foo)

add_executable(main ${SOURCE_EXE})

add_subdirectory(foo)

target_link_libraries(main foo)

main.cpp (Root folder)

#include "foo.h"

int main() {
HelloWorld();

return 0;
}

Foo folder (Root folder / Foo folder)

CMakeLists.txt (Foo folder)

project(foo)

set(SOURCE_LIB foo.cpp)

add_library(foo SHARED ${SOURCE_LIB})

foo.h (Foo folder)

void HelloWorld();

foo.cpp (Foo folder)

#include <iostream>

void HelloWorld() {
std::cout << "Hello World!" << std::endl;
}

Link to the example project again:

cmake_windows_export_all_symbols

CMake uses the different from "2.2. Export symbols from static library" approach.

It does the following:

1) Create "objects.txt" file in the build directory with information of .obj files are used in a dll.

2) Compile the dll, that is create .obj files.

3) Based on "objects.txt" file information extract all symbols from .obj file.

Example of usage:

DUMPBIN /SYMBOLS example.obj > log.txt

More info about this is provided by link:

/SYMBOLS

4) Parse extracted from .obj file information.

In my opinion I would use calling convection, for example "__cdecl/__fastcall", "SECTx/UNDEF" symbol field (the third column), "External/Static" symbol field (the fifth column), "??", "?" information for parsing an .obj files.

I don't know how exactly CMake parse an .obj file.
However, CMake is open source, so you could find out if it's interested for you.

Link to the CMake project:

CMake_github

5) Put all exported symbols in a .def file.

6) Link a dll with usage of a .def created file.

Steps 4)-5), that is parse .obj files and create a .def file before linking and using the .def file CMake does with help of "Pre-Link event".
While "Pre-Link event" fires you could call any program you want.
So in case of "CMake usage" "Pre-Link event" call the CMake with the following information about where to put the .def file and where the "objects.txt" file and with argument "-E __create_def".
You could check this information by creating CMake Visusal Studio project with "set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)" and then check the ".vcxproj" project file for dll.

If you try to compile a project without "set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)" or with "set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)" you will get linking errors, due to the fact that symbols are not exported from a dll.

More info about this is provided by link:

Understanding Custom Build Steps and Build Events


2.3.2. Without CMake usage

You simple could create a small program for parsing .obj file by youself without CMake usege. Hovewer, I have to admit that CMake is very usefull program especially for cross-platform development.

Exporting symbols when compiling DLL - MSVC

It is enough to export only the entry functions which are a part of API. No need to export static functions.

Also, no need to use __declspec(dllimport) for functions. It is needed only for data. Windows will automatically take care of doing the import incase of functions.

The below links can be helpful:

http://msdn.microsoft.com/en-us/library/ms235636(VS.80).aspx

http://msdn.microsoft.com/en-us/library/ms682589(VS.85).aspx

How to have CMake export symbols automatically on Windows?

According to WIN32 (LD):

… the default auto-export behavior will be disabled if either of the following are true:

  • A DEF file is used.

  • Any symbol in any object file was marked with the __declspec(dllexport) attribute.

In this case, the --export-all-symbols linker option forces the auto-export functionality and exports all symbols, except some special ones. Therefore, to also export bar_funcA without modifying C/C++ codes, add this line in src/bar/CMakeLists.txt:

target_link_options(bar PRIVATE "-Wl,--export-all-symbols")

Dll export symbol of function from static linked library

Coming back to all this, the answer was actually to #define LIB_EXPORT in the static library build as well which I did not expect.

I did not think that such a thing would be needed for a static .lib files since all they are is just a bundle of object files so they did not need to be marked for export. Apparently, it was needed if you want to export the functions from the static lib to your wrapper dll.

why the @number symbol at the end of an exported dll function

The "@n" is used by the stdcall calling convention. You don't need to mention it in your declaration, you just need to change your declaration to stdcall so that the compiler knows they need to be decorated with "@n" suffixes. Like this:

__declspec ( dllexport ) XLStatus __stdcall _xlActivateChannel(XLportHandle,  XLuint64, unsigned int, unsigned int)

Exporting static lib symbols from DLL

You will need to create a .def file and pass it to the linker. DLLEXPORT is not necessary in this case.

The reason for this is the way symbols are resolved when using a static library. When you create a DLL, only those symbols needed by the DLL itself are searched, and object files containing these symbols are copied into the DLL. If the DLL code does not reference your destructor, it will not be included.

A .def file will tell the linker which functions are exported. Exported functions will be searched and pulled from the static library.

One downside of this process is that you need to use mangled C++ names in the .def file. Mangled names can be obtained with the dumpbin utility.



Related Topics



Leave a reply



Submit