Python 3.x CMake-MacOS-BundleUtilities将Python解释器添加到应用程序中,并且不';我可不喜欢它

Python 3.x CMake-MacOS-BundleUtilities将Python解释器添加到应用程序中,并且不';我可不喜欢它,python-3.x,macos,cmake,bundle,Python 3.x,Macos,Cmake,Bundle,我正在使用cmakeversion3.16.1将Python添加到MacOS 10.15.1终端上的应用程序包中。当我尝试捆绑MacOS应用程序时,BundleUtilities出现了一个cmake错误: 包含在我的cmake生成的myApp.app/release文件夹中的Python解释器正在链接到外部库,也就是说,它没有被捆绑工具修复 如果我遗漏了任何重要信息,请告诉我 注意:这些是一个CMakeLists.txt的摘录,它还为我们的跨平台应用程序构建了几个其他插件。我已经尽力缩小范围

我正在使用
cmakeversion3.16.1
将Python添加到MacOS 10.15.1终端上的应用程序包中。当我尝试捆绑MacOS应用程序时,BundleUtilities出现了一个cmake错误:

  • 包含在我的cmake生成的myApp.app/release文件夹中的Python解释器正在链接到外部库,也就是说,它没有被捆绑工具修复
如果我遗漏了任何重要信息,请告诉我

注意:这些是一个CMakeLists.txt的摘录,它还为我们的跨平台应用程序构建了几个其他插件。我已经尽力缩小范围了

Python是从
/opt/local/Library/Frameworks/Python.framework/Versions/3.6/Python
端口
实用程序安装的,python3.6被设置为默认版本

$python3--version
在我的终端上输出
python3.6.9

我正在尝试使用
CMakeLists.txt
将Python3添加到我的MacOS应用程序包中。我已经将
cmakcache.txt
中的一些变量复制到下面的注释中,以显示cmake找到了它们

cmake_minimum_required(VERSION 3.12)
project(myApp)
#PYTHON_VERSION_NUMBER inherited from Makefile, e.g. "3.6"
#NOTE: Problem happens with and without "Interpreter" being specified
find_package(Python3 EXACT ${PYTHON_VERSION_NUMBER} REQUIRED COMPONENTS Development Interpreter)
#Python3 include directory is '/opt/local/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m'
include_directories(AFTER SYSTEM ${Python3_INCLUDE_DIRS})
#$Python3_LIBRARY_DIRS is /opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib
link_directories(${Python3_LIBRARY_DIRS})
#Python3_LIBRARIES is '/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/libpython3.6m.dylib'
target_link_libraries(myApp ${Python3_LIBRARIES})
此时,我能够构建多个源文件并将其链接到可执行文件中,其中一些文件需要Python,例如带有Python.h和cython编译源文件的C代码。 我可以将它们安装到应用程序中

if(APPLE)
set(APPS "\${CMAKE_INSTALL_PREFIX}/myApp.app")
(……)

在fixup_bundle的cmake输出期间,它复制Python:

-- fixup_bundle: preparing...
-- fixup_bundle: copying...
(...)
-- 2/66: copying '/opt/local/Library/Frameworks/Python.framework/Versions/3.6/Python'
。。。它修复了Python库:

-- 35/66: fixing up '/Users/username/Projects/myApp/build/release/myApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Python'
在cmake的
捆绑功能
验证应用程序
功能期间输出错误。这表明Python解释器没有修复

-- executable file 2: /Users/username/Projects/myApp/build/release/myApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python
-- verified='0'
-- info='external prerequisites found:
f='/Users/username/Projects/myApp/build/release/myApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python'
external_prereqs='/opt/local/Library/Frameworks/Python.framework/Versions/3.6/Python;/opt/local/lib/libiconv.2.dylib;/opt/local/lib/libintl.8.dylib'
-- 
CMake Error at /opt/local/share/cmake-3.16/Modules/BundleUtilities.cmake:1119 (message):
  error: verify_app failed
Call Stack (most recent call first):
  /opt/local/share/cmake-3.16/Modules/BundleUtilities.cmake:986 (verify_app)
  cmake_install.cmake:155 (fixup_bundle)
查看BundleUtilities输出抱怨的特定文件,显示它正在链接到外部资源

% otool -L build/release/myApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python
build/release/myApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python:
  /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1670.10.0)
  /opt/local/Library/Frameworks/Python.framework/Versions/3.6/Python (compatibility version 3.6.0, current version 3.6.0)
  /opt/local/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
fixup_bundle复制了python框架,包括python库和解释器。只有图书馆修好了。然后Bundle实用程序发现解释器正在链接到外部资源,并正确地生成了错误

这引出了我的问题:

  • 为什么捆绑工具不能修复它
  • 我能做些什么来解决这个问题吗
  • 也许我没有正确使用cmake
错误中指定的文件是Python解释器。我不确定是否需要。一些C代码使用Python.h来调用Python解释器(可能是一个子问题——这个Python解释器是必需的吗?)

