With VS2005, I want to create a DLL and automatically export all symbols without adding __declspec(dllexport) everywhere and without hand-creating .def files. Is threre a way to do this?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- How to know full paths to DLL's from .csproj f
- Importing NuGet references through a local project
相关文章
- 如何让cmd.exe 执行 UNICODE 文本格式的批处理?
- 怎么把Windows开机按钮通过修改注册表指向我自己的程序
- How to show location of errors, references to memb
- Warning : HTML 1300 Navigation occured?
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- How to track MongoDB requests from a console appli
It can be done...
The way we do it here is to use the /DEF option of the linker to pass a "module definition file" containing a list of our exports. I see from your question that you know about these files. However, we do not do it by hand. The list of exports itself is created by the dumpbin /LINKERMEMBER command, and manipulating the output via a simple script to the format of a module definition file.
It is a lot of work to setup, but it allows us to compile code created without dllexport declarations for Unix on Windows.
No, you will need a macro that resolves to
__declspec(dllexport)
when it's included by the .cpp file that implements the exported functions, and resolves to__declspec(dllimport)
otherwise.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:
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):
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:
Example of function export:
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:
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:
Example of .def file (__cdecl naming convention):
2.2. Export symbols from static library
I tried approach suggested by "user72260".
He said:
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!
Example of usage:
Root folder
CMakeLists.txt (Root folder)
main.cpp (Root folder)
Foo folder (Root folder / Foo folder)
CMakeLists.txt (Foo folder)
foo.h (Foo folder)
foo.cpp (Foo folder)
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:
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.
I've written a small program to parse the output of "dumpbin /linkermember" on the .lib file. I have upwards of 8,000 function references to export from one DLL.
The problem with doing it on a DLL is that you have to link the DLL without the exported definitions once to create the .lib file, then generate the .def which means you now have to relink the DLL again with the .def file to actually have the references exported.
Working with static libraries is easier. Compile all your sources into static libs, run dumbin, generate a .def with your little program, then link the libs together into a DLL now that the export names are available.
Unfortunately my company won't allow me to show you the source. The work involved is recognizing which "public symbols" in the dump output are not needed in your def file. You have to throw away a lot of those references, NULL_IMPORT_DESCRIPTOR, NULL_THUNK_DATA, __imp*, etc.
Thanks @Maks for the detailed answer.
Below is an example of what I used in Pre-Link event to generate def file from obj. I hope it will be helpful for someone.
Basically I just took one of objects (mdb.obj) and grepped mdb_* functions. Then parsed output to keep just names taking into account amount of spaces for indentation (one after splitting into tokens and another in echo. I don't know if it's matter though).
Real world script probably will kind of more complex though.