marcelotduarte / cx_Freeze

cx_Freeze creates standalone executables from Python scripts, with the same performance, is cross-platform and should work on any platform that Python itself works on.
https://marcelotduarte.github.io/cx_Freeze/
Other
1.35k stars 218 forks source link

Gtk.DrawingArea crashes app packaged by cx_Freeze but it's fine to run the code without cx_Freeze packing #1416

Closed nuixdt closed 1 year ago

nuixdt commented 2 years ago

Prerequisite

Describe the bug The following code works fine if run it in terminal directly on macOS 12.3 with M1 chipset. But, if it was packaged by cx_Freeze, the app created is hanged up and no GUI is presented. The error info is presented below:

/opt/homebrew/lib/python3.9/site-packages/gi/overrides/Gtk.py:1680: Warning: g_boxed_type_register_static: assertion 'g_type_from_name (name) == 0' failed return _Gtk_main(*args, *kwargs) /opt/homebrew/lib/python3.9/site-packages/gi/overrides/Gtk.py:1680: Warning: g_once_init_leave: assertion 'result != 0' failed return _Gtk_main(args, **kwargs)

If we use Gtk.Button instead of Gtk.DrawingArea, there is no problem packaged by cx_Freeze.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import gi
gi.require_version('Gtk', '3.0')
import gi.repository.Gtk  as  Gtk
import gi.repository.Gdk  as  Gdk

def on_draw(da, ctx):
    ctx.set_source_rgb(1.0,0.0,0.0)
    ctx.paint()
    return True
def main():
    window = Gtk.Window()
    window.connect('destroy', lambda w: Gtk.main_quit())

    drawingArea = Gtk.DrawingArea()
    drawingArea.set_size_request(300,200)
    drawingArea.set_events(Gdk.EventMask.ALL_EVENTS_MASK)

    # crash on this line code if packed by cx_Freeze
    drawingArea.connect ('draw', on_draw)

    window.add(drawingArea)
    window.show_all()
    window.set_title("test")
    Gtk.main()
    return
if __name__ == '__main__':
    main()
    sys.exit(1)

Expected behavior

display the created GUI window

Desktop (please complete the following information):

marcelotduarte commented 2 years ago

What is the setup.py and command to build? Are you using bdist_mac or tried it? python setup.py bdist_mac

nuixdt commented 2 years ago

yes, I use bdist_mac to build the app

setup.py applied for building is listed below :

from cx_Freeze import setup, Executable

# Dependencies are automatically detected, but it might need
# fine tuning.
build_options = {'packages': ["gi", "numpy", "PIL"], 'excludes': []}

import sys
base = 'Win32GUI' if sys.platform=='win32' else None

executables = [
    Executable('test.py', base=base)
]

setup(name='test',
      version = '1.0',
      description = 'test',
      options = {'build_exe': build_options},
      executables = executables)
marcelotduarte commented 2 years ago

I can't test it on mac, but I can try on linux (to see if it's any change in packaging and dependencies, which can affect all systems). I see it depends on cairo and something else. Anyway, cx_Freeze already has hooks for gtk._gtk for example. It may be that in this version of gtk you are using something has changed. Try using includes=["gtk._gtk"] or add "gtk" to packages.

nuixdt commented 2 years ago

I tried using includes=["gtk._gtk"] or add "gtk" to packages. App is failed to be packaged and info shows that no modules or packages are installed.

I try to help to fix the problem. Where should I start in cx_Freeze source code?

I have following packages installed (brew) : gtk+3: stable 3.24.33 (bottled) gtk+: stable 2.24.33 (bottled) gtk-mac-integration: stable 3.0.1 (bottled)

python modules installed: $ pip3.9 list Package Version


