Generation and deployment of dynamic libraries (.dll and .a files) under IDE/mingw (compared to .dll and .lib under MSVC)

Article directory

  • overview
  • problem generation
    • DLL dynamic library based on mingw
    • EXE executable program based on mingw
    • \*.a files using the Qt library in the Makefile
    • Who works under *.a files and *.dll under mingw
    • episode
  • What exactly is the \*.a file generated by mingw
  • Why mingw’s dll can be used to compile and link the process
  • convert to lib boot file

Overview

This article introduces the dynamic library generation and usage method under the QtCreator + mingW integrated development environment, focusing on the analysis of the function of the *.a file generated after the dynamic library project is compiled under mingw. This article also compares and analyzes the differences between the deployment and use of dynamic libraries under mingw and the generation and use of dynamic libraries under MSVC.
When using the MingW compiler, no .lib boot file is generated, so how does mingW complete the dynamic library linking process? And experience tells us that under mingw, when an executable program uses a dll, it can directly point to the dll file for compilation and linking. How does it do it?

Regarding the DLL generation and deployment in the VS integrated development environment, please refer to “IDE/DLL Dynamic Library Deployment and Loading Problem Analysis under VS” for better comparison and analysis.

MinGW provides a development environment that facilitates the development of C, C++, and other programming languages on the Windows platform. Developers can use the tools and libraries provided by MinGW to write Windows applications without relying on Microsoft Visual Studio or other commercial development tools. MinGW is a branch based on the GNU tool set, which allows developers to use Linux-like development tools in the Windows environment, such as GCC compiler, GNU Make, etc., as well as some commonly used library files, such as C/C++ runtime Time library, header files for Windows API, etc.

Generation of the problem

The overall directory distribution of Demo code, E:\TestDll, consists of: bin, bin_d, DllOfMingw, ExeOfMingw directories, DllOfMingw.pro is located in DllOfMingw directory; ExeOfMingw.pro is located in ExeOfMingw directory. For special test steps, the E:\TestDll\lib directory is also set.

DLL dynamic library based on mingw

Under the Qt Creator File menu, select New File or Project, in the pop-up tab, select Library – C++ Library, and create a new project named DllOfMingw.

Qt modules choose Qt nothing, Kits choose Mingw 64…

//DllOfMingw.pro
CONFIG -= qt

TEMPLATE=lib
DEFINES += DLLOFMINGW_LIBRARY

CONFIG+=c++11

Debug:DESTDIR=$$PWD/../bin_d
Debug: TARGET = dllofmingw_d

Release: DESTDIR = $$PWD/../bin
Release: TARGET = dllofmingw

SOURCES + = \
    dllofmingw.cpp

HEADERS + = \
    dllofmingw.h \
    dllofmingw_global.h

DEFINES += QT_DEPRECATED_WARNINGS
//dllofmingw_global.h
#ifndef DLLOFMINGW_GLOBAL_H
#define DLLOFMINGW_GLOBAL_H

#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#define Q_DECL_EXPORT __declspec(dllexport)
#define Q_DECL_IMPORT __declspec(dllimport)
#else
# define Q_DECL_EXPORT __attribute__((visibility("default")))
# define Q_DECL_IMPORT __attribute__((visibility("default")))
#endif

#if defined(DLLOFMINGW_LIBRARY)
#define DLLOFMINGW_EXPORT Q_DECL_EXPORT
#else
#define DLLOFMINGW_EXPORT Q_DECL_IMPORT
#endif

#endif // DLLOFMINGW_GLOBAL_H
//dllofmingw.h
#ifndef DLLOFMINGW_H
#define DLLOFMINGW_H
#include <string>
#include "dllofmingw_global.h"

class DLLOFMINGW_EXPORT DllOfMingw
{<!-- -->
public:
    DllOfMingw();
public:
    std::string InvokeTest();
};
#endif // DLLOFMINGW_H
//dllofmingw.cpp
#include "dllofmingw.h"

