Well, let me just copy and paste what wikipedia says:
Binary compatible operating systems are OSes that aim to implement binary compatibility with another OS, or another variant of the same brand. This means that they are ABI-compatible (for application binary interface). As the job of an OS is to run programs, the instruction set architectures running the OSes have to be the same or compatible. Otherwise, programs can be employed within a CPU emulator or a faster dynamic translation mechanism to make them compatible.
For example, the Linux kernel is not compatible with Windows. This does not mean that Linux can’t be binary compatible with Windows applications. Additional software, Wine, is available that does that to some degree. The ReactOS OS development effort, seeks to create an open source, free software OS that is binary compatible with Microsoft’s Windows NT family of OSes using Wine for application compatibility and reimplementing the Windows kernel for additional compatibility such as for drivers whereas Linux would use Linux drivers not Windows drivers. FreeBSD and other members of the BSD family have binary compatibility with the Linux kernel in usermode by translating Linux system calls into BSD ones. This enables the application and libraries code that run on Linux-based OSes to be run on BSD as well.
Note that a binary compatible OS is different from running an alternative OS through virtualization or emulation, which is done to run software within the alternative OS in the case when the host OS isn’t compatible. Sometimes virtualization is provided with the host OS (or such software can be obtained), which effectively makes the host OS compatible with programs. For example, Windows XP Mode for Windows 7 allows users to run a 64-bit version of Windows 7 and enable old software to still work in a 32-bit virtual machine running Windows XP; VMware Workstation/VMware Fusion, Parallels Workstation, and Windows Virtual PC allow other OSes to be run on Windows, Linux, and OS X.
For another example, Mac OS X on the PowerPC had the ability to run Mac OS 9 and earlier application software through Classic—but this did not make OS X a binary compatible OS with Mac OS 9. Instead, the Classic environment was actually running Mac OS 9.1 in a virtual machine, running as a normal process inside of OS X.[1][2]
Рано или поздно перед Python программистом встает проблема распространения своего ПО на компьютерах без установленного интерпретатора Python. Наиболее рациональным способом при этом кажется упаковка кода в автономный бинарный файл. Для этого существует целый сомн фреймворков.
По прочтении обсуждений в разных местах, пришел к выводу, что PyInstaller лучше всего подходит для данных целей из-за простоты в использовании, своей кросс-платформенности и потому, что собранный им exe-файл легче переносится с одной версии Windows на другую. А так же позволяет без особых танцев собирать бинарники для Windows из-под других операционных систем.
Подготовка
Нам понадобятся:
- Python2 — К сожалению PyInstaller работает только для Python-2.x.x
- Сам Pyinstaller
Pywin32 — дополнения Python для Windows. Опять же последняя стабильная версия (216)
Wine — ну без него тут никуда.
Я тестировал кросс-сборку на Ubuntu 11.04 с Python 2.7.1 и Wine 1.3.20.
Ставим все необходимое:
#Wine
sudo apt-get install wine1.3-dev
#Python
wget http://python.org/ftp/python/2.7.1/python-2.7.1.msi
wine msiexec /i python-2.7.1.msi
#Pyinstaller
wget http://www.pyinstaller.org/static/source/1.5/pyinstaller-1.5.tar.bz2
tar xvf pyinstaller-1.5.tar.bz2
#Pywin32
wget http://downloads.sourceforge.net/project/pywin32/pywin32/Build216/pywin32-216.win32-py2.7.exe?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fpywin32%2Ffiles%2Fpywin32%2FBuild216%2F&ts=1305544745&use_mirror=citylan -o pywin32.exe
wine pywin32.exe
Настройка и запуск
Теперь необходимо настроить Pyinstaller с помощью скрипта Configure.py. Конфигурацию надо производить каждый раз когда меняется конфигурация Python, поэтому имеет смысл держать отдельную версию Pyinstaller для каждой версии Python. Сконфигурируем Pyinstaller под Windows-версию интерпретатора:
cd pyinstaller-1.5
wine ~/.wine/drive_c/Python27.exe Configure.py
Теперь можно собирать exe-файл. Сначала создаем spec-файл, в котором содержаться настройки упаковки проекта. Для наглядности назовем упаковываемый файл test.py (в случае, когда в проекте не один файл, указываем путь к главному).
wine ~/.wine/drive_c/Python27.exe Makespec.py test.py
По умолчанию папка со spec-фалом будет создана в папке Pyinstaller и будет иметь имя упаковываемого файла без расширения (в нашем случае test).
К команде создания spec-файла можно добавить полезные ключи, например:
- —onefile — по умолчанию PyInstaller создает exe-файл и кладет в папку рядом с ним необходимые dll. Этот ключ форсирует упаковку всего в единый бинарник.
- —out=DIR — позволяет задать определенную папку для spec-файла
- —windowed — под Windows отключает консоль приложения
И наконец финальный этап — построение:
wine ~/.wine/drive_c/Python27/python.exe Build.py test/test.spec
Упакованное приложение можно найти в папке dist/ внутри папки со spec-файлом.
За сим все. Тестовая программа заработала под Wine, а затем под Windows XP и Windows 7 без малейших писков.
PyInstaller bundles a Python application and all its dependencies into a single
package. The user can run the packaged app without installing a Python
interpreter or any modules.
- Documentation:
-
https://pyinstaller.org/
- Code:
-
https://github.com/pyinstaller/pyinstaller
PyInstaller reads a Python script written by you. It analyzes your code
to discover every other module and library your script needs in order to
execute. Then it collects copies of all those files – including the active
Python interpreter! – and puts them with your script in a single folder, or
optionally in a single executable file.
PyInstaller is tested against Windows, macOS, and GNU/Linux.
However, it is not a cross-compiler:
to make a Windows app you run PyInstaller in Windows; to make
a GNU/Linux app you run it in GNU/Linux, etc.
PyInstaller has been used successfully
with AIX, Solaris, FreeBSD and OpenBSD,
but is not tested against them as part of the continuous integration tests.
Main Advantages
-
Works out-of-the-box with any Python version 3.7-3.11.
-
Fully multi-platform, and uses the OS support to load the dynamic libraries,
thus ensuring full compatibility. -
Correctly bundles the major Python packages such as numpy, PyQt5,
PySide2, PyQt6, PySide6, wxPython, matplotlib and others out-of-the-box. -
Compatible with many 3rd-party packages out-of-the-box. (All the required
tricks to make external packages work are already integrated.) -
Works with code signing on macOS.
-
Bundles MS Visual C++ DLLs on Windows.
Installation
PyInstaller is available on PyPI. You can install it through pip:
pip install pyinstaller
Requirements and Tested Platforms
-
- Python:
-
-
3.7-3.11. Note that Python 3.10.0 contains a bug making it unsupportable by
PyInstaller. PyInstaller will also not work with beta releases of Python
3.12.
-
-
- Windows (32bit/64bit):
-
-
PyInstaller should work on Windows 7 or newer, but we only officially support Windows 8+.
-
Support for Python installed from the Windows store without using virtual
environments requires PyInstaller 4.4 or later. -
Note that Windows on arm64 is not yet supported. If you have such a
device and want to help us add arm64 support then please let us know on
our issue tracker.
-
-
- Linux:
-
-
GNU libc based distributions on architectures x86_64, aarch64,
i686, ppc64le, s390x. -
musl libc based distributions on architectures x86_64, aarch64.
-
ldd: Console application to print the shared libraries required
by each program or shared library. This typically can be found in
the distribution-package glibc or libc-bin. -
objdump: Console application to display information from
object files. This typically can be found in the
distribution-package binutils. -
objcopy: Console application to copy and translate object files.
This typically can be found in the distribution-package binutils,
too. -
Raspberry Pi users on armv5—armv7 should add piwheels as an extra
index url then pip install pyinstaller
as usual.
-
-
- macOS (x86_64 or arm64):
-
-
macOS 10.15 (Catalina) or newer.
-
Supports building universal2 applications provided that your installation
of Python and all your dependencies are also compiled universal2.
-
Usage
Basic usage is very simple, just run it against your main script:
pyinstaller /path/to/yourscript.py
For more details, see the manual.
Untested Platforms
The following platforms have been contributed and any feedback or
enhancements on these are welcome.
-
- FreeBSD
-
-
ldd
-
-
- Solaris
-
-
ldd
-
objdump
-
-
- AIX
-
-
AIX 6.1 or newer. PyInstaller will not work with statically
linked Python libraries. -
ldd
-
-
Linux on any other libc implementation/architecture combination not listed
above.
Before using any contributed platform, you need to build the PyInstaller
bootloader. This will happen automatically when you pip install pyinstaller provided that you have an appropriate C compiler (typically
either gcc or clang) and zlib’s development headers already installed.
Support
-
Official debugging guide: https://pyinstaller.org/en/v5.7.0/when-things-go-wrong.html
-
Assorted user contributed help topics: https://github.com/pyinstaller/pyinstaller/wiki
-
Web based Q&A forums: https://github.com/pyinstaller/pyinstaller/discussions
-
Email based Q&A forums: https://groups.google.com/g/pyinstaller
Changes in this Release
You can find a detailed list of changes in this release
in the Changelog section of the manual.
Using Wine and Pyinstaller.
Pyinstaller is a program that packages Python programs into stand-alone executables, under the most used OSs (Windows, Linux, Mac OS X, FreeBSD, Solaris and AIX).
Initially Pyinstaller had a beta feature that allows the cross-compilation of a windows executable under Linux.
However, due the instability of the feature, it has been removed since version 1.5.
Fortunately, is still possible to package a Windows executable using PyInstaller under Wine.
1. Install wine and Python
$ sudo apt-get install wine $ wget https://www.python.org/ftp/python/2.7.9/python-2.7.9.amd64.msi $ wine msiexec /i python-2.7.9.amd64.msi /qb
If you need to compile a 32bit executable, you need to install wine32:
sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt-get install wine32
2. Install PyInstaller on wine
$ cd ~/.wine/drive_c/Python27 $ wine python.exe Scripts/pip.exe install pyinstaller
3. Package a python scripts
Package Python scripts (e.g., helloworld.py) with pyinstaller.
$ cat helloworld.py #!/usr/bin/env python print('Hello World!') $ wine ~/.wine/drive_c/Python27/Scripts/pyinstaller.exe --onefile helloworld.py
The Windows executable file is located in dist/
.
$ wine dist/helloworld.exe Hello World!
Finally, transfer the executable on a windows box and test it:
References
- http://www.pyinstaller.org/
- https://www.winehq.org/
I’m trying to generate an executable from Linux for Windows using pyinstaller.
pyinstaller --onefile --windowed montecarlo.py
I run this command and get a single executable that works on Linux just fine, but if I try on Windows, it’s just a simple file. Why?
asked May 17, 2017 at 2:13
2
I was trying to do this same thing today and ran across this answer. It pointed to the FAQ, which says cross-compiling is not supported. It recommends using Wine.
answered Jul 12, 2017 at 18:28
JackJack
2,7212 gold badges23 silver badges32 bronze badges
1
www.makeworld.space
Oct 4th, 2021
by makeworld
Packaging a Python project into a standalone executable is often a struggle. Thankfully we
have tools like PyInstaller to make this easier. Recently
I ran into another struggle of my own, which was that it seemed impossible to “cross-compile”
with PyInstaller. That is to say, run PyInstaller on one OS, and have it generate an executable
for another. It was hinted at that Linux → Windows was possible using Wine, but I couldn’t find any guides on it.
Eventually, I got it working, so here is that guide. Hope this helps! This guide might also work
on macOS, but I have not tested it.
Thanks to Noah Broyles for the script that helped me figure this all out.
First off, I was only able to use Python 3.8. I tried with 3.9, but I was not able to install it
under WINE. If you are able to, feel free to use that, and change references to 38
in this post
to 39
. I was also using PyInstaller 4.5.1, but other versions should work fine.
The first step is to install WINE for your Linux system. WINE is a compatibility layer that allows
the running of Windows software on non-Windows systems. You can install WINE easily enough from
your distro’s package manager. I am using wine-6.16
, but most likely your distro’s version will
work fine.
Next, download the Python 3.8 Windows installer. You can download that directly from the official
Python Software Foundation here. With
it downloaded, you can run wine python-3.8.9.exe
to begin the installation. WINE may prompt you
to install something like .NET or Mono, you should click Yes and let it install.
You should not use the default installation, follow these steps:
- Check “Add Python 3.8 to PATH”
- Click “Customize installation
- Click “Next”
- Click “Install for all users”
- Set the install location as
C:\Python38
- Click “Install”
- Close the window.
Using the C:\Python38
path helps keep things standard for this blog post.
Now Python 3.8 should be successfully installed in WINE. You can check this by running
wine C:/Python38/python.exe --version
, which will run Windows Python through WINE. Amazing!
Next we’ll need to upgrade pip, to make sure things will install fine. Run
wine C:/Python38/python.exe -m pip install --upgrade pip
. WINE might spit out a lot of warnings
about libgnutls
or something or other, but as long as Pip doesn’t report any errors it’s fine.
Now if your project has any dependencies, you should export them into the standard Python
requirements.txt
file. You can then install them into your WINE Python with this command:
wine C:/Python38/python.exe -m pip install -r requirements.txt
If you’re using a superior dependency
manager like Poetry, you should be able to install and use that in WINE,
although I haven’t tested that.
In any case, you’ll need PyInstaller to be installed, so run this command if PyInstaller wasn’t in
requirements.txt
already:
wine C:/Python38/python.exe -m pip install pyinstaller
Now you can run PyInstaller and an EXE will be built! Just run
wine C:/Python38/Scripts/pyinstaller.exe ...
and replace ...
with whatever arguments you used
to build a Linux executable.
Enjoy!
I created a game using pygame, and I wish to export it to a .exe
file. I’ve used pyinstaller for this, as it is available for Ubuntu. When I run the --onefile game
, it works perfectly fine (on my ubuntu computer). However, when I send it to my friend who has windows, it is NOT a Windows executable, but simply a «file» without any extension. He cannot run it. Renaming it Game.exe
has not worked either.
I’m out of ideas… can anyone help?
asked Feb 26, 2016 at 23:24
6
Obviously the binary executable generated by PyInstaller on Linux only runs on Linux and not on other operating systems like Windows. The file name extension is irrelevant here.
According to the PyInstall FAQ you cannot use it to cross-compile for different platforms either, but running PyInstall inside Wine is supposed to achieve what you want:
- Can I use PyInstaller as a cross-compiler?
Can I package Windows binaries while running under Linux?
No, this is not supported. Please use Wine for this, PyInstaller runs fine in Wine. You may also want to have a look at this thread in the mailinglist. In version 1.4 we had build in some support for this, but it showed to work only half. It would require some Windows system on another partition and would only work for pure Python programs. As soon as you want a decent GUI (gtk, qt, wx), you would need to install Windows libraries anyhow. So it’s much easier to just use Wine.
From what I understand, you’ll need to install PyInstall inside a Wine environment like you would in Windows and then use it like you would on a native Windows system.
Please refer to How can I install Windows software or games? for an overview of how to get started with Wine on Ubuntu.
answered Feb 28, 2016 at 9:49
David FoersterDavid Foerster
35.3k54 gold badges90 silver badges143 bronze badges
1
You can try Python Packager
The git homepage gives the instruction (python 2.7):
wget "http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi"
wget "http://nchc.dl.sourceforge.net/project/pywin32/pywin32/Build%20218/pywin32-218.win32-py2.7.exe"
build_environment/create.sh
export WINEPREFIX=/tmp/path-outputted-from-create
wine start python-2.7.3.msi
wine pywin32-218.win32-py2.7.exe
build_environment/freeze.sh
./package sample-application/src/main.py MySampleProgram
This will build a separate wine environment and installs Python 2.7 as mentioned. In case you need another version, got to the python homepage and download your version.
You can also follow this instruction which downloads a wine-clone:
git clone https://github.com/paulfurley/python-windows-packager
./python-windows-packager/package.sh /path/to/myProject
answered Jul 9, 2018 at 13:45
abu_buaabu_bua
10.1k10 gold badges41 silver badges60 bronze badges
1
My main development platform is Ubuntu. The cross-compilation feature is removed from PyInstaller since 1.5
. In this article, I’ll show you how to package a Windows executable from Python scripts using PyInstaller under wine.
Table of Contents
- 1. Build a Windows excutable on Ubuntu
- Step 1: Install wine and Python
- Step 2: Install PyInstaller on wine
- Step 3: Package Python scripts
- 2. Troubleshooting
- 2.1 ImportError: No module named
1. Build a Windows excutable on Ubuntu
Step 1: Install wine and Python
sudo apt-get install wine winetricks
winetricks python
# Python installation directory
$ cd ~/.wine/drive_c/Python26
Note that python26
is installed, not including pip
(is used to install pyinstaller
). Fortunately, newer Python versions already include pip
. Choose the proper version from Download Python (for me, python-2.7.10.msi
) and install it on wine by:
$ wine msiexec /i python-2.7.10.msi /L*v log.txt
Step 2: Install PyInstaller on wine
$ cd ~/.wine/drive_c/Python27
$ wine python.exe Scripts/pip.exe install pyinstaller
Successfully installed pyinstaller-3.1.1 pypiwin32-219
Step 3: Package Python scripts
Package Python scripts (e.g., HelloWorld.py
) with pyinstaller
.
# run `pyinstaller` under the same directory as Python scripts
$ wine ~/.wine/drive_c/Python27/Scripts/pyinstaller.exe --onefile HelloWorld.py
# filename: HelloWorld.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print('Hello World!')
The Windows executable file is located in dist/
.
$ wine dist/HelloWorld.exe
Hello World!
fixme:msvcrt:__clean_type_info_names_internal (0x1e24e5b8) stub
2. Troubleshooting
2.1 ImportError: No module named
I package a Python script imported openpyxl
, but encounter the issue ImportError: No module named openpyxl
while running the Windows exculable.
$ cd ~/.wine/drive_c/Python27/Scripts/dist
$ wine ProcessSpreadsheet.exe
Traceback (most recent call last):
File "<string>", line 4, in <module>
ImportError: No module named openpyxl
ProcessSpreadsheet returned -1
fixme:msvcrt:__clean_type_info_names_internal (0x1e24e5b8) stub
To tackle this issue, append the openpyxl
path (~/.wine/drive_c/Python27/Lib/site-packages
) to pathex
in the Analysis
object in the application spec file (ProcessSpreadsheet.spec
).
# Step 1: install the python module, openpyxl
$ wine python.exe Scripts/pip.exe install openpyxl
# Step 2: add the `openpyxl` path
a = Analysis(['ProcessSpreadsheet.py'],
pathex=['C:\Python27\Scripts', '~/.wine/drive_c/Python27/Lib/site-packages'],
binaries=None,
datas=None,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
# Step 3: rebuild
$ wine pyinstaller.exe ProcessSpreadsheet.spec
References:
[1]AskUbuntu: Install Python in Wine
[2]StackOverflow: pyInstaller: Import Error
[3]StackOverflow: Cross-compiling a Python script on Linux into a Windows executable
赞赏
微信赞赏
支付宝赞赏
Table of contents:
- Install the PyInstaller
- Experiment: creating the installation
- What will PyInstaller do?
- When PyInstaller output is not a single file
- Command line arguments
- Basic switches:
- Output to generate:
Thanks to PyInstaller it is now easy to create the installation for a Python based project you distribute to: Linux, Windows or MacOS. In here I will examine the PyInstaller on Linux.
When on Linux, you cannot create the final executable for Windows or MacOS, that would be the PyInstaller limitation.
This is why for each OS (Operating System) you should build separate distributable executable.
In other words, PyInstaller doesn’t have the platform switch, like Python Kivy or C# Unity tools that are cross platform.
Install the PyInstaller
First step would be to download PyInstaller from PyPi, but it is even easier to install it using pip:
If you are not sure you have the latest PyInstaller version already you can try to install and upgrade:
pip install --upgrade pyinstaller
From now on, you can call pyinstaller
from the command line.
Experiment: creating the installation
Let’s make our fingers dirty with some code. Let’s create a program you can distribute to any Linux platform even if Python is not installed. In other words we will create the Linux standalone executable as the output of this experiment.
First we create a folder called /content to hold our experiment. In there we create a file called getdatetime.py:
# save as getdatetime.py
import datetime
now = datetime.datetime.now()
print ("Current date and time : ")
print (now.strftime("%Y-%m-%d %H:%M:%S"))
Check here how to work with Python date and time in detail.
Assuming we installed the PyInstaller already, we are now ready to create the one-file standalone executable.
pyinstaller --onefile getdatetime.py
If we list the /content folder, we will get the following output. Wow!
If we now execute the file
command to check the file type for the getdatetime:
file /content/dist/getdatetime
We get the output this is ELF Linux executable:
/content/dist/getdatetime: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=294d1f19a085a730da19a6c55788ec08c2187039, stripped
To run the executable we simple type from the command line:
/content/dist/getdatetime
Output:
Date and time is:
2020-02-22 11:35:15
This is how simple it is; to create independent executable you may run on any Linux, with or without Python installed.
What will PyInstaller do?
We had originally just a single detdatetime.py file, and after the PyInstaller command we have several files and folders more:
build/
dist/
getdatetime.py
getdatetime.spec
__pycache__/
build/
folder is where PyInstaller prepares the distribution executable and stores that to dist/
folder. The getdatetime.spec
is a specification file that PyInstaller creates the first time you run it.
You can edit the getdatetime.spec
file and name your output executable other way.
When PyInstaller output is not a single file
There is another way. You can run PyInstaller with this command:
pyinstaller --onedir getdatetime.py
This time we use --onedir
switch. Inside the dist folder we now have different output. Recall that with the --onefile
option we had just a single file output.
There are many
.so
files inside our dist folder. Files with.so
extension are Shared Objects files. In Windows these would be.dll
s. Under Linux you can get some feedback on.so
files usingldd
command.
To run the final executable and to get the output we should call from the command line:
/content/dist/getdatetime/getdatetime
Output:
Date and time is:
2020-02-22 12:02:15
Command line arguments
Basic switches:
-h, –help | show this help message and exit | |
-v, –version | Show program version info and exit. | |
–distpath DIR | Where to put the bundled app (default: ./dist) | |
–workpath WORKPATH | Where to put all the temporary work files, .log, .pyz and etc. (default: ./build) | |
-y, –noconfirm | Replace output directory –upx-dir UPX_DIR | Path to UPX utility (default: search the execution path) |
-a, –ascii | Do not include unicode encoding support (default: included if available) | |
–clean | Clean PyInstaller cache and remove temporary files before building. | |
–log-level LEVEL | Amount of detail in build-time console messages. LEVEL may be one of TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL (default: INFO). |
Output to generate:
-D, –onedir | Create a one-folder bundle containing an executable (default) |
-F, –onefile | Create a one-file bundled executable. |
–specpath DIR | Folder to store the generated spec file (default: current directory) |
-n NAME, –name NAME | Name to assign to the bundled app and spec file (default: first script’s basename) |
…
tags: install — installer — linux
&
category: python