AppKit 0.2.8 beautifulsoup4 4.10.0 black 22.1.0 click 8.0.4 cx-Freeze 6.10 cycler 0.11.0 Flask 2.0.3 fonttools 4.29.1 importlib-metadata 4.11.2 iterm2 1.31 itsdangerous 2.1.1 Jinja2 3.0.3 kiwisolver 1.3.2 MarkupSafe 2.1.0 matplotlib 3.5.1 mypy-extensions 0.4.3 numpy 1.22.3 packaging 21.3 pathspec 0.9.0 Pillow 9.0.1 pip 22.0.4 platformdirs 2.5.1 protobuf 3.19.4 pyappkit 0.0.3 pycairo 1.21.0 PyGObject 3.42.0 pymongo 4.0.2 pyobjc 8.4 pyobjc-core 8.4 pyobjc-framework-Accessibility 8.4 pyobjc-framework-Accounts 8.4 pyobjc-framework-AddressBook 8.4 pyobjc-framework-AdServices 8.4 pyobjc-framework-AdSupport 8.4 pyobjc-framework-AppleScriptKit 8.4 pyobjc-framework-AppleScriptObjC 8.4 pyobjc-framework-ApplicationServices 8.4 pyobjc-framework-AppTrackingTransparency 8.4 pyobjc-framework-AudioVideoBridging 8.4 pyobjc-framework-AuthenticationServices 8.4 pyobjc-framework-AutomaticAssessmentConfiguration 8.4 pyobjc-framework-Automator 8.4 pyobjc-framework-AVFoundation 8.4 pyobjc-framework-AVKit 8.4 pyobjc-framework-BusinessChat 8.4 pyobjc-framework-CalendarStore 8.4 pyobjc-framework-CallKit 8.4 pyobjc-framework-CFNetwork 8.4 pyobjc-framework-ClassKit 8.4 pyobjc-framework-CloudKit 8.4 pyobjc-framework-Cocoa 8.4 pyobjc-framework-Collaboration 8.4 pyobjc-framework-ColorSync 8.4 pyobjc-framework-Contacts 8.4 pyobjc-framework-ContactsUI 8.4 pyobjc-framework-CoreAudio 8.4 pyobjc-framework-CoreAudioKit 8.4 pyobjc-framework-CoreBluetooth 8.4 pyobjc-framework-CoreData 8.4 pyobjc-framework-CoreHaptics 8.4 pyobjc-framework-CoreLocation 8.4 pyobjc-framework-CoreMedia 8.4 pyobjc-framework-CoreMediaIO 8.4 pyobjc-framework-CoreMIDI 8.4 pyobjc-framework-CoreML 8.4 pyobjc-framework-CoreMotion 8.4 pyobjc-framework-CoreServices 8.4 pyobjc-framework-CoreSpotlight 8.4 pyobjc-framework-CoreText 8.4 pyobjc-framework-CoreWLAN 8.4 pyobjc-framework-CryptoTokenKit 8.4 pyobjc-framework-DataDetection 8.4 pyobjc-framework-DeviceCheck 8.4 pyobjc-framework-DictionaryServices 8.4 pyobjc-framework-DiscRecording 8.4 pyobjc-framework-DiscRecordingUI 8.4 pyobjc-framework-DiskArbitration 8.4 pyobjc-framework-DVDPlayback 8.4 pyobjc-framework-EventKit 8.4 pyobjc-framework-ExceptionHandling 8.4 pyobjc-framework-ExecutionPolicy 8.4 pyobjc-framework-ExternalAccessory 8.4 pyobjc-framework-FileProvider 8.4 pyobjc-framework-FileProviderUI 8.4 pyobjc-framework-FinderSync 8.4 pyobjc-framework-FSEvents 8.4 pyobjc-framework-GameCenter 8.4 pyobjc-framework-GameController 8.4 pyobjc-framework-GameKit 8.4 pyobjc-framework-GameplayKit 8.4 pyobjc-framework-ImageCaptureCore 8.4 pyobjc-framework-IMServicePlugIn 8.4 pyobjc-framework-InputMethodKit 8.4 pyobjc-framework-InstallerPlugins 8.4 pyobjc-framework-InstantMessage 8.4 pyobjc-framework-Intents 8.4 pyobjc-framework-IntentsUI 8.4 pyobjc-framework-IOSurface 8.4 pyobjc-framework-iTunesLibrary 8.4 pyobjc-framework-KernelManagement 8.4 pyobjc-framework-LatentSemanticMapping 8.4 pyobjc-framework-LaunchServices 8.4 pyobjc-framework-libdispatch 8.4 pyobjc-framework-LinkPresentation 8.4 pyobjc-framework-LocalAuthentication 8.4 pyobjc-framework-LocalAuthenticationEmbeddedUI 8.4 pyobjc-framework-MailKit 8.4 pyobjc-framework-MapKit 8.4 pyobjc-framework-MediaAccessibility 8.4 pyobjc-framework-MediaLibrary 8.4 pyobjc-framework-MediaPlayer 8.4 pyobjc-framework-MediaToolbox 8.4 pyobjc-framework-Metal 8.4 pyobjc-framework-MetalKit 8.4 pyobjc-framework-MetalPerformanceShaders 8.4 pyobjc-framework-MetalPerformanceShadersGraph 8.4 pyobjc-framework-MetricKit 8.4 pyobjc-framework-MLCompute 8.4 pyobjc-framework-ModelIO 8.4 pyobjc-framework-MultipeerConnectivity 8.4 pyobjc-framework-NaturalLanguage 8.4 pyobjc-framework-NetFS 8.4 pyobjc-framework-Network 8.4 pyobjc-framework-NetworkExtension 8.4 pyobjc-framework-NotificationCenter 8.4 pyobjc-framework-OpenDirectory 8.4 pyobjc-framework-OSAKit 8.4 pyobjc-framework-OSLog 8.4 pyobjc-framework-PassKit 8.4 pyobjc-framework-PencilKit 8.4 pyobjc-framework-Photos 8.4 pyobjc-framework-PhotosUI 8.4 pyobjc-framework-PreferencePanes 8.4 pyobjc-framework-PushKit 8.4 pyobjc-framework-Quartz 8.4 pyobjc-framework-QuickLookThumbnailing 8.4 pyobjc-framework-ReplayKit 8.4 pyobjc-framework-SafariServices 8.4 pyobjc-framework-SceneKit 8.4 pyobjc-framework-ScreenCaptureKit 8.4 pyobjc-framework-ScreenSaver 8.4 pyobjc-framework-ScreenTime 8.4 pyobjc-framework-ScriptingBridge 8.4 pyobjc-framework-SearchKit 8.4 pyobjc-framework-Security 8.4 pyobjc-framework-SecurityFoundation 8.4 pyobjc-framework-SecurityInterface 8.4 pyobjc-framework-ServiceManagement 8.4 pyobjc-framework-ShazamKit 8.4 pyobjc-framework-Social 8.4 pyobjc-framework-SoundAnalysis 8.4 pyobjc-framework-Speech 8.4 pyobjc-framework-SpriteKit 8.4 pyobjc-framework-StoreKit 8.4 pyobjc-framework-SyncServices 8.4 pyobjc-framework-SystemConfiguration 8.4 pyobjc-framework-SystemExtensions 8.4 pyobjc-framework-UniformTypeIdentifiers 8.4 pyobjc-framework-UserNotifications 8.4 pyobjc-framework-UserNotificationsUI 8.4 pyobjc-framework-VideoSubscriberAccount 8.4 pyobjc-framework-VideoToolbox 8.4 pyobjc-framework-Virtualization 8.4 pyobjc-framework-Vision 8.4 pyobjc-framework-WebKit 8.4 pyparsing 3.0.7 pypi 2.1 python-dateutil 2.8.2 pyupgrade 2.31.0 setuptools 60.5.0 six 1.16.0 soupsieve 2.3.1 tokenize-rt 4.2.1 tomli 2.0.1 typing_extensions 4.1.1 websockets 10.2 Werkzeug 2.0.3 wheel 0.37.1 wxPython 4.1.1 zipp 3.7.0

