Original address: blog.kitware.com/create-dlls…

The original author: blog.kitware.com/author/bill…

Release time: July 24, 2015

CMake 3.4 will have a new feature to simplify porting C and C++ software from Linux/UNIX to Windows using shared libraries. Linux/UNIX developers are often surprised to find that creating a shared library called a DLL (dynamic link library) on Windows requires modifying the source code or explicitly listing all symbols that the DLL will export. Compilers on Linux/UNIX have the ability to automatically export all symbols from shared libraries. On Windows, you must use the compiler directives __declspec(import) and __declspec(export) to declare which symbols will be exported/imported from the shared library, or you must create a module definition text file (.def) that contains a list of all symbols you want to export, And pass the file to the linker.

With the C library, it is not difficult to create a. Def file manually or automatically, because you only need to list the names of all the functions in the library. However, with C++ code, it is almost impossible to make a. Def file by hand because of the confusion of names and the number of functions. The standard workaround is to use the preprocessor to conditionally insert __declspec(import) and __declspec(export) into the code. However, with a large existing C++ code base, editing all the source code can be difficult and time-consuming. CMake now has a feature that allows it to query the.obj files that make up DLLS and automatically create a.def file, in most cases without modifying the original source code.

This is done in CMake with a new target property WINDOWS_EXPORT_ALL_SYMBOLS. When enabled, this property causes CMake to automatically create a.def file that contains all symbols found in the input.obj file of the SHARED library on Windows. The.def file will be passed to the linker, causing all symbols to be exported from the DLL. For global data symbols, __declSpec (DLlimPort) must still be used when compiling against code in DLLS. The symbol is automatically exported from the DLL correctly, but the compiler needs to know that it was imported from the DLL at compile time. All other function symbols are automatically exported and imported by the caller. This simplifies porting projects to Windows and reduces the need for explicit dllexport tags, even in C++ classes. When creating a target, this property is initialized by the value of the CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS variable.

To try this feature in an existing project, run the following command

cmake -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE
Copy the code

On the CMake project. This will make all add_library calls without an explicitly specified build type a shared build. If there are no global data variables in the project, all libraries are built as DLLs with no errors. If you encounter undefined symbols, examine global data, such as static data members of a class. The easiest way to process global data is to use the CMake GenerateExportHeader module, like this.

add_library(mylibrary ${mylibrary_SOURCES})
# add these lines
include(GenerateExportHeader)
generate_export_header(mylibrary)
Copy the code

Edit the source code like this.

#include <mylibary_export.h>
class myclass
{
 static mylibrary_EXPORT intGlobalCounter; ...Copy the code

Note that if you use GenerateExportHeader and still want static builds to work, you need to add -dmyLIBRARY_static to the static build process. See the generated mylibary_export.h for more details.

Practical application cases

After adding this functionality to CMake, I tried it out on two of the larger software projects VXL (vxl.sourceforge.net/) and ITK (www.itk.org). Although it did take some time, it was much easier than adding DLL tags to every source file. In the end, the changes required are among the following recurring problems and fixes.

  • Handles class static data members
    • Add DLL import/export macros to static data.
    • Eliminate static data –
      • This can be done by doing a static getter function with a local static variable.
  • Static members
    • None of this can be exported by the new feature. In some cases, to support older compilers, these are placed in.cxx files and compiled into libraries, rather than just inline in.h files. If you have this situation, you need to use the DLlimPort and DLlexport tags, not just the DLlimPort tag, because automatic export will not work.
  • Inherit the DLlimPort/DLlexPort tag from STD :: String or another template class.
    • This can lead to repeated symbol errors in the parent template class in some cases. The solution to this problem is to remove the tag and let the automatic export do its job.
class mylibrary_EXPORT myclass public std::string
{
..
Copy the code
  • There are no fully linked libraries. On many Unix systems, the linker allows shared libraries to be created with unparsed symbols that should be parsed when linking executable files. Windows DLLS must parse all symbols, so your library must explicitly link to everything it depends on. If you get an undefined symbol while linking, one way is to look for the symbol’s presence in the larger system in the.def file you created. From a bash (Cygwin or Git) shell, you can run such programs.
 find . -name "*.def" | xargs grep symbol
Copy the code
  • Static data member of a templated class. It is best to avoid these directly, or to use explicit instantiation or specialization only for these. There’s no way I can make this work.

Thank you

I would especially like to thank Valeri Fine and Bertrand Bellenot and the rest of the ROOT team at CERN for contributing.obj file symbol parsing code and testing it on their projects. Please appreciate

link

Night CMake new features: www.cmake.org/files/dev/c…

Evening papers are special topics.

www.cmake.org/cmake/help/…

The function of the ITK changes: review.source.kitware.com/#/c/20020

VXL changes to this feature: github.com/vxl/vxl/pul…

Valeri Fine presented the method and presented the original code at the Lichtenberger Conference, the Center for Computing in High Energy Physics, Berlin, 7-11 April 2977.

www.ifh.de/CHEP97/abst…

www.ifh.de/CHEP97/pape…


Translation via www.DeepL.com/Translator (free version)