CMake 使用 Homebrew 公式安装 pybind11 绑定
CMake install pybind11 bindings using Homebrew formula
我想为构建和安装 C++ 库及其使用 pybind11 编写的 Python 绑定的 CMake 项目提供 Homebrew 公式。理想情况下,该公式应该通过 运行 a plain
cmake --build . --target install
此安装流程在本地运行良好,但使用 Homebrew 公式会在 Python 绑定的安装目录中引入问题:而 headers 和库安装在 Cellar 的正确目录中由#{prefix} 标识,绑定需要位于 Python 可见的 site-packages 目录中。我在 CMake 中使用
获取这样的目录
install(TARGETS pyariadne DESTINATION ${Python_SITEARCH})
但是 Homebrew 似乎无法写入该目录,返回一个 Operation not permitted
。
通过以下方式识别安装目录
execute_process(COMMAND python3 -m site --user-site OUTPUT_VARIABLE INSTALL_DIR)
也不起作用,因为 Homebrew 在 /tmp 中标识了一个临时用户站点,因此安装在那里的任何库随后都会被删除。
我应该如何安装 Homebrew 中的所有内容,而不求助于更改目录权限?我想避免打包 pypi 并使用 pip 单独安装绑定。
编辑(输出示例,涉及的目录):
[109/110] Install the project...
-- Install configuration: "Release"
-- Installing:
/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pyariadne.so
CMake Error at cmake_install.cmake:49 (file):
file INSTALL cannot copy file
"/tmp/ariadne-20210305-1763-ggejxl/ariadne-2.1-rc2/build/pyariadne.so" to
"/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pyariadne.so":
Operation not permitted.
目录 /usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages
链接到 /usr/local/lib/python3.9/site-packages
。前者有用户lgeretti:staff,后者有用户lgeretti:admin.
这个问题不仅发生在我的机器上,而且我还在 macos:latest GitHub Actions 机器上验证了它,唯一需要的步骤是 brew install 包。
在 Homebrew 讨论中找到 this post 的解决方案,该解决方案依赖于 libexec 目录和 pth 文件创建:
- 在 CMake 中使用 libexec 作为安装目标,以使用 Homebrew 而不是本地安装为条件:
if (HOMEBREW)
install(TARGETS pyariadne DESTINATION libexec)
else()
find_package(Python)
install(TARGETS pyariadne DESTINATION ${Python_SITEARCH})
endif()
- 在公式中设置以下内容,以创建 .pth 文件:
def install
mkdir "build" do
system "cmake -G \"Ninja\" .. -DCMAKE_BUILD_TYPE=Release -DHOMEBREW=1 -DCMAKE_INSTALL_PREFIX=#{prefix}"
system "cmake", "--build", ".", "--target", "install", "--parallel"
end
python_version = Language::Python.major_minor_version Formula["python@3.9"].bin/"python3"
(lib/"python#{python_version}/site-packages/homebrew-ariadne.pth").write <<~EOS
import site; site.addsitedir('#{libexec}')
EOS
end
这是一个更好的 CMake 实现 Luca 的好解决方案。应该通过缓存变量直接引入包定制点,而不是特定于包装程序的标志。这是标准 GNUInstallDirs
模块采用的方法。见下文:
find_package(Python)
set(MyProj_INSTALL_PYTHONDIR "${Python_SITEARCH}"
CACHE STRING "Install destination for Python targets")
install(TARGETS pyariadne DESTINATION "${MyProj_INSTALL_PYTHONDIR}")
MyProj_INSTALL_PYTHONDIR
的默认值为Python_SITEARCH
,但可以在包脚本中覆盖:
def install
mkdir "build" do
system "cmake -G \"Ninja\" .. -DCMAKE_BUILD_TYPE=Release " \
"-DMyProj_INSTALL_PYTHONDIR=libexec -DCMAKE_INSTALL_PREFIX=#{prefix}"
system "cmake", "--build", ".", "--target", "install", "--parallel"
end
python_version = Language::Python.major_minor_version Formula["python@3.9"].bin/"python3"
(lib/"python#{python_version}/site-packages/homebrew-ariadne.pth").write <<~EOS
import site; site.addsitedir('#{libexec}')
EOS
end
这种方式明显更好,因为 CMake 构建不再需要了解 Homebrew 的任何信息。
我想为构建和安装 C++ 库及其使用 pybind11 编写的 Python 绑定的 CMake 项目提供 Homebrew 公式。理想情况下,该公式应该通过 运行 a plain
cmake --build . --target install
此安装流程在本地运行良好,但使用 Homebrew 公式会在 Python 绑定的安装目录中引入问题:而 headers 和库安装在 Cellar 的正确目录中由#{prefix} 标识,绑定需要位于 Python 可见的 site-packages 目录中。我在 CMake 中使用
获取这样的目录install(TARGETS pyariadne DESTINATION ${Python_SITEARCH})
但是 Homebrew 似乎无法写入该目录,返回一个 Operation not permitted
。
通过以下方式识别安装目录
execute_process(COMMAND python3 -m site --user-site OUTPUT_VARIABLE INSTALL_DIR)
也不起作用,因为 Homebrew 在 /tmp 中标识了一个临时用户站点,因此安装在那里的任何库随后都会被删除。
我应该如何安装 Homebrew 中的所有内容,而不求助于更改目录权限?我想避免打包 pypi 并使用 pip 单独安装绑定。
编辑(输出示例,涉及的目录):
[109/110] Install the project...
-- Install configuration: "Release"
-- Installing:
/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pyariadne.so
CMake Error at cmake_install.cmake:49 (file):
file INSTALL cannot copy file
"/tmp/ariadne-20210305-1763-ggejxl/ariadne-2.1-rc2/build/pyariadne.so" to
"/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pyariadne.so":
Operation not permitted.
目录 /usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages
链接到 /usr/local/lib/python3.9/site-packages
。前者有用户lgeretti:staff,后者有用户lgeretti:admin.
这个问题不仅发生在我的机器上,而且我还在 macos:latest GitHub Actions 机器上验证了它,唯一需要的步骤是 brew install 包。
在 Homebrew 讨论中找到 this post 的解决方案,该解决方案依赖于 libexec 目录和 pth 文件创建:
- 在 CMake 中使用 libexec 作为安装目标,以使用 Homebrew 而不是本地安装为条件:
if (HOMEBREW)
install(TARGETS pyariadne DESTINATION libexec)
else()
find_package(Python)
install(TARGETS pyariadne DESTINATION ${Python_SITEARCH})
endif()
- 在公式中设置以下内容,以创建 .pth 文件:
def install
mkdir "build" do
system "cmake -G \"Ninja\" .. -DCMAKE_BUILD_TYPE=Release -DHOMEBREW=1 -DCMAKE_INSTALL_PREFIX=#{prefix}"
system "cmake", "--build", ".", "--target", "install", "--parallel"
end
python_version = Language::Python.major_minor_version Formula["python@3.9"].bin/"python3"
(lib/"python#{python_version}/site-packages/homebrew-ariadne.pth").write <<~EOS
import site; site.addsitedir('#{libexec}')
EOS
end
这是一个更好的 CMake 实现 Luca 的好解决方案。应该通过缓存变量直接引入包定制点,而不是特定于包装程序的标志。这是标准 GNUInstallDirs
模块采用的方法。见下文:
find_package(Python)
set(MyProj_INSTALL_PYTHONDIR "${Python_SITEARCH}"
CACHE STRING "Install destination for Python targets")
install(TARGETS pyariadne DESTINATION "${MyProj_INSTALL_PYTHONDIR}")
MyProj_INSTALL_PYTHONDIR
的默认值为Python_SITEARCH
,但可以在包脚本中覆盖:
def install
mkdir "build" do
system "cmake -G \"Ninja\" .. -DCMAKE_BUILD_TYPE=Release " \
"-DMyProj_INSTALL_PYTHONDIR=libexec -DCMAKE_INSTALL_PREFIX=#{prefix}"
system "cmake", "--build", ".", "--target", "install", "--parallel"
end
python_version = Language::Python.major_minor_version Formula["python@3.9"].bin/"python3"
(lib/"python#{python_version}/site-packages/homebrew-ariadne.pth").write <<~EOS
import site; site.addsitedir('#{libexec}')
EOS
end
这种方式明显更好,因为 CMake 构建不再需要了解 Homebrew 的任何信息。