nuixdt commented 2 years ago

There is a warning shown when I use python3.9 -m pip install to install modules. I don't know whether it effects cx_Freeze.

DEPRECATION: Configuring installation scheme with distutils config files is deprecated and will no longer work in the near future. If you are using a Homebrew or Linuxbrew Python, please see discussion at https://github.com/Homebrew/homebrew-core/issues/76621

marcelotduarte commented 2 years ago

I recommend to you test in a virtual environment with minimal packages installed. cx_Freeze depends on setuptools instead of distutils. To ensure better results, upgrade setuptools to the latest version.

nuixdt commented 2 years ago

The code works if built by python3.9 cx_Freeze_setup.py build instead of python3.9 cx_Freeze_setup.py bdist_mac. I run command build/exe.macosx-12-arm64-3.9/test directly. The GUI shows up, but failed to find cairo.Context:

TypeError: Couldn't find foreign struct converter for 'cairo.Context'

Cairo Integration of pygobject shows that the PyGObject cairo support in a separate package. If your application requires the cairo integration you can use gi.require_foreign():

try:
    gi.require_foreign("cairo")
except ImportError:
    print("No pycairo integration :(")

python3.9 test.py works fine. I have no idea why it failed after packed.

marcelotduarte commented 2 years ago

put cairo in the packages list