DllOfMingw::DllOfMingw() {<!-- --> }

std::stringDllOfMingw::InvokeTest()
{<!-- --> return "Dll Interface was invoked!"; }

Compile the above project in Debug mode, and generate two files in the E:\TestDll\bin_d directory,

What they do, especially what libdllofmingw_d.a does, will be discussed later.

EXE executable program based on mingw

Under the Qt Creator file menu, select New File or Project, in the pop-up tab, select Application, and create a new Qt console project named ExeOfMingw. Select the same Kits settings as the DLL project. The project creation is consistent with the DLL, both are in the E:\TestDll directory.

//ExeOfMingw.pro
QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES + = \
        main.cpp

# you'd better build a public include
INCLUDEPATH += $$PWD/../DllOfMingw

win32 {<!-- -->
    Debug:LIBS += -L$$PWD/../bin_d\
                     -ldllofmingw_d

    Release:LIBS + = -L$$PWD/../bin\
                      -ldllofmingw
}

# .exe's dir same as .dll file
Debug:DESTDIR=$$PWD/../bin_d
Release: DESTDIR = $$PWD/../bin
//mian.cpp
#include <QCoreApplication>
#include <QDebug>
#include "dllofmingw.h"

int main(int argc, char *argv[])
{<!-- -->
    QCoreApplication a(argc, argv);

    DllOfMingw aDll;
    qDebug() << QString::fromLocal8Bit(aDll.InvokeTest().c_str());

    return a.exec();
}

The *.a file using the Qt library in the Makefile file

Under the above test code, both DLL and EXE can be compiled and executed normally. Running can output “Dll Interface was invoked!”…

I found out when sorting out other integrated development environment related issues before that in the Makefile file, the reference to the Qt library in LIBS used *.a files, which were only recorded and not studied in detail at that time. Take the above normal compiled and running code as an example, open the Makefile.Debug file in the compilation directory of the ExeOfMingw project,

LIBS = -LE:\TestDll\bin_d -ldllofmingw_d D:\Qt\Qt5.12.8\5.12.8\mingw73_64\lib\libQt5Cored.a

The relevant compilation output at this time, the screenshot is as follows, can be matched with the makefile,

Unfortunately, we cannot judge which of dllofmingw_d.dll and libdllofmingw_d.a is used by ExeOfMingw in the compilation phase through the content marked in the red box. However, seeing that ExeOfMingw refers to the libQt5Cored.a file in LIBS, we probably first guessed that “-LE:\TestDll\bin_d -ldllofmingw_d” will point to the $$PWD/…/bin_d/libdllofmingw_d.a file, but Is this the case?

Who works under *.a files and *.dll under mingw

Simply combining the relevant theoretical knowledge of dynamic library deployment and execution under VS, DLL should not be related to compilation! But past experience has told us that under the mingw compilation suite, the dll file seems to play a role in the compilation process. To this end, we will gradually launch the test on the basis of the above-mentioned normal compilation and deployment of the program. Note that in order to ensure the reliability of the test, I manually delete the process files generated by the last compilation before each recompilation.

Test-1
We focus on the libdllofmingw_d.a file, and guess that it may play the same role as the dynamic library boot file under the MSVC compiler. To this end, we delete the E:\TestDll\bin_d\libdllofmingw_d.a file, and re-execute the ExeOfMingw compilation, no compilation exception occurs, and the operation is correct.
Test-2
Then we restored libdllofmingw_d.a, deleted dllofmingw_d.dll, and re-executed ExeOfMingw compilation again, and there was no compilation exception. dll is loaded and used at runtime, without it, the program will definitely not run normally.
Test-3
We have tested in the “IDE/Integrated Development Environment Qt Creator + MSVC Compiler + CDB Debugger” article, in the case of using the MSVC compiler, the LIBS in the pro project file must be configured with the path of the dynamic library boot file lib and name, otherwise it will fail to compile. In the previous test, we only deleted one of dllofmingw_d.dll or libdllofmingw_d.a each time, what if delete both?

