Short answer
You can do this with the new version of CMake (any version of cmake-3.3.20150721-g9cd2f-win32-x86.exe or higher).
This is currently in the developer's branch. This feature will later be added to the release version of cmake-3.4.
Link to cmake dev:
cmake_dev
Link to an article that describes the technique:
Create dlls on Windows without declspec () using the new export function of all CMake
Link to an example project:
cmake_windows_export_all_symbols
Long answer
Caution! All information below refers to the MSVC compiler or Visual Studio.
If you use other compilers, such as gcc on Linux or the MinGW gcc compiler on Windows, you will not have layout errors due to unexported characters, since the gcc compiler by default exports all characters to a dynamic library (dll) instead of MSVC or Intel compilers Windows.,
In windows, you must explicitly export the symbol from the DLL.
More information about this is provided at the links:
Export from DLL
How to: export C ++ classes from a DLL
So if you want to export all characters from a dll using MSVC (Visual Studio compiler), you have two options:
- Use the __declspec (dllexport) keyword in the class / function definition.
- Create a module definition file (.def) and use the .def file when building the DLL.
1. Use the __declspec (dllexport) keyword in the class / function definition
1.1. Add the macros "__declspec (dllexport) / __ declspec (dllimport)" to the class or method that you want to use. So if you want to export all classes, you must add these macros to all
More information on this is provided here:
Export from DLL using __declspec (dllexport)
Example of use (replace "Project" with the real name of the project):
// ProjectExport.h
Then add “PROJECT” to all classes. Define "USEPROJECTLIBRARY" only if you want to export / import characters from the dll. Define "PROJECTLIBRARY_EXPORTS" for the DLL.
Class export example:
#include "ProjectExport.h" namespace hello { class PROJECTAPI Hello {} }
Function export example:
#include "ProjectExport.h" PROJECTAPI void HelloWorld();
Note: do not forget to include the file "ProjectExport.h".
1.2. Export to C function. If you use the C ++ compiler for compilation code written in C, you can add extern "C" in front of the function to eliminate name distortion
More information on C ++ name distortion is provided here:
Name Decoration
Usage example:
extern "C" __declspec(dllexport) void HelloWorld();
More information on this is provided here:
Export C ++ functions for use in C language executables
2. Create a module definition file (.def) and use the .def file when building the DLL.
More information on this is provided here:
Export from DLL using DEF files
Next, I will describe three approaches to creating a .def file.
2.1. Export Functions C
In this case, you can simply add function declarations to the .def file manually.
Usage example:
extern "C" void HelloWorld();
Example .def file (__cdecl naming convention):
EXPORTS _HelloWorld
2.2. Export symbols from a static library
I tried the approach suggested by "user72260".
He said:
- First, you can create a static library.
- Then use "dumpbin / LINKERMEMBER" to export all the characters from the static library.
- Parse the output.
- Put all the results in a .def file.
- Create a dll using the .def file.
I used this approach, but it is not always convenient to create two assemblies (one as a static and the other as a dynamic library). However, I must admit that this approach really works.
2.3. Export characters from .obj files or using CMake
2.3.1. Using CMake
Important Note: You do not need export macros to classes or functions!
Important Note: You cannot use / GL ( Optimizing the entire program ) when using this approach!
- Create a CMake project based on the file "CMakeLists.txt".
- Add the following line to the CMakeLists.txt file: set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
- Then create a Visual Studio project using "CMake (cmake-gui)".
- Compile the project.
Usage example:
The 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 (folder Foo)
void HelloWorld();
foo.cpp (Foo folder)
#include <iostream> void HelloWorld() { std::cout << "Hello World!" << std::endl; }
Link to an example project again:
cmake_windows_export_all_symbols
CMake uses a different approach than "2.2. Exporting Symbols from a Static Library" approach.
This does the following:
1) Create a file "objects.txt" in the assembly directory with information about the .obj files used in the dll.
2) Compile the dll, i.e. create .obj files.
3) Based on the information in the "objects.txt" file, extract all the characters from the .obj file.
Usage example:
DUMPBIN /SYMBOLS example.obj > log.txt
More information on this is provided here:
/ SYMBOLS
4) Parsing extracted from .obj file data.
In my opinion, I would use calling convection, for example, "__cdecl / __ fastcall", the character field "SECTx / UNDEF" (third column), the character field "External / Static" (fifth column), "??", "? "information for analyzing .obj files.
I don’t know how exactly CMake parses the .obj file. However, CMake is open source, so you can find out if it is of interest to you.
Link to the CMake project:
CMake_github
5) Put all exported characters in a .def file.
6) Link the DLL using the .def file.
Steps 4) -5), that is, analyzing the .obj files and creating the .def file before linking and using the .def file that CMake does using the "Pre-Link event". While the "Pre-Link event" is triggered, you can call any program you want. Therefore, in the case of "using CMake" "Pre-Link Event", call CMake with the following information about where to put the .def file and where the "objects.txt" file is located and with the argument "-E __create_def". You can verify this information by creating a CMake Visusal Studio project using "set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)", and then check the project file .vcxproj for dll.
If you try to compile the project without "set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)" or with "set (CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF)", you will get layout errors due to characters not being exported from dll.
More information on this is provided here:
Understanding custom build steps and build events
2.3.2. Without using CMake
You can create a small program to parse the .obj file yourself without using CMake. However, I have to admit that CMake is a very useful program, especially for cross-platform development.