nuixdt commented 2 years ago

It works if put cairo in the packages list. but why built by bdist_mac failed ?

nuixdt commented 2 years ago

The latest setuptools (version 61.1.0) failed to pack App if there are more than 1 python file or directory. version 60.5.0 works fine.

The error messages are as follows:

error: Multiple top-level packages discovered in a flat-layout: ['Image', 'Resoure'].

To avoid accidental inclusion of unwanted files or directories, setuptools will not proceed with this build.

If you are trying to create a single distribution with multiple packages on purpose, you should not rely on automatic discovery. Instead, consider the following options:

  1. set up custom discovery (find directive with include or exclude)
  2. use a src-layout
  3. explicitly set py_modules or packages with a list of names

To find more information, look for "package discovery" on setuptools docs.

nuixdt commented 2 years ago

bdist_mac was ended by prepare_qt_app(). But, I use gtk library instead of qt. cx-Freeze seems optimized for qt.

marcelotduarte commented 2 years ago

It works if put cairo in the packages list.

Good.

but why built by bdist_mac failed ? bdist_mac was ended by prepare_qt_app(). But, I use gtk library instead of qt. cx-Freeze seems optimized for qt.

cx_Freeze has some optimizations for PyQt and PySide. What is the error?

The latest setuptools (version 61.1.0) failed to pack App if there are more than 1 python file or directory.

I see this error. It is working until 60.10.0

nuixdt commented 2 years ago

cx_Freeze has some optimizations for PyQt and PySide. What is the error?

There is no error

marcelotduarte commented 2 years ago

Can I close this issue?

nuixdt commented 2 years ago

The setup.py works fine by python3 setup.py build, which packed gi, cairo correctly.

But, python3 setup.py bdist_mac seems missing some files when packing gi, cairo, resulted in app crash. If the commented code is uncommented, python3 setup.py bdist_mac says: error: error in setup script: command 'bdist_mac' has no such option 'packages'

Is there another way to let bdist_mac pack gi, cairo correctly? Thanks!

from cx_Freeze import setup, Executable

build_options = {'packages': ["gi", "cairo", "PIL", "numpy"], 'excludes': []}

import sys
base = 'Win32GUI' if sys.platform=='win32' else None

executables = [
    Executable('test.py', base=base)
]

setup(name='test',
      version = '1.0',
      description = 'test App',
      options = {
          'build_exe': build_options,
#          'bdist_mac': build_options,
          },
      executables = executables)
nuixdt commented 2 years ago

Can I close this issue?

There is still a problem: bdist_mac doesn't support packages build option resulted in missing files

marcelotduarte commented 2 years ago

See #1033 regarding bdist_mac differences.

marcelotduarte commented 2 years ago

Can you test with v 6.11 and/or the latest development version? For binary wheels? pip install --pre --extra-index-url https://marcelotduarte.github.io/packages/ cx_Freeze or compiling from sources: pip install -U git+https://github.com/marcelotduarte/cx_Freeze.git@develop

marcelotduarte commented 2 years ago

But, python3 setup.py bdist_mac seems missing some files when packing gi, cairo, resulted in app crash. If the commented code is uncommented, python3 setup.py bdist_mac says: error: error in setup script: command 'bdist_mac' has no such option 'packages'

I'm re-reading the comments, and noted this. bdist_mac is a layer above build_exe, so when you run bdist_mac, build_exe run, then bdist_mac run. The packages options for build_exe take effect then. build_exe bdist_mac

marcelotduarte commented 1 year ago

Release 6.15.3 is out!