Well, the compilation reported an error, and the specified dllofmingw_d library could not be found. And the meaning here should be: neither dllofmingw_d.dll nor libdllofmingw_d.a file was found. Because, as long as there is one of them, there is no compilation error.
Another round of regression testing,
Just add dllofmingw_d.dll back to E:\TestDll\bin_d, compile ExeOfMingw without error, run without error.
Just add libdllofmingw_d.a back to E:\TestDll\bin_d, compile ExeOfMingw without errors, but the program doesn’t run normally.
Test-4
Let’s be serious, when using the migw compiler, if I don’t configure LIBS,

Interim conclusions,
When referencing the DLL compiled by mingw, the LIBS path and files must also be configured, but for the compilation process, as long as there is any one of dllofmingw_d.dll or libdllofmingw_d.a, the compilation process can be passed. So guess what? The *.lib files and *.a files generated when mingw compiles the dynamic library project can be linked to the executable program that calls it during the compilation process.

Verify *.a file support for compilation process,
Further, we separate *.a from the bin folder and put it in a separate E:\TestDll\lib folder, dllofmingw_d.dll is still placed under E:\TestDll\bin_d, and modify ExeOfMingw accordingly. The LIBS configuration in the pro file,

win32 {<!-- -->
    Debug:LIBS += -L$$PWD/../lib\
                     -ldllofmingw_d

    Release:LIBS += -L$$PWD/../lib\
                      -ldllofmingw
}

After testing, it can pass the compilation process and run without any exceptions.

A few final conclusions,

  • The dynamic library reference under mingw also requires LIBS configuration.
  • The lib*.a files generated when compiling dynamic library projects under mingw can be used for compiling and linking.
  • And in the project built by qmke, the reference to the Qt framework library, the LIBS configuration is the file of type *.a.
  • If there is no *.a file, only the .dll file generated under mingw can also support the compilation and linking process.

From this point of view, for dynamic library projects, it is not a big problem to compare the *.a files under mingw to the *.lib boot files under MSVC. Their naming methods and functions are basically the same. The big difference is that the .dll files under mingw can also participate in the compilation and linking process, while the .dll files generated under msvc do not have this function.

Vignette

During a certain test phase, I encountered the following exception. There is no problem with the compilation, but the program always fails to start, even the main function cannot enter.

Tried, restarting QtCreator did not take effect. “qtcreator_process_stub.exe” is a helper process in Qt Creator for interacting with the application being debugged. It allows Qt Creator to communicate with the application, set breakpoints, inspect variables and control the debugging process. As in the above error message, the “qtcreator_process_stub.exe” process cannot be started, but returns “operation completed successfully”, which means that the execution of the process itself has no error, and the process exit code returned by the operating system is “0”, which means the process exited normally.

I copied dllofmingw_d.dll and ExeOfMingw.exe to the bin library corresponding to Qt to execute, no problem. I shut down and restarted the PC, still to no avail. So, I commented out all the references to the dynamic library, but it didn’t help. I just created a new console application to test whether there is any problem with my IDE environment? The result is sad, and it can’t be used. Could it be that my IDE was tripped by Qt company?
Use Everything to search for qtcreator_process_stub to find it, D:\Qt\Qt5.9.3\Tools\QtCreator\bin, and use the command window to execute it,

Combined with this situation, what I can think of is that the anti-virus software may be turned on, and sure enough, after the above-mentioned files are restored from the quarantine area, the relevant problems will be resolved by themselves.

What is the *.a file generated by mingw

