- Build Windows .exe from macOS system
- Create portable Windows executable for AMD64 architecture
- PyInstaller created ARM64 Mach-O executable (macOS format)
- File named as .exe but actually macOS binary
- Cross-compilation from macOS to Windows failed
PyInstaller builds executables for the HOST platform, not TARGET platform
Technical Details:
- Host Platform: macOS ARM64 (where build runs)
- Target Platform: Windows AMD64 (what we wanted)
- PyInstaller Behavior: Always creates host platform binaries
- Result: ARM64 Mach-O instead of Windows PE32+
Original build_windows.py configuration:
'--onefile', # Single executable
'--windowed', # No console (caused .app creation on macOS)
'--console', # Changed to console (but still creates macOS binary)The --windowed flag:
- On macOS: Creates .app bundle (even for "Windows" build)
- On Windows: Creates GUI executable without console
- Not a cross-platform target specifier
- Bootloader: Platform-specific (compiled C code)
- Python Runtime: Platform-specific libraries
- Dependencies: Platform-specific (.so vs .dll vs .dylib)
- Executable Format: Platform-specific (Mach-O vs PE32+ vs ELF)
macOS ARM64: Mach-O 64-bit executable arm64
Windows AMD64: PE32+ executable (console) x86-64
Linux AMD64: ELF 64-bit LSB executable, x86-64
file dist/windows/FFmpeg_GUI_Windows_AMD64
# Output: Mach-O 64-bit executable arm64Not:
# What we wanted:
# PE32+ executable (console) x86-64, for MS Windows- Files Created:
FFmpeg_GUI_Windows.spec,BUILD_WINDOWS_NATIVE.md - Approach: Build on actual Windows system
- Result: True Windows PE32+ executable
- GitHub Actions:
runs-on: windows-latest - Automated: Build on Windows runners
- Distribution: Artifacts from Windows build
FROM mcr.microsoft.com/windows/servercore:ltsc2022
RUN pip install pyinstaller
COPY . .
RUN pyinstaller FFmpeg_GUI_Windows.spec# Install Windows Python under Wine
wine python.exe -m pip install pyinstaller
wine python.exe -m PyInstaller FFmpeg_GUI_Windows.spec- No cross-compilation support for different architectures
- Host platform determines output format always
- --windowed flag creates .app on macOS regardless of intent
- Executable format cannot be overridden
- Build on target platform or use CI/CD
- Separate build scripts per platform
- Platform-specific configuration files
- Testing on target platform mandatory
- Naming file
.exedoesn't make it Windows executable - File extension != executable format
- Always verify with
filecommand
- macOS ARM64: Native build complete (
FFmpeg_GUI_macOS_ARM64.dmg) - Windows AMD64: Spec files ready for native build
- Documentation: Complete build instructions provided
- Cross-compilation: PyInstaller limitation (not configuration error)
- Wine approach: Complex, unreliable for distribution
- Docker Windows: Resource intensive, complex setup
The issue was not a configuration error but a fundamental PyInstaller limitation. Cross-compilation from macOS to Windows is not supported. The proper solution is native builds on each target platform, which is now implemented with the spec files and documentation created.