When it comes to Wine, most seasoned Linux users have heard of it, but when asked to explain exactly what Wine is, many might not be able to articulate it clearly. This article will provide a simple introduction to how Wine works and how to start developing with Wine. So, if you fall into one of the following three categories of readers:
You want to participate in Wine development but don't know where to start.
You just want to have a general understanding of how Wine works.
You simply want to enjoy using the latest version of Wine.
Hopefully, after reading this article, you will gain some insights.
Part 1: What is Wine?
Wine is a recursive acronym for "Wine Is Not an Emulator," similar to "GNU" (GNU's Not Unix). This means that Wine is not an emulator in the traditional sense. Specifically, it is not a virtual machine but rather a compatibility layer that implements the Windows API. To put it in perspective, you can think of Windows applications as being similar to Android applications, and Wine plays a role akin to Android. It encapsulates the various functionalities provided by the operating system into APIs and allows applications to run in an isolated environment. The specifics of what the API looks like and the extent of the isolation are implementation details and do not conflict with the fundamental concept. On another level, Wine can also be considered a simulator, but instead of simulating hardware like a CPU, it simulates the behavior of Windows.
Part 2: Introduction to Wine's Principles
This section is relatively basic and singular, and it is best to have a certain understanding of operating systems when reading. If you are only interested in compiling and running Wine and are not interested in the principles, you can skip this part without affecting your understanding of the subsequent content.
The purpose of Wine is to run executable programs on Windows (PE, portable executable). We know that the essence of an executable program is machine code arranged according to certain rules, and machine code is related to the instruction set. Thanks to the fact that most PCs are x86/x64, Windows applications can theoretically run directly on x86/x64 Linux machines from the perspective of the instruction set, without the need for hardware-level simulation.
However, to directly load and run PE files, certain ABI compatibility is required. For example, Windows PE programs assume that they are loaded at address 0x400000, so when Wine implements its own loader, it needs to ensure that the PE image is loaded to the same location. For statically linked programs, there may not be much to do, but for dynamically linked programs, Wine needs to mimic the behavior of the Windows loader, loading dependent libraries and performing the necessary relocation work.
To minimize dependence on the binary level, Wine decided to implement at least the GDI32, KERNEL32, and USER32 dynamic libraries, as other libraries are built on the foundation of these three. In theory, other dynamic libraries could directly use existing libraries from Windows, but for various reasons, Wine tends to implement as many APIs as possible. We refer to the API libraries implemented by Wine itself as "builtin" and those from Windows as "native." When Wine loads builtin dynamic libraries, it also establishes a PE header in memory to mimic the memory layout on Windows. A more detailed implementation could be the subject of a future article on Wine's loader, explaining how Wine itself, PE programs, and dynamic libraries are loaded.
In addition to the loader's functionality, Wine also needs to address inter-process communication (IPC) issues. Wine's approach is to implement all cross-process objects and mechanisms, such as GDI objects and semaphores, within the Wine server. Wine also allows the system to run multiple instances of the Wine server. Objects within the same Wine server can naturally communicate with each other as if they were in the same space, while objects under different Wine servers are isolated from each other. This architecture ensures that programs in different containers do not affect each other. The specific implementation of the Wine server is through Unix sockets, which provide an IPC mechanism for interaction with the API layer.
With these foundations in place, Wine can systematically implement various features. It simply involves understanding the behavior and meaning of APIs under Windows and then re-implementing them. Although it sounds simple, the actual difficulty is not small, especially for some undocumented behaviors, which require a considerable understanding of the overall system before they can be addressed. Even some differences, such as UI-related content, require selective implementation due to the different design philosophies between the Windows window system and X. Currently, Wine supports not only Linux but also BSD, Mac OS X, and Android.
Part 3 Environment
The following development environment is described using deepin as an example.
First, obtain the code. The official Wine code repository address is:
git://source.winehq.org/git/wine.git
If you want to conveniently package it for others to use and don't want to deal with the details of packaging, you can use the Wine maintained by each distribution. For example, the Debian-maintained Wine repository address is:
https://salsa.debian.org/wine-team/wine.git
Here, we will use the official Wine as an example:
git clone git://source.winehq.org/git/wine.git
Next, install the dependencies required for development. For simplicity, we will only compile 32-bit Wine, as 64-bit Wine only supports 64-bit PE programs, and there are still many programs on Windows that are only available in 32-bit versions.
Depending on the version of Wine, you may see different feature support messages at this point. You can adjust the dependencies and parameters based on your needs, and for more details, you can check the contents of configure.ac.
The Wine source code is quite large, and compilation can be time-consuming. You can increase the parallelism parameter based on your CPU's capabilities, for example, using make -j8 for compilation.
After compiling, run:
./wine --version
to check the version number. If you want to install it to the system, you can run:
sudo make install
However, note that installing it may change the default file associations.
Part 4 Usage
Run the following command:
./wine winecfg
This will allow you to configure the default container. The default container is located in the .wine directory under your HOME directory. The WINEPREFIX environment variable is used to modify the current container path. For example, if you have an executable file called demo.exe and you want to test whether it can run normally, you can run:
WINEPREFIX=~/.demo_exe ./wine demo.exe
The demo_exe directory under your HOME directory will be used as its container directory.
Part 5 Development
After compiling, the directory structure of the Wine source code is as follows:
The dlls directory contains the implementations of all APIs, organized by module.
The loader directory includes code related to the startup and loading of Wine.
The programs directory stores the code for external programs, such as the registry management tool regedit.
The server directory, as the name suggests, is the implementation of the Wine server.
From here, the process is similar to regular development. For example, if we find a font-related bug in a certain application, we can first use our experience to determine how the program is implemented on Windows, and then check the corresponding implementation. For instance, the GDI-related font implementation is located in dlls/gdi32/font.c and dlls/gdi32/freetype.c. After modifying the code, you can quickly verify it by running make in the module's directory, such as dlls/gdi32 in the example above.
For complex issues that are not easily located, you can use logging for debugging. The WINEDEBUG environment variable specifies the logs that need to be output.
Sometimes, we may need to simplify complex situations, which often involves writing small demo programs to reproduce the problem. If you don't want to compile on Windows, you can use mingw to directly compile exe files on deepin. The process is straightforward: first, install mingw:
sudo apt install mingw-w64
Then, implement the program using the Windows API as usual, and finally use the mingw toolchain to generate the file. Here's an example Makefile:
In the example above, UNICODE is defined, so the program uses the UNICODE version of the API with the entry function wmain. The -lgdi32 flag indicates that the gdi32 library needs to be linked. The resulting hello.exe can run on both Windows and deepin.
Part 6 Other Considerations
This article only covers the basics of Wine development. There is much more to explore in Wine itself. For example, how does Wine use a driver mechanism to separate interfaces from implementations? Or how does Wine implement the COM mechanism using pure C? Although Wine has been around for some time, its development is still very active. Interested students can join in and contribute to the Linux ecosystem, allowing everyone to access more high-quality applications. This can be considered a form of indirect support for the community.
Part 7 Updates
7.1 New WOW64
In the previous compilation example, we only compiled 32-bit Wine and omitted the details of compiling 64-bit Wine. Starting from Wine 8, Wine began a development process called PE Conversion, which re-implemented the WOW64 mechanism. In this mode, you only need to compile one version of Wine, which can run both 32-bit and 64-bit programs. It also no longer relies on 32-bit runtime libraries. Although this mode is still considered experimental, it has been the default method since deepin-wine8.
To compile Wine with the new WOW64 mechanism, follow these steps:
You still need to install the development libraries required for compilation, but this time you only need to install the amd64 versions. When installing development libraries, you no longer need to specify the :i386 suffix. Additionally, mingw-w64 is now a requirement in this mode.
Create a new directory called build-wine at the same level as the Wine source code directory, and navigate into this directory.
Run ../wine/configure --prefix=/opt/wine-newwow64 --enable-archs=i386,x86_64. If there are any prompts, such as missing compilation dependencies, you can run the command again after installing the necessary packages.
Compile with make -j8.
Install with sudo make install. Wine will be installed in the location specified by the prefix in step 4, i.e., /opt/wine-newwow64. Of course, you can also choose not to install and run it directly from the compilation directory.
7.2 Other Architectures
As mentioned in the section on principles, Linux systems on x86/x64 machines can run x86/x64 PE programs through Wine. In fact, with the advancement of DBT (dynamic binary translation) technology, there are now solutions for running Wine on ARM and other architectures. Interested readers can check out the Box64 project.
In November, WeChat released a native Linux version on the deepin store, with functionalities that are almost identical to those on Windows and macOS. The Wine version of WeChat can finally "retire," and we look forward to more software releasing native versions in the future, allowing Wine to complete its "historical mission" sooner.
Regarding the link to the Box64 project, I encountered some issues while trying to parse it. This could be due to the link itself or network-related issues. I recommend checking the validity of the link and trying again. If you have any other questions or need assistance with something else, feel free to ask!
Click: https://www.deepin.org/en/getting-started-with-wine/
When it comes to Wine, most seasoned Linux users have heard of it, but when asked to explain exactly what Wine is, many might not be able to articulate it clearly. This article will provide a simple introduction to how Wine works and how to start developing with Wine. So, if you fall into one of the following three categories of readers:
Hopefully, after reading this article, you will gain some insights.
Part 1: What is Wine?
Wine is a recursive acronym for "Wine Is Not an Emulator," similar to "GNU" (GNU's Not Unix). This means that Wine is not an emulator in the traditional sense. Specifically, it is not a virtual machine but rather a compatibility layer that implements the Windows API. To put it in perspective, you can think of Windows applications as being similar to Android applications, and Wine plays a role akin to Android. It encapsulates the various functionalities provided by the operating system into APIs and allows applications to run in an isolated environment. The specifics of what the API looks like and the extent of the isolation are implementation details and do not conflict with the fundamental concept. On another level, Wine can also be considered a simulator, but instead of simulating hardware like a CPU, it simulates the behavior of Windows.
Part 2: Introduction to Wine's Principles
This section is relatively basic and singular, and it is best to have a certain understanding of operating systems when reading. If you are only interested in compiling and running Wine and are not interested in the principles, you can skip this part without affecting your understanding of the subsequent content.
The purpose of Wine is to run executable programs on Windows (PE, portable executable). We know that the essence of an executable program is machine code arranged according to certain rules, and machine code is related to the instruction set. Thanks to the fact that most PCs are x86/x64, Windows applications can theoretically run directly on x86/x64 Linux machines from the perspective of the instruction set, without the need for hardware-level simulation.
However, to directly load and run PE files, certain ABI compatibility is required. For example, Windows PE programs assume that they are loaded at address 0x400000, so when Wine implements its own loader, it needs to ensure that the PE image is loaded to the same location. For statically linked programs, there may not be much to do, but for dynamically linked programs, Wine needs to mimic the behavior of the Windows loader, loading dependent libraries and performing the necessary relocation work.
To minimize dependence on the binary level, Wine decided to implement at least the GDI32, KERNEL32, and USER32 dynamic libraries, as other libraries are built on the foundation of these three. In theory, other dynamic libraries could directly use existing libraries from Windows, but for various reasons, Wine tends to implement as many APIs as possible. We refer to the API libraries implemented by Wine itself as "builtin" and those from Windows as "native." When Wine loads builtin dynamic libraries, it also establishes a PE header in memory to mimic the memory layout on Windows. A more detailed implementation could be the subject of a future article on Wine's loader, explaining how Wine itself, PE programs, and dynamic libraries are loaded.
In addition to the loader's functionality, Wine also needs to address inter-process communication (IPC) issues. Wine's approach is to implement all cross-process objects and mechanisms, such as GDI objects and semaphores, within the Wine server. Wine also allows the system to run multiple instances of the Wine server. Objects within the same Wine server can naturally communicate with each other as if they were in the same space, while objects under different Wine servers are isolated from each other. This architecture ensures that programs in different containers do not affect each other. The specific implementation of the Wine server is through Unix sockets, which provide an IPC mechanism for interaction with the API layer.
With these foundations in place, Wine can systematically implement various features. It simply involves understanding the behavior and meaning of APIs under Windows and then re-implementing them. Although it sounds simple, the actual difficulty is not small, especially for some undocumented behaviors, which require a considerable understanding of the overall system before they can be addressed. Even some differences, such as UI-related content, require selective implementation due to the different design philosophies between the Windows window system and X. Currently, Wine supports not only Linux but also BSD, Mac OS X, and Android.
Part 3 Environment
The following development environment is described using deepin as an example.
First, obtain the code. The official Wine code repository address is:
If you want to conveniently package it for others to use and don't want to deal with the details of packaging, you can use the Wine maintained by each distribution. For example, the Debian-maintained Wine repository address is:
Here, we will use the official Wine as an example:
Next, install the dependencies required for development. For simplicity, we will only compile 32-bit Wine, as 64-bit Wine only supports 64-bit PE programs, and there are still many programs on Windows that are only available in 32-bit versions.
Next, run the script:
Depending on the version of Wine, you may see different feature support messages at this point. You can adjust the dependencies and parameters based on your needs, and for more details, you can check the contents of
configure.ac
.The Wine source code is quite large, and compilation can be time-consuming. You can increase the parallelism parameter based on your CPU's capabilities, for example, using
make -j8
for compilation.After compiling, run:
to check the version number. If you want to install it to the system, you can run:
However, note that installing it may change the default file associations.
Part 4 Usage
Run the following command:
This will allow you to configure the default container. The default container is located in the
.wine
directory under your HOME directory. TheWINEPREFIX
environment variable is used to modify the current container path. For example, if you have an executable file calleddemo.exe
and you want to test whether it can run normally, you can run:The
demo_exe
directory under your HOME directory will be used as its container directory.Part 5 Development
After compiling, the directory structure of the Wine source code is as follows:
dlls
directory contains the implementations of all APIs, organized by module.loader
directory includes code related to the startup and loading of Wine.programs
directory stores the code for external programs, such as the registry management toolregedit
.server
directory, as the name suggests, is the implementation of the Wine server.From here, the process is similar to regular development. For example, if we find a font-related bug in a certain application, we can first use our experience to determine how the program is implemented on Windows, and then check the corresponding implementation. For instance, the GDI-related font implementation is located in
dlls/gdi32/font.c
anddlls/gdi32/freetype.c
. After modifying the code, you can quickly verify it by runningmake
in the module's directory, such asdlls/gdi32
in the example above.For complex issues that are not easily located, you can use logging for debugging. The
WINEDEBUG
environment variable specifies the logs that need to be output.Sometimes, we may need to simplify complex situations, which often involves writing small demo programs to reproduce the problem. If you don't want to compile on Windows, you can use mingw to directly compile exe files on deepin. The process is straightforward: first, install mingw:
Then, implement the program using the Windows API as usual, and finally use the mingw toolchain to generate the file. Here's an example Makefile:
In the example above,
UNICODE
is defined, so the program uses the UNICODE version of the API with the entry functionwmain
. The-lgdi32
flag indicates that the gdi32 library needs to be linked. The resultinghello.exe
can run on both Windows and deepin.Part 6 Other Considerations
This article only covers the basics of Wine development. There is much more to explore in Wine itself. For example, how does Wine use a driver mechanism to separate interfaces from implementations? Or how does Wine implement the COM mechanism using pure C? Although Wine has been around for some time, its development is still very active. Interested students can join in and contribute to the Linux ecosystem, allowing everyone to access more high-quality applications. This can be considered a form of indirect support for the community.
Part 7 Updates
7.1 New WOW64
In the previous compilation example, we only compiled 32-bit Wine and omitted the details of compiling 64-bit Wine. Starting from Wine 8, Wine began a development process called PE Conversion, which re-implemented the WOW64 mechanism. In this mode, you only need to compile one version of Wine, which can run both 32-bit and 64-bit programs. It also no longer relies on 32-bit runtime libraries. Although this mode is still considered experimental, it has been the default method since deepin-wine8.
To compile Wine with the new WOW64 mechanism, follow these steps:
build-wine
at the same level as the Wine source code directory, and navigate into this directory.../wine/configure --prefix=/opt/wine-newwow64 --enable-archs=i386,x86_64
. If there are any prompts, such as missing compilation dependencies, you can run the command again after installing the necessary packages.make -j8
.sudo make install
. Wine will be installed in the location specified by the prefix in step 4, i.e.,/opt/wine-newwow64
. Of course, you can also choose not to install and run it directly from the compilation directory.7.2 Other Architectures
As mentioned in the section on principles, Linux systems on x86/x64 machines can run x86/x64 PE programs through Wine. In fact, with the advancement of DBT (dynamic binary translation) technology, there are now solutions for running Wine on ARM and other architectures. Interested readers can check out the Box64 project.
In November, WeChat released a native Linux version on the deepin store, with functionalities that are almost identical to those on Windows and macOS. The Wine version of WeChat can finally "retire," and we look forward to more software releasing native versions in the future, allowing Wine to complete its "historical mission" sooner.
Regarding the link to the Box64 project, I encountered some issues while trying to parse it. This could be due to the link itself or network-related issues. I recommend checking the validity of the link and trying again. If you have any other questions or need assistance with something else, feel free to ask!
Related Reading:
(1)Click to support the deepin Community
(2)Collection of deepin Technical Sharing