Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

M1 & M2 Mac 本地构建纯arm64架构RealESRGAN GUI.app的方法(内附方法) #18

Closed
ghost opened this issue Feb 10, 2023 · 30 comments

Comments

@ghost
Copy link

ghost commented Feb 10, 2023

https://github.com/blacklein/RealESRGAN-GUI-macOS-arm64
fork后改的仓库,专门用于M1 M2 芯片的Mac本地构建纯arm64的macOS app,效率提升相比intel app和universal app要明显,这在其他开源项目作者issue里也得到证实了,即为吊轨的是,虽然苹果官方宣称universal(即显示简介里说的“通用”)应用兼容x64和arm64,在苹果芯片电脑上优先使用arm64,理论上会跟纯arm64应用的效率一样,但实际测下里,universal应用并没有最大优化苹果芯片的效率,其他作者也证实了这点Anjok07/ultimatevocalremovergui#364 (comment)

改过的仓库里已经提供了纯arm64的tkinterdnd2、realesrgan-ncnn-vulkan,以及超分models,运行pyinstaller可以直接打包成完整的app,希望对用苹果芯片Mac的同学有帮助。

最后再次感谢T大的优秀开源项目!!!

PS:T大,我改过的realesrgan-gui-for-macOS-arm64.spec应该对intel macOS app打包应该也是有一样作用的,这样workflow应该可以大幅度简化,只是Github runner好像打包不出arm64 app,希望对你有帮助,谢谢!

@TransparentLC TransparentLC pinned this issue Feb 10, 2023
@TransparentLC
Copy link
Owner

好耶!这个 Issue 我就置顶啦!

GitHub Actions 规划在今年第三季度开始提供使用 M1 运行的 macOS 镜像( actions/runner-images#2187 ),到那个时候就可以在分支里把自动打包加上了。

@ghost
Copy link
Author

ghost commented Feb 10, 2023

深色模式界面
使用 darkdetect 实现。
在启动时根据系统设定选择使用浅色或深色模式界面,支持在修改系统设定时自动切换。
在 macOS 上不适用(?)

关于深色模式,打包时这个darkdetect包是warning的,有个_mac_detect 无法导入,实测确实不支持深色模式

@TransparentLC
Copy link
Owner

那个 warning 可能指的是 darkdetect 的这一行:https://github.com/albertosottile/darkdetect/blob/3347df3e95e8a96118b3ae7229a8fe699701159c/darkdetect/_mac_detect.py#L25

try:
    # macOS Big Sur+ use "a built-in dynamic linker cache of all system-provided libraries"
    appkit = ctypes.cdll.LoadLibrary('AppKit.framework/AppKit') # <-- 这一行
    objc = ctypes.cdll.LoadLibrary('libobjc.dylib')
except OSError:
    # revert to full path for older OS versions and hardened programs
    appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('AppKit'))
    objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))

不过我也没办法确定是 darkdetect 不应该这么导入还是 pyinstaller 的问题,翻了两遍的 issue 都没有结果……

@ghost
Copy link
Author

ghost commented Mar 14, 2023

请问release里面新的模型怎么用?

@TransparentLC
Copy link
Owner

还在写 README,稍后补充

@ghost
Copy link
Author

ghost commented Mar 15, 2023

pip install tkinterdnd2-osxarm64
上传了一个支持linux64 windows64 osx64 和osx arm64的tkinterdnd2,不知道能不能用来替代requirements

@TransparentLC
Copy link
Owner

TransparentLC commented Mar 15, 2023

https://github.com/blacklein/tkinterdnd2/blob/4d83a3e10c65b97d1c20e8b0622304998a478165/tkinterdnd2/TkinterDnD.py#L42

    try:
        import os.path
        import platform

        if platform.system()=="Darwin": # <-- This line
        if platform.system()=="Darwin" and platform.machine()=="arm64":
            tkdnd_platform_rep = "osx64arm"
        elif platform.system()=="Darwin" and platform.machine()!="arm64":
            tkdnd_platform_rep = "osx64"

这样写确定不会有 IndentationError 吗……

@ghost
Copy link
Author

ghost commented Mar 15, 2023

我也不知道,晚上我回去测试下

@ghost
Copy link
Author

ghost commented Mar 15, 2023

这里是要删掉的,忘记删了

@ghost
Copy link
Author

ghost commented Mar 16, 2023

@TransparentLC 删掉了if platform.system()=="Darwin": ,请T大再给看看是否可以用,谢谢!

@ghost
Copy link
Author

ghost commented Mar 17, 2023

这个是windows x64 linux x64 macos arm64
pip install tkinterdnd2-osxarm64