Under VS & amp; MSVC, when we use the dynamic library implicit loading method, we must have a dynamic boot file of *.lib to compile normally. There is no *.lib file generated under mingw, the *.a file looks a bit similar to the *.lib under MSVC, but at this time I am still not sure what the *.a file is? Some information shows that *.a files are static library files, but I think this is the same as someone saying that *.lib files under MSVC are static library files.

To further explain, *.a files under mingw are not static library files, we create a static library project under mingw, implement it as DLL consistency, and compare them.

Under the Qt Creator file menu, select a new file or project, and in the pop-up tab, select Library – C++ Library, the project name is SllOfMingw, and the creation path is E:\TestDll, which is consistent with the DLL project. Select the project type as Statically Linked Library statically linked library. Qt module is still none, it has nothing to do with Qt, and Kits also chooses mingw 64… Make the same implementation of SllOfMingw class and DllOfMingw class…

Observing the static library project, it is found that there is no export macro definition such as dllofmingw_global.h under the DLL project; compared with the DLL, the pro file has an extra CONFIG + = staticlib configuration. In order to have better comparability, we implement SLL and DLL as the same interface and attributes.

//SllOfMingw.pro
CONFIG -= qt
CONFIG+=c++11

TEMPLATE=lib
CONFIG += staticlib

DEFINES += QT_DEPRECATED_WARNINGS

Debug:DESTDIR=$$PWD/../bin_d
Debug: TARGET = sllofmingw_d

Release: DESTDIR = $$PWD/../bin
Release: TARGET = sllofmingw

SOURCES + = \
    sllofmingw.cpp
HEADERS + = \
    sllofmingw.h
//sllofmingw.h
#ifndef SLLOFMINGW_H
#define SLLOFMINGW_H

#include <string>

class SllOfMingw
{<!-- -->
public:
    SllOfMingw();
public:
    std::string InvokeTest();
};

#endif // SLLOFMINGW_H
//sllofmingw.cpp
#include "sllofmingw.h"

SllOfMingw::SllOfMingw() {<!-- --> }

std::string SllOfMingw::InvokeTest() {<!-- -->
    return "Sll Interface was invoked!"; }

After the compilation is complete, it can be seen that the static library project only generates a static library file named libsllofmingw_d.a, as marked in the red box below.

in addition,
We also noticed that although they all have the suffix of the .a static library file type, the real static library file libsllofmingw_d.a is an order of magnitude larger than the fake static library file libdllofmingw_d.a. Therefore, it can be concluded that libdllofmingw_d.a is not a real static library file, which is exactly the same as the *.lib file compiled and generated under MSVC is not a real static library file. Like the .lib guide file under MSVC, the .a type file generated by the mingw dynamic library project also has the ability to participate in the compilation and linking process. Gu, the .a file at this time can also be called the dynamic library guide under mingw document.

Why mingw’s dll can be used to compile and link the process

First give yourself the linking process of the compiler,
The linking process of the compiler is the process of merging multiple compiled object files (usually .obj files) and library files (static or dynamic) into a final executable or shared library. The connection process of the connector Linker is usually divided into the following steps:
Symbol Resolution (Symbol Resolution): The linker first needs to resolve symbol references in the object file. A symbolic reference refers to a reference to a function, variable, and other symbols defined in another object file or library file in one object file.
Address Relocation (Address Relocation): After resolving symbolic references, the linker needs to address the references. This is because the symbol addresses in the object file are relative to the object file itself, and the linker needs to correct these addresses according to the location of the object file in the final executable file or shared library.
Combine object files: The linker combines all object and library files into a single executable or shared library. This step usually includes resolving symbol conflicts and organizing the code and data in all object files and library files together according to certain rules.
Generate executable or shared library: The linker will combine the object files and library files to generate the final executable or shared library. When generating an executable file, the linker will set the correct entry address for the entry point of the program, so that the program can start executing correctly.

A special method of dynamically linking DLLs,
Mingw uses the DLL itself as the boot file of the dynamic library, mainly because it uses a link method called “Load-Time Dynamic Linking”. This is a way to dynamically link DLLs when the program loads. When the program starts, Mingw will parse the export table of the DLL file and bind the address of the symbol in the DLL to the corresponding symbol in the program. In this way, during the running of the program, when the function in the DLL needs to be called or the data in the DLL is used, the program can be called directly through the bound address without further dynamic linking.
The advantage of this link method is that all dynamic link operations have been completed when the program starts, so the functions in the DLL can be called faster at runtime, avoiding the dynamic link overhead at runtime. In addition, since Mingw is an open source compiler, it is not subject to specific commercial constraints and restrictions like MSVC. Therefore, Mingw can handle dynamic linking more flexibly, choosing to use the DLL itself as the boot file of the dynamic library. This method simplifies the compilation and linking process to a certain extent, making Mingw more convenient to integrate and use with open source DLL libraries.

Convert to lib guide file

Normally, the DLL generated by Mingw can be used in the compilation and linking process because it uses a runtime library compatible with MSVC and can be linked with the executable file compiled by MSVC. The DLL generated by MSVC cannot be directly linked with the executable file compiled by Mingw because it uses its own runtime library. If you need to use the DLL generated by Mingw in the project compiled by MSVC, some additional configuration and adaptation work is required.
But also note that DLL files compiled with MinGW often depend on MinGW’s runtime libraries (such as mingw32.dll), which may not exist or be compatible on systems without MinGW. So you need to make sure that these dependencies are included in the generated DLL file. This kind of cross-compiler replacement is not a simple matter, and it is not recommended to do so unless it is a last resort.

Next we will try to convert the DLL generated by the DllOfMingw project into a library that can be used under mscv…

Find the gendef.exe tool under D:\Qt\Qt5.12.8\Tools\mingw730_64\bin, which generates .def files from DLL files.

It has been successfully generated, D:\Qt\Qt5.12.8\Tools\mingw730_64\bin\dllofmingw_d.def, haha, there must be other command parameters, so I haven’t studied it further. Directly cut dllofmingw_d.def to my project file directory E:\TestDll\bin_d, proceed to the next step,
Open a Visual Studio developer command prompt and use the lib command to generate a .lib file. The command is as follows,

As above, two files, .lib and .exp, are generated at the same time.

Next, we create a new VS project, and there is no problem with dynamic library deployment and code, but I did not succeed. compile error,

#include <stdio.h>
#include "dllofmingw.h"

int main()
{<!-- -->
    DllOfMingw aDll;
    printf("%s", aDll.InvokeTest().c_str());

    system("pause");
    return 0;
}

//ExeOfVS.obj : error LNK2019 : Unresolved external symbol "__declspec(dllimport) public: __cdecl DllOfMingw::DllOfMingw(void)" (__imp_ ? ? 0DllOfMingw@@QEAA@XZ), the symbol is in the function main quoted
//ExeOfVS.obj : error LNK2019 : Unresolved external symbol "__declspec(dllimport) public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl DllOfMingw ::InvokeTest(void)" (__imp_ ? InvokeTest@DllOfMingw@@QEAA?AV ? $basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ), the Symbol is referenced in function main
//..\bin_d\ExeOfVS.exe : fatal error LNK1120 : 2 unresolved external commands

Through the above warning information, I found that the export symbols prompted are not consistent with the definitions in dllofmingw_d.def.

//dllofmingw_d.def
;
; Definition file of dllofmingw_d.dll
; Automatically generated by gendef
; written by Kai Tietz 2008
;
LIBRARY "dllofmingw_d.dll"
EXPORTS
_ZN10DllOfMingw10InvokeTestB5cxx11Ev
_ZN10DllOfMingwC1Ev
_ZN10DllOfMingwC2Ev

I don’t have time to continue with this question, so I can only give up for now. The last section does not fit well with the main purpose of this article. If there is a chance in the future, I will start it separately and continue.