其中,因为这是一个lib,它捆绑了应用程序部署的复制和修复

$ file /opt/local/Library/Frameworks/Python.framework/Versions/3.6/Python 
/opt/local/Library/Frameworks/Python.framework/Versions/3.6/Python: Mach-O 64-bit dynamically linked shared library x86_64
旁白:我将创建一个小项目,要么复制这个,要么显示我们更大项目中的某些东西正在把事情搞砸。如果它复制了这一点,可能是对如何使用cmake的误解,或者更糟。

这个问题暂时还没有解决

请注意,
Python.app
位于
Resources
下,这有点不寻常。如果我们查看
函数(将\u解析的\u框架\u复制到\u捆绑包中…
,则存在盲目的资源复制:

execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_resources}" "${resolved_embedded_resources}")
这解释了
Python
可执行文件如何到达一个包中,而不是依赖项

然后
函数(验证捆绑包\u先决条件…
调用结果捆绑包上的
验证应用程序
,并在复制后第一次发现
Python.app
,因此取消了补丁

起初,我考虑删除Python可执行文件,这就解决了问题。后来我想,拥有一个捆绑的Python解释器可能没那么糟糕。我们可以通过以下修改进行处理:

--- a/BundleUtilities.cmake 2019-12-28 02:10:43.000000000 +0100
+++ b/BundleUtilities.cmake 2019-12-28 09:39:26.000000000 +0100
@@ -982,6 +984,13 @@
     message(STATUS "fixup_bundle: cleaning up...")
     clear_bundle_keys(keys)

+    # Recursively discover and fix all subsequent executables.
+    get_bundle_all_executables("${bundle}" file_list)
+    list(REMOVE_ITEM file_list "${app}" ${CFG_IGNORE_ITEM})
+    list(LENGTH file_list nexecutables)
+    if (${nexecutables} GREATER 0)
+      list(GET file_list 0 f)
+      message(STATUS "fixup_bundle: fixing newly discovered executable ${f}...")
+      fixup_bundle("${f}" "" "${dirs}" IGNORE_ITEM ${CFG_IGNORE_ITEM} ${app})
+    endif()
+
     message(STATUS "fixup_bundle: verifying...")
     verify_app("${app}" IGNORE_ITEM "${CFG_IGNORE_ITEM}")
   else()
使用此模块,CPack将成功完成:

-- fixup_bundle: done
CPack: Create package
CPack: - package: ****.dmg generated.

谢谢假期过后我会试试这个。当我验证它是否有效时,我会将此标记为答案。我用一个C程序做了一个很小的例子,调用Python.h,它再现了错误。如果可以,我将把它放在一个公共存储库中,并将其作为一个bug提交给cmake.Validated,使用测试项目和使用Python.h的C程序以及我们更大的项目进行验证<代码>--fixup\U bundle:正在清理…--修复包:修复新发现的可执行文件/Users/myname/Projects/MyApp/build/release/MyApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python…
otool-L
显示它已经修复
build/release/MyApp.app/Contents/Frameworks/Python.framework/Versions/3.6/Resources/Python.Contents/Versions/3.6/compatibility version 3.6.0,当前版本3.6.0)@executable\u path//Frameworks/Python.framework/Versions/3.6/Python.app/Contents/MacOS/Python(兼容版本3.6.0,当前版本3.6.0)@executable\path//Frameworks/libint(兼容版本10.0.0,当前版本10.5.0)/usr/lib/libSystem.B.dylib(兼容版本1.0.0,当前版本1281.0.0)
还发布了cmake 3.16.2。确认问题仍然存在,并通过上述建议的解决方案修复。将向cmake提交错误,并在公共存储库中提供示例代码。cmake的错误报告:
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${resolved_resources}" "${resolved_embedded_resources}")
--- a/BundleUtilities.cmake 2019-12-28 02:10:43.000000000 +0100
+++ b/BundleUtilities.cmake 2019-12-28 09:39:26.000000000 +0100
@@ -982,6 +984,13 @@
     message(STATUS "fixup_bundle: cleaning up...")
     clear_bundle_keys(keys)

+    # Recursively discover and fix all subsequent executables.
+    get_bundle_all_executables("${bundle}" file_list)
+    list(REMOVE_ITEM file_list "${app}" ${CFG_IGNORE_ITEM})
+    list(LENGTH file_list nexecutables)
+    if (${nexecutables} GREATER 0)
+      list(GET file_list 0 f)
+      message(STATUS "fixup_bundle: fixing newly discovered executable ${f}...")
+      fixup_bundle("${f}" "" "${dirs}" IGNORE_ITEM ${CFG_IGNORE_ITEM} ${app})
+    endif()
+
     message(STATUS "fixup_bundle: verifying...")
     verify_app("${app}" IGNORE_ITEM "${CFG_IGNORE_ITEM}")
   else()
-- fixup_bundle: done
CPack: Create package
CPack: - package: ****.dmg generated.