这个是windows x64 linux x64 macos x64 macos arm64
这个使用lipo -create命令把x86_64和arm64的dylib合并成一个fat binary
这个用mac亲测可以用,兼容intel和arm64的mac
效率上和纯arm64那个package似乎没有太大区别,肉眼看不出来,我自己是用纯arm64的,universal给有需要的同学们
pip install tkinterdnd2-universal

windows和linux试图编译tkdnd,但失败了,不知道怎么解决,就还是用原来的tkdnd2.9.2了

@ghost
Copy link
Author

ghost commented Mar 18, 2023

更新下,pip install tkinterdnd2-universal==1.1.0 这个全平台libtkdnd更新到官方仓库最新版的2.9.3,其中macos兼容x64和arm64,经测试可用,为了摸索windows和linux编译环境真是老费功夫了,linux arm64也编译了,但.so文件好像不能合并成一个,要另外写个条件判断,我想应该也没人用arm版的linux吧,就不放进去了?试错花了大把时间,最后解决办法异常简单,也是没说的了

@ghost
Copy link
Author

ghost commented Mar 19, 2023

请教下,我把tkdnd除arm windows以外的平台都编译到2.9.3了,然后tkinterdnd2文件目录如下:

.
├── TkinterDnD.py
├── __init__.py
└── tkdnd
    ├── linux-arm64
    │   ├── libtkdnd2.9.3.so
    │   ├── pkgIndex.tcl
    │   ├── tkdnd.tcl
    │   ├── tkdnd_compat.tcl
    │   ├── tkdnd_generic.tcl
    │   ├── tkdnd_macosx.tcl
    │   ├── tkdnd_unix.tcl
    │   ├── tkdnd_utils.tcl
    │   └── tkdnd_windows.tcl
    ├── linux-x64
    │   ├── libtkdnd2.9.3.so
    │   ├── pkgIndex.tcl
    │   ├── tkdnd.tcl
    │   ├── tkdnd_compat.tcl
    │   ├── tkdnd_generic.tcl
    │   ├── tkdnd_macosx.tcl
    │   ├── tkdnd_unix.tcl
    │   ├── tkdnd_utils.tcl
    │   └── tkdnd_windows.tcl
    ├── osx-arm64
    │   ├── libtkdnd2.9.3.dylib
    │   ├── pkgIndex.tcl
    │   ├── tkdnd.tcl
    │   ├── tkdnd_compat.tcl
    │   ├── tkdnd_generic.tcl
    │   ├── tkdnd_macosx.tcl
    │   ├── tkdnd_unix.tcl
    │   ├── tkdnd_utils.tcl
    │   └── tkdnd_windows.tcl
    ├── osx-x64
    │   ├── libtkdnd2.9.3.dylib
    │   ├── pkgIndex.tcl
    │   ├── tkdnd.tcl
    │   ├── tkdnd_compat.tcl
    │   ├── tkdnd_generic.tcl
    │   ├── tkdnd_macosx.tcl
    │   ├── tkdnd_unix.tcl
    │   ├── tkdnd_utils.tcl
    │   └── tkdnd_windows.tcl
    └── win-x64
        ├── libtkdnd2.9.3.dll
        ├── pkgIndex.tcl
        ├── tkdnd.tcl
        ├── tkdnd2.9.3.lib
        ├── tkdnd_compat.tcl
        ├── tkdnd_generic.tcl
        ├── tkdnd_macosx.tcl
        ├── tkdnd_unix.tcl
        ├── tkdnd_utils.tcl
        └── tkdnd_windows.tcl

7 directories, 48 files

然后TkinterDnD.py修改为:

        if platform.system()=="Darwin" and platform.machine()=="arm64":
            tkdnd_platform_rep = "osx-arm64"
        elif platform.system()=="Darwin" and platform.machine()=="x86_64":
            tkdnd_platform_rep = "osx-x64"
        elif platform.system()=="Linux" and platform.machine()=="arm64":
            tkdnd_platform_rep = "linux-arm64"
        elif platform.system()=="Linux" and platform.machine()=="x86_64":
            tkdnd_platform_rep = "linux-x64"
        elif platform.system()=="Windows":
            tkdnd_platform_rep = "win-x64"
        else:
            raise RuntimeError('Plaform not supported.')

然后这个项目仓库的hook-tkinterdnd2.py修改如下:

s = platform.system()
p = {
    'Windows': ({'win-x64'}, {'tkdnd_unix.tcl', 'tkdnd_macosx.tcl'}),
    'Linux': ({'linux-x64', 'linux-arm64'}, {'tkdnd_windows.tcl', 'tkdnd_macosx.tcl'}),
    'Darwin': ({'osx-x64', 'osx-arm64'}, {'tkdnd_windows.tcl', 'tkdnd_unix.tcl'}),

实际测试会把osx-x64osx-arm64都hook进去,构建完成后可以正常拖放运行,我想问题应该是hook这边应该要加个Platform.machine()
但我不会写,希望作者能教一下,谢谢!@TransparentLC


更新下
琢磨了下把hook内容改成下面这样,测试可以hook正确了,希望作者再帮忙把把关这样写是否有其他隐患,谢谢啊~

s = platform.system() and platform.machine()
p = {
    'Windows' and 'x86_64': ({'win-x64'}, {'tkdnd_unix.tcl', 'tkdnd_macosx.tcl'}),
    'Linux' and 'x86_64': ({'linux-x64'}, {'tkdnd_windows.tcl', 'tkdnd_macosx.tcl'}),
    'Linux' and 'arm64': ({'linux-arm64'}, {'tkdnd_windows.tcl', 'tkdnd_macosx.tcl'}),
    'Darwin' and 'x86_64': ({'osx-x64'}, {'tkdnd_windows.tcl', 'tkdnd_unix.tcl'}),
    'Darwin' and 'arm64': ({'osx-arm64'}, {'tkdnd_windows.tcl', 'tkdnd_unix.tcl'}),
}

@TransparentLC
Copy link
Owner

platform.machine() 对应的是 Unix/Linux 的 uname -m,在 Windows 下没有 uname 所以实现是读取环境变量 PROCESSOR_ARCHITECTURE,可能的值不是 x86_64 而是 AMD64

https://github.com/python/cpython/blob/3.10/Lib/platform.py#L716
https://superuser.com/questions/305901/possible-values-of-processor-architecture#answer-1441469

这个匹配的写法是有问题的,按照短路求值的话 a and b and c and d 这种表达式在全是 truthy 值的情况下的值是 d,所以最后会变成 s = platform.machine()p = {'x86_64': ..., 'arm64': ...},在你的 macOS arm64 下运行倒是不会缺文件(因为 arm64 那一项最后还是 'Darwin' and 'arm64': ...),但是换到别的系统上嘛……

这种时候可以用 tuple 作为 dict 的 key,也可以换成用 match 表达式来匹配:

# value的两个set,第一个是打包时需要带上的目录名称,第二个是那个目录里需要排除的文件
p = {
    ('Windows', 'AMD64'): ({'win-x64'}, {'tkdnd_unix.tcl', 'tkdnd_macosx.tcl'}),
    ...
}
s = (platform.system(), platform.machine())
...

@ghost
Copy link
Author

ghost commented Mar 20, 2023

p = {
    ('Windows', 'amd64'): ({'win-x64'}, {'tkdnd_unix.tcl', 'tkdnd_macosx.tcl'}),
    ('Linux', 'x86_64'): ({'linux-x64'}, {'tkdnd_windows.tcl', 'tkdnd_macosx.tcl'}),
    ('Linux', 'aarch64'): ({'linux-arm64'}, {'tkdnd_windows.tcl', 'tkdnd_macosx.tcl'}),
    ('Darwin', 'x86_64'): ({'osx-x64'}, {'tkdnd_windows.tcl', 'tkdnd_unix.tcl'}),
    ('Darwin', 'arm64'): ({'osx-arm64'}, {'tkdnd_windows.tcl', 'tkdnd_unix.tcl'}),
}
s = (platform.system(), platform.machine())

改成这样对吗,linux x64要改成amd64吗?

@TransparentLC
Copy link
Owner

只有 Windows 下才可能出现 AMD64,其他的不用改

@ghost
Copy link
Author

ghost commented Mar 20, 2023

pip install tkinterdnd2-universal==1.7.0
tkdnd for windows on arm也编译成功了,为了编译装了10GB VS2022和编译器,最后只是为了100多kb的成品
1.7.0包含windows x64和arm64,Linux x64和arm64,macOS x64和arm64的tkdnd runtime,全都是单独的runtime,没有做合并,全都升级到官方仓库最新的2.9.3(原作者一直没有放出2.9.3的release不知道为什么),hook文件也都改过了,请帮忙看下是否能用?能用的话我提交PR更新下requirements和hook,谢谢!

@TransparentLC
Copy link
Owner

Windows 的 AMD64ARM64 等等都是大写的。

@ghost
Copy link
Author

ghost commented Mar 21, 2023

好的,谢谢帮助!已修改windows的大写,linux和macos仍然小写(这个我用uname查出来是小写的,不确定是否也要大写),已重新上传,pip install tkinterdnd2-universal==1.7.2

@TransparentLC
Copy link
Owner

看样子没什么问题了,这样 requirements.txt 就可以改成:

- tkinterdnd2 == 0.3.*; sys_platform != 'darwin' or platform_machine != 'arm64'
- tkinterdnd2-osxarm64 == 0.3.*; sys_platform == 'darwin' and platform_machine == 'arm64'
- # https://github.com/TransparentLC/realesrgan-gui/issues/18#issuecomment-1469605298
+ # https://github.com/TransparentLC/realesrgan-gui/issues/18#issuecomment-1477203041
+ tkinterdnd2-universal >= 1.7.3, < 2.0.0

参见 https://en.wikipedia.org/wiki/Uname ,Unix/Linux 那边的 uname -m 绝大多数都是小写的。

@Bavoch
Copy link

Bavoch commented May 30, 2023

Mac M1 按照作者大大提供的打包方法未能成功,提示:
99 INFO: PyInstaller: 5.10.1
99 INFO: Python: 3.10.6
105 INFO: Platform: macOS-13.3.1-arm64-arm-64bit
107 INFO: UPX is not available.
112 INFO: Extending PYTHONPATH with paths
['/Users/Bavoch/realesrgan-gui']
190 INFO: Appending 'binaries' from .spec
Unable to find "/Users/Bavoch/realesrgan-gui/models" when adding binary and data files.
Bavoch@Mac-Studio realesrgan-gui %

@TransparentLC
Copy link
Owner

你看看倒数第二行 ( ゚∀。)

正常执行 Build-macOS-arm64.sh 的话是会下载 Real-ESRGAN 然后解压出模型的文件夹的。

@Bavoch
Copy link

Bavoch commented May 31, 2023

谢谢回复,它提示我少了个model文件,但我不知道咋处理😅

@TransparentLC
Copy link
Owner

https://github.com/xinntao/Real-ESRGAN/releases 下载 realesrgan-ncnn-vulkan-*-macos.zip 的压缩包,解压之后里面会有模型文件夹 models 和 Real-ESRGAN 的主程序(按照 realesrgan-gui-macOS-arm64.spec 写的文件名是 realesrgan-ncnn-vulkan,不是的话改一下就可以了),把这两个放到你 git clone 之后这个 repo 所在的目录下。

@Bavoch
Copy link

Bavoch commented May 31, 2023

万分感谢大佬🧎,晚上回家试一下哈哈

@Bavoch
Copy link

Bavoch commented May 31, 2023

现在模型有了,又提示这个:
ValueError: Unknown Mach-O header: 0x37373637 in <_io.BufferedReader name='/Users/Bavoch/realesrgan-gui/models/realesr-animevideov3-x3.param'>

@TransparentLC
Copy link
Owner

似乎是 realesrgan-gui-macOS-arm64.spec 写错了?打包的时候模型不应该放到 binaries 这里的。

试一下这么修改可不可以:

  a = Analysis(
      ['main.py'],
-     binaries=[
-         ('realesrgan-ncnn-vulkan', '.'),
-         ('models', 'models'),
-     ],
      datas=[
+         ('realesrgan-ncnn-vulkan', '.'),
+         ('models', 'models'),
          ('theme', 'theme'),
          ('i18n.ini', '.'),
          ('icon.icns', '.'),
          ('icon-128px.png', '.'),
          # macOS下通过app实现通知,打包时需要附带
          *(collect_data_files('notifypy') if sys.platform == 'darwin' else []),
      ],

不过我没有 macOS 的设备所以没办法测试,如果还是不行的话大概就需要自己摸索了……

@Bavoch
Copy link

Bavoch commented May 31, 2023

谢谢大佬,可还是不行😅

@hyrulelinks
Copy link
Contributor

似乎是 realesrgan-gui-macOS-arm64.spec 写错了?打包的时候模型不应该放到 binaries 这里的。

试一下这么修改可不可以:

  a = Analysis(
      ['main.py'],
-     binaries=[
-         ('realesrgan-ncnn-vulkan', '.'),
-         ('models', 'models'),
-     ],
      datas=[
+         ('realesrgan-ncnn-vulkan', '.'),
+         ('models', 'models'),
          ('theme', 'theme'),
          ('i18n.ini', '.'),
          ('icon.icns', '.'),
          ('icon-128px.png', '.'),
          # macOS下通过app实现通知,打包时需要附带
          *(collect_data_files('notifypy') if sys.platform == 'darwin' else []),
      ],

不过我没有 macOS 的设备所以没办法测试,如果还是不行的话大概就需要自己摸索了……

这个修改有效的,改过后就能打包成功,但打出来的应用双击闪退,无法正常启动

@hyrulelinks
Copy link
Contributor

#39
问题已解决@Bavoch
作者可以close这个issue了@TransparentLC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants