我如何告诉Bazel Python.h住在哪里? [英] How do I tell Bazel where Python.h lives?

查看:106
本文介绍了我如何告诉Bazel Python.h住在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个C ++可执行文件,该文件需要从用户的Python安装中#include"Python.h".

要在Bazel中表达Python.h(及其包含的各种头文件),我需要知道Python包含目录在哪里.在Windows和Linux上,此位置将有所不同,我希望使用单个Bazel配置来同时构建它们.

引用在WORKSPACE根目录之外的软件的最佳Bazel做法是什么?

解决方案

因此,要告诉Bazel外部依赖项,您需要使用选择( )函数,以使Bazel为您的主机操作系统选择合适的库来构建.

这是实现目标的一种动力:

首先,我们在项目的根目录中有WORKSPACE文件,该文件定义了两个库以及用于它们的BUILD文件.在这里,我只是使用build_file_content,但是如果这变得太复杂了,则可以将其放在自己的文件中,然后引用它.此处的BUILD文件公开了Python随附的预构建库以及所需的头文件.它还为依赖于这些库的任何目标添加了一个包含路径,因此您可以#include "Python.h"

new_local_repository(
    name = "python_linux",
    path = "/usr",
    build_file_content = """
cc_library(
    name = "python35-lib",
    srcs = ["lib/python3.5/config-3.5m-x86_64-linux-gnu/libpython3.5.so"],
    hdrs = glob(["include/python3.5/*.h"]),
    includes = ["include/python3.5"],
    visibility = ["//visibility:public"]
)
    """
)

new_local_repository(
    name = "python_win",
    path = "C:/Python35",
    build_file_content = """
cc_library(
    name = "python35-lib",
    srcs = ["libs/python35.lib"],
    hdrs = glob(["include/*.h"]),
    includes = ["include/"],
    visibility = ["//visibility:public"]
)
    """
)

接下来是您的应用程序的BUILD文件.在这里,您需要定义一些 config_settings .这使我们能够为我们的构建定义平台相关的设置.我们使用cpu值确定主机操作系统.

cc_binary规则中,我们使用select()函数根据配置选择要链接的正确主机库.

config_setting(
    name = "linux_x86_64",
    values = {"cpu": "k8"},
    visibility = ["//visibility:public"],
)

config_setting(
    name = "windows",
    values = {"cpu": "x64_windows"},
    visibility = ["//visibility:public"],
)

cc_binary(
    name="python-test",
    srcs = [
        "main.c",
    ],
    deps = select({
        "//:linux_x86_64": [
            "@python_linux//:python35-lib"
        ],
        "//:windows": [
            "@python_win//:python35-lib"
        ]
    })
)

FWIW这是我正在玩的main.c,以使其正常工作.

#include "Python.h"

int main(int argc, char *argv[])
{
  Py_SetProgramName(argv[0]);  /* optional but recommended */
  Py_Initialize();
  PyRun_SimpleString("from time import time,ctime\n"
                     "print('Today is',ctime(time()))\n");
  Py_Finalize();
  return 0;
}

另一种方法(也许更简单)是将python标头和库检查到存储库中.您仍然需要使用select()选择要链接的正确库,但是至少您无需在WORKSPACE文件中添加任何内容,而只需依赖存储库中的另一个BUILD文件即可.如果您查看 Bazel存储库,他们会将大量外部依赖项签入third_party目录,因此它是常见的做法.

I'm building a C++ executable that needs to #include "Python.h" from the user's Python installation.

To express Python.h (and the various header files it includes) in Bazel, I need to know where the Python include directory is. This location will be different on Windows and Linux, and I'd like a single Bazel configuration to build them both.

What's the best Bazel practice for referencing software that exists outside of the WORKSPACE root?

解决方案

So to tell Bazel about external dependencies you need to use one of the Workspace Rules to specify the location of the external dependency, as well as the BUILD file for Bazel to use with that external dependency.

To have something work cross-platform you need to use the select() function to have Bazel select the proper library to build against for your host operating system.

Here's a stab at accomplishing it:

First we have the WORKSPACE file in your project's root that defines the two libraries and the BUILD file to use for them. Here I'm just using build_file_content but if that becomes too complex you can put it in it's own file and reference it instead. The BUILD file here exposes the prebuild library shipped with Python along with the header files needed. It also adds an include path for any targets that depend on these libraries so you can do #include "Python.h"

new_local_repository(
    name = "python_linux",
    path = "/usr",
    build_file_content = """
cc_library(
    name = "python35-lib",
    srcs = ["lib/python3.5/config-3.5m-x86_64-linux-gnu/libpython3.5.so"],
    hdrs = glob(["include/python3.5/*.h"]),
    includes = ["include/python3.5"],
    visibility = ["//visibility:public"]
)
    """
)

new_local_repository(
    name = "python_win",
    path = "C:/Python35",
    build_file_content = """
cc_library(
    name = "python35-lib",
    srcs = ["libs/python35.lib"],
    hdrs = glob(["include/*.h"]),
    includes = ["include/"],
    visibility = ["//visibility:public"]
)
    """
)

Next the BUILD file for your application. Here you need to define some config_settings. This allows us to define platform dependent settings for our build. We use the cpu value to determine the host OS.

In the cc_binary rule we use the select() function to choose the correct host library to link against based on the configuration.

config_setting(
    name = "linux_x86_64",
    values = {"cpu": "k8"},
    visibility = ["//visibility:public"],
)

config_setting(
    name = "windows",
    values = {"cpu": "x64_windows"},
    visibility = ["//visibility:public"],
)

cc_binary(
    name="python-test",
    srcs = [
        "main.c",
    ],
    deps = select({
        "//:linux_x86_64": [
            "@python_linux//:python35-lib"
        ],
        "//:windows": [
            "@python_win//:python35-lib"
        ]
    })
)

FWIW here's the main.c I was playing around with to get this working.

#include "Python.h"

int main(int argc, char *argv[])
{
  Py_SetProgramName(argv[0]);  /* optional but recommended */
  Py_Initialize();
  PyRun_SimpleString("from time import time,ctime\n"
                     "print('Today is',ctime(time()))\n");
  Py_Finalize();
  return 0;
}

Another way (and perhaps simpler) is checking the python headers and libraries into your repository. You will still need to use select() to choose the correct library to link against but at least you won't need to add anything to your WORKSPACE file and can just rely on another BUILD file in your repository. If you look at the Bazel repo they check in lots of external dependencies into the third_party directory, so it's a common practice.

这篇关于我如何告诉Bazel Python.h住在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