diff --git a/BUILD b/BUILD index 3ae07ae..db34e8d 100644 --- a/BUILD +++ b/BUILD @@ -2,7 +2,7 @@ exports_files([ "._dummy_.py", "pywrapper.sh", "coverage_report.sh", -]) +] + glob(["external/*.BUILD"])) sh_library( name = "pywrapper", diff --git a/bazel_pybind11.bzl b/bazel_pybind11.bzl new file mode 100644 index 0000000..17c8e39 --- /dev/null +++ b/bazel_pybind11.bzl @@ -0,0 +1,138 @@ + +def bazel_pybind11( + name = "pybind11", + build_file = "@pybind11_bazel//:pybind11.BUILD", + sha256 = "c9375b7453bef1ba0106849c83881e6b6882d892c9fae5b2572a2192100ffb8a", + strip_prefix = "pybind11-a54eab92d265337996b8e4b4149d9176c2d428a6", + urls = ["https://github.com/pybind/pybind11/archive/a54eab92d265337996b8e4b4149d9176c2d428a6.tar.gz"], +): + native.http_archive( + name = name, + build_file = build_file, + sha256 = sha256, + strip_prefix = strip_prefix, + urls = urls, + ) + +# https://github.com/pybind/pybind11_bazel/blob/master/build_defs.bzl +# Copyright (c) 2019 The Pybind Development Team. All rights reserved. +# +# All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +"""Build rules for pybind11.""" + +def register_extension_info(**kwargs): + pass + +PYBIND_COPTS = select({ + "@pybind11//:msvc_compiler": [], + "//conditions:default": [ + "-fexceptions", + ], +}) + +PYBIND_FEATURES = [ + "-use_header_modules", # Required for pybind11. + "-parse_headers", +] + +PYBIND_DEPS = [ + "@pybind11", + # "@local_config_python//:python_headers", + # "@python//:python", + "@python", +] + +# Builds a Python extension module using pybind11. +# This can be directly used in python with the import statement. +# This adds rules for a .so binary file. +def pybind_extension( + name, + copts = [], + features = [], + linkopts = [], + tags = [], + deps = [], + **kwargs): + # Mark common dependencies as required for build_cleaner. + tags = tags + ["req_dep=%s" % dep for dep in PYBIND_DEPS] + + native.cc_binary( + name = name + ".so", + copts = copts + PYBIND_COPTS + select({ + "@pybind11//:msvc_compiler": [], + "//conditions:default": [ + "-fvisibility=hidden", + ], + }), + features = features + PYBIND_FEATURES, + linkopts = linkopts + select({ + "@pybind11//:msvc_compiler": [], + "@pybind11//:osx": [], + "//conditions:default": ["-Wl,-Bsymbolic"], + }), + linkshared = 1, + tags = tags, + deps = deps + PYBIND_DEPS, + **kwargs + ) + +# Builds a pybind11 compatible library. This can be linked to a pybind_extension. +def pybind_library( + name, + copts = [], + features = [], + tags = [], + deps = [], + **kwargs): + # Mark common dependencies as required for build_cleaner. + tags = tags + ["req_dep=%s" % dep for dep in PYBIND_DEPS] + + native.cc_library( + name = name, + copts = copts + PYBIND_COPTS, + features = features + PYBIND_FEATURES, + tags = tags, + deps = deps + PYBIND_DEPS, + **kwargs + ) + +# # Builds a C++ test for a pybind_library. +# def pybind_library_test( +# name, +# copts = [], +# features = [], +# tags = [], +# deps = [], +# **kwargs): +# # Mark common dependencies as required for build_cleaner. +# tags = tags + ["req_dep=%s" % dep for dep in PYBIND_DEPS] + +# native.cc_test( +# name = name, +# copts = copts + PYBIND_COPTS, +# features = features + PYBIND_FEATURES, +# tags = tags, +# deps = deps + PYBIND_DEPS + [ +# "//util/python:python_impl", +# "//util/python:test_main", +# ], +# **kwargs +# ) + +# Register extension with build_cleaner. +register_extension_info( + extension = pybind_extension, + label_regex_for_dep = "{extension_name}", +) + +register_extension_info( + extension = pybind_library, + label_regex_for_dep = "{extension_name}", +) + +# register_extension_info( +# extension = pybind_library_test, +# label_regex_for_dep = "{extension_name}", +# ) diff --git a/bazel_python.bzl b/bazel_python.bzl index ccde609..1a634c8 100644 --- a/bazel_python.bzl +++ b/bazel_python.bzl @@ -1,17 +1,119 @@ load("@bazel_tools//tools/python:toolchain.bzl", "py_runtime_pair") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") -def bazel_python(venv_name = "bazel_python_venv"): +""" Using a local pre-installed Python. """ + +_LOCAL_PYTHON_REPO_BUILD=""" +cc_library( + name = "python", + srcs = glob(["lib/*.a"]), + hdrs = glob([ + "include/**/*.h", + "include/**/**/*.h", + ]), + includes = ["include/python3.9"], + visibility = ["//visibility:public"], +) + +exports_files(glob(["bin/**"])) +""" + +def _setup_local_python_repository_impl(repository_ctx): + BAZEL_PYTHON_DIR = repository_ctx.attr.dir \ + or repository_ctx.os.environ.get("BAZEL_PYTHON_DIR", None) + if BAZEL_PYTHON_DIR == None: + fail("Environment variable `BAZEL_PYTHON_DIR` is missing.") + + path = "{}/{}".format(BAZEL_PYTHON_DIR, repository_ctx.attr.python_version) + repository_ctx.symlink(path, "") + repository_ctx.file("BUILD", + content = _LOCAL_PYTHON_REPO_BUILD, + executable = False, + legacy_utf8 = True + ) + return BAZEL_PYTHON_DIR + +setup_local_python_repository = repository_rule( + implementation = _setup_local_python_repository_impl, + attrs = { + "python_version": attr.string(), + "dir": attr.string() + }, + local = True, +) + +def bazel_local_python( + python_version = "3.9.7", + name = "python", + venv_name = "bazel_python_venv" +): + """Workspace rule setting up bazel_python for a repository from a + local Python installation. + + Arguments + ========= + @python_version should be a Python version number in `major.minor.patch`. + @name is the repository name. + @venv_name should match the 'name' argument given to the + bazel_python_interpreter call in the BUILD file. + """ + native.register_toolchains("//:" + venv_name + "_toolchain") + setup_local_python_repository( + name=name, + python_version=python_version + ) + + +""" Build a hermetic Python. """ + +_known_python_archives_sha256 = { + 3: { + 9: { + 7: "a838d3f9360d157040142b715db34f0218e535333696a5569dc6f854604eb9d1" + } + } +} + +def bazel_hermetic_python( + python_version = "3.9.7", + name = "python", + venv_name = "bazel_python_venv" +): """Workspace rule setting up bazel_python for a repository. Arguments ========= + @python_version should be a Python version number in `major.minor.patch`. + @name is the repository name. @venv_name should match the 'name' argument given to the bazel_python_interpreter call in the BUILD file. """ native.register_toolchains("//:" + venv_name + "_toolchain") + print(""" + ========================================================================================= + Warning: build a hermetic Python is experimental. + + Known issues: + 1. "[33/43] test_pprint -- test_pickle failed (6 errors)" during PGO. + 2. (Optional) `libsqlite3-dev` is required for Jupyter Notebook. + + TODOs: + 1. Build with tcmalloc. + ========================================================================================= + """) + py_major, py_minor, py_patch = [int(num) for num in python_version.split(".")] + http_archive( + name = name, + build_file = "@bazel_python//:external/python{major}.{minor}.BUILD".format( + major=py_major, minor=py_minor), + sha256 = _known_python_archives_sha256[py_major][py_minor][py_patch], + strip_prefix = "Python-{}".format(python_version), + urls = ["https://www.python.org/ftp/python/{0}/Python-{0}.tgz".format( + python_version)], + ) + def bazel_python_interpreter( - python_version, name = "bazel_python_venv", requirements_file = None, **kwargs): @@ -19,7 +121,7 @@ def bazel_python_interpreter( Arguments ========= - @python_version should be the Python version string to use (e.g. 3.7.4 is + @python_version (deprecated) should be the Python version string to use (e.g. 3.7.4 is the standard for DARG projects). You must run the setup_python.sh script with this version number. @name is your preferred Bazel name for referencing this. The default should @@ -30,7 +132,6 @@ def bazel_python_interpreter( """ bazel_python_venv( name = name, - python_version = python_version, requirements_file = requirements_file, **kwargs ) @@ -68,71 +169,151 @@ def bazel_python_interpreter( toolchain_type = "@bazel_tools//tools/python:toolchain_type", ) +# def _bazel_python_install_external(ctx, srcs): +# outs = [] +# for src in srcs: +# for file in src.files.to_list(): +# out = ctx.actions.declare_file("{dir}/{name}".format(dir=bazel_python_external_bin, name=file.basename)) +# outs.append(out) +# print(out.path) +# ctx.actions.symlink(output=out, target_file=file) + +# return outs + +def _resolve_external_index(ctx, index_file_path, srcs): + + files = [f for src in srcs for f in src.files.to_list()] + + index = ctx.actions.declare_file(index_file_path) + ctx.actions.write( + output=index, + content="\n".join([f.path for f in files]) + ) + + return index, files + def _bazel_python_venv_impl(ctx): """A Bazel rule to set up a Python virtual environment. Also installs requirements specified by @ctx.attr.requirements_file. """ - python_version = ctx.attr.python_version - use_system = False - only_warn = ctx.var.get("BAZEL_PYTHON_ONLY_WARN", "false").lower() == "true" - if "BAZEL_PYTHON_DIR" not in ctx.var: - if only_warn: - print("A bazel-python installation was not found. Falling back to the system python. For reproducibility, please run setup_python.sh for " + python_version) - use_system = True - else: - fail("You must run setup_python.sh for " + python_version) - if use_system: - python_dir = "" - else: - python_parent_dir = ctx.var.get("BAZEL_PYTHON_DIR") - python_dir = python_parent_dir + "/" + python_version - - # TODO: Fail if python_dir does not exist. + tool_inputs, tool_input_mfs = ctx.resolve_tools(tools = [ctx.attr.python]) venv_dir = ctx.actions.declare_directory("bazel_python_venv_installed") + inputs = [] - if use_system: - command = "" - else: - command = """ - export PATH={py_dir}/bin:$PATH - export PATH={py_dir}/include:$PATH - export PATH={py_dir}/lib:$PATH - export PATH={py_dir}/share:$PATH - export PYTHON_PATH={py_dir}:{py_dir}/bin:{py_dir}/include:{py_dir}/lib:{py_dir}/share - """ - command += """ - python3 -m venv {out_dir} || exit 1 - source {out_dir}/bin/activate || exit 1 + + inputs_setup = [ f for s in ctx.attr.setups for f in s.files.to_list() ] + index_setup = ctx.actions.declare_file("_external_setup_to_install") + ctx.actions.write( + output=index_setup, + content="\n".join([ s.label.workspace_root for s in ctx.attr.setups ]) + ) + + inputs.append(index_setup) + inputs.extend(inputs_setup) + + index_bin, inputs_bin = _resolve_external_index(ctx, "_external_bin_to_install", ctx.attr.bins) + + inputs.append(index_bin) + inputs.extend(inputs_bin) + + index_lib, inputs_lib = _resolve_external_index(ctx, "_external_lib_to_install", ctx.attr.libs) + + inputs.append(index_lib) + inputs.extend(inputs_lib) + + """ Setup venv. """ + command = """ + set -e + + $(readlink -f {py_executable}) -m venv {venv_dir} || exit 1 + source {venv_dir}/bin/activate || exit 1 + export venv_path={venv_dir} + export bazel_bin_path={bazel_bin_dir} + export PATH=$PWD/{venv_dir}/bin:$PWD/{venv_dir}/include:$PWD/{venv_dir}/lib:$PWD/{venv_dir}/share:$PATH + export LD_LIBRARY_PATH=$PWD/{venv_dir}/lib:$LD_LIBRARY_PATH + export PYTHONPATH=$PWD/{venv_dir}:$PWD/{venv_dir}/bin:$PWD/{venv_dir}/include:$PWD/{venv_dir}/lib:$PWD/{venv_dir}/share + + python3 -m pip install --upgrade pip + + for _external_bin_src in $(cat {index_bin}) + do + echo $_external_bin_src + ln -sfn $(readlink $_external_bin_src) $PWD/{venv_dir}/bin + done + rm {index_bin} + + for _external_lib_src in $(cat {index_lib}) + do + echo $_external_lib_src + ln -sfn $(readlink $_external_lib_src) $PWD/{venv_dir}/lib + done + rm {index_lib} + + for _external_setup_prefix in $(cat {index_setup}) + do + _external_setup_file=$(find . -path "*/$_external_setup_prefix/*/setup.py" | head -n 1) + pushd $(dirname $_external_setup_file) + python3 ./setup.py install || exit 1 + popd + done + rm {index_setup} + """ + + """ Install requirements.txt. """ if ctx.attr.requirements_file: command += "pip3 install -r " + ctx.file.requirements_file.path + " || exit 1" inputs.append(ctx.file.requirements_file) - for src in ctx.attr.run_after_pip_srcs: + + """ Include resources. """ + for src in ctx.attr.data: inputs.extend(src.files.to_list()) + + """ Append post-pip scripts. """ command += ctx.attr.run_after_pip + command += """ - REPLACEME=$PWD/'{out_dir}' + REPLACEME=$PWD/'{venv_dir}' REPLACEWITH='$PWD/bazel_python_venv_installed' # This prevents sed from trying to modify the directory. We may want to # do a more targeted sed in the future. - rm -rf {out_dir}/bin/__pycache__ || exit 1 - sed -i'' -e s:$REPLACEME:$REPLACEWITH:g {out_dir}/bin/* || exit 1 + rm -rf {venv_dir}/bin/__pycache__ || exit 1 + sed -i'' -e s:$REPLACEME:$REPLACEWITH:g {venv_dir}/bin/* || exit 1 """ + command = command.format( + py_executable = ctx.executable.python.path, + venv_dir = venv_dir.path, + bazel_bin_dir = ctx.bin_dir.path, + index_bin = index_bin.path, + index_lib = index_lib.path, + index_setup = index_setup.path, + ) + ctx.actions.run_shell( - command = command.format(py_dir = python_dir, out_dir = venv_dir.path), inputs = inputs, outputs = [venv_dir], + tools = tool_inputs, + command = command ) + return [DefaultInfo(files = depset([venv_dir]))] bazel_python_venv = rule( implementation = _bazel_python_venv_impl, attrs = { - "python_version": attr.string(), "requirements_file": attr.label(allow_single_file = True), + "bins": attr.label_list(allow_files = True), + "libs": attr.label_list(allow_files = True), + "setups": attr.label_list(allow_files = True), + "data": attr.label_list(allow_files = True), "run_after_pip": attr.string(), - "run_after_pip_srcs": attr.label_list(allow_files = True), + "python": attr.label( + executable = True, + allow_single_file = True, + cfg = 'exec', + default = Label("@python//:bin/python3"), + ), }, ) diff --git a/external/pybind11.BUILD b/external/pybind11.BUILD new file mode 100644 index 0000000..65fe8a2 --- /dev/null +++ b/external/pybind11.BUILD @@ -0,0 +1,62 @@ +# pybind11 - Seamless operability between C++11 and Python. +load("@rules_cc//cc:defs.bzl", "cc_library") + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +exports_files(["LICENSE"]) + +OPTIONS = select({ + ":msvc_compiler": [], + "//conditions:default": [ + "-fexceptions", + # Useless warnings + "-Xclang-only=-Wno-undefined-inline", + "-Xclang-only=-Wno-pragma-once-outside-header", + "-Xgcc-only=-Wno-error", # no way to just disable the pragma-once warning in gcc + ], +}) + +INCLUDES = [ + "include/pybind11/**/*.h", +] + +EXCLUDES = [ + # Deprecated file that just emits a warning + "include/pybind11/common.h", +] + +cc_library( + name = "pybind11", + hdrs = glob( + INCLUDES, + exclude = EXCLUDES, + ), + copts = OPTIONS, + includes = ["include"], + # deps = ["@local_config_python//:python_headers"], + deps = ["@python"], +) + +cc_library( + name = "pybind11_embed", + hdrs = glob( + INCLUDES, + exclude = EXCLUDES, + ), + copts = OPTIONS, + includes = ["include"], + # deps = ["@local_config_python//:python_embed"], + deps = ["@python"], +) + +config_setting( + name = "msvc_compiler", + flag_values = {"@bazel_tools//tools/cpp:compiler": "msvc-cl"}, +) + +config_setting( + name = "osx", + constraint_values = ["@platforms//os:osx"], +) diff --git a/external/python3.9.BUILD b/external/python3.9.BUILD new file mode 100644 index 0000000..974ce6c --- /dev/null +++ b/external/python3.9.BUILD @@ -0,0 +1,222 @@ +genrule( + name = "build_python", + srcs = glob(["**/**"]) + [ + "@local_config_cc//:toolchain", + ], + outs = [ + "bin/2to3", + "bin/2to3-3.9", + "bin/idle3", + "bin/idle3.9", + "bin/pip3", + "bin/pip3.9", + "bin/pydoc3", + "bin/pydoc3.9", + "bin/python3", + "bin/python3-config", + "bin/python3.9", + "bin/python3.9-config", + # + "lib/libpython3.9.a", + "lib/pkgconfig", + "lib/python3.9", + # + "include/python3.9/abstract.h", + "include/python3.9/asdl.h", + "include/python3.9/ast.h", + "include/python3.9/bitset.h", + "include/python3.9/bltinmodule.h", + "include/python3.9/boolobject.h", + "include/python3.9/bytearrayobject.h", + "include/python3.9/bytesobject.h", + "include/python3.9/cellobject.h", + "include/python3.9/ceval.h", + "include/python3.9/classobject.h", + "include/python3.9/code.h", + "include/python3.9/codecs.h", + "include/python3.9/compile.h", + "include/python3.9/complexobject.h", + "include/python3.9/context.h", + "include/python3.9/datetime.h", + "include/python3.9/descrobject.h", + "include/python3.9/dictobject.h", + "include/python3.9/dynamic_annotations.h", + "include/python3.9/enumobject.h", + "include/python3.9/errcode.h", + "include/python3.9/eval.h", + "include/python3.9/exports.h", + "include/python3.9/fileobject.h", + "include/python3.9/fileutils.h", + "include/python3.9/floatobject.h", + "include/python3.9/frameobject.h", + "include/python3.9/funcobject.h", + "include/python3.9/genericaliasobject.h", + "include/python3.9/genobject.h", + "include/python3.9/graminit.h", + "include/python3.9/grammar.h", + "include/python3.9/import.h", + "include/python3.9/interpreteridobject.h", + "include/python3.9/intrcheck.h", + "include/python3.9/iterobject.h", + "include/python3.9/listobject.h", + "include/python3.9/longintrepr.h", + "include/python3.9/longobject.h", + "include/python3.9/marshal.h", + "include/python3.9/memoryobject.h", + "include/python3.9/methodobject.h", + "include/python3.9/modsupport.h", + "include/python3.9/moduleobject.h", + "include/python3.9/namespaceobject.h", + "include/python3.9/node.h", + "include/python3.9/object.h", + "include/python3.9/objimpl.h", + "include/python3.9/odictobject.h", + "include/python3.9/opcode.h", + "include/python3.9/osdefs.h", + "include/python3.9/osmodule.h", + "include/python3.9/parsetok.h", + "include/python3.9/patchlevel.h", + "include/python3.9/picklebufobject.h", + "include/python3.9/py_curses.h", + "include/python3.9/pyarena.h", + "include/python3.9/pycapsule.h", + "include/python3.9/pyconfig.h", + "include/python3.9/pyctype.h", + "include/python3.9/pydebug.h", + "include/python3.9/pydtrace.h", + "include/python3.9/pyerrors.h", + "include/python3.9/pyexpat.h", + "include/python3.9/pyfpe.h", + "include/python3.9/pyframe.h", + "include/python3.9/pyhash.h", + "include/python3.9/pylifecycle.h", + "include/python3.9/pymacconfig.h", + "include/python3.9/pymacro.h", + "include/python3.9/pymath.h", + "include/python3.9/pymem.h", + "include/python3.9/pyport.h", + "include/python3.9/pystate.h", + "include/python3.9/pystrcmp.h", + "include/python3.9/pystrhex.h", + "include/python3.9/pystrtod.h", + "include/python3.9/Python-ast.h", + "include/python3.9/Python.h", + "include/python3.9/pythonrun.h", + "include/python3.9/pythread.h", + "include/python3.9/pytime.h", + "include/python3.9/rangeobject.h", + "include/python3.9/setobject.h", + "include/python3.9/sliceobject.h", + "include/python3.9/structmember.h", + "include/python3.9/structseq.h", + "include/python3.9/symtable.h", + "include/python3.9/sysmodule.h", + "include/python3.9/token.h", + "include/python3.9/traceback.h", + "include/python3.9/tracemalloc.h", + "include/python3.9/tupleobject.h", + "include/python3.9/typeslots.h", + "include/python3.9/ucnhash.h", + "include/python3.9/unicodeobject.h", + "include/python3.9/warnings.h", + "include/python3.9/weakrefobject.h", + "include/python3.9/cpython/abstract.h", + "include/python3.9/cpython/bytearrayobject.h", + "include/python3.9/cpython/bytesobject.h", + "include/python3.9/cpython/ceval.h", + "include/python3.9/cpython/code.h", + "include/python3.9/cpython/dictobject.h", + "include/python3.9/cpython/fileobject.h", + "include/python3.9/cpython/fileutils.h", + "include/python3.9/cpython/frameobject.h", + "include/python3.9/cpython/import.h", + "include/python3.9/cpython/initconfig.h", + "include/python3.9/cpython/interpreteridobject.h", + "include/python3.9/cpython/listobject.h", + "include/python3.9/cpython/methodobject.h", + "include/python3.9/cpython/object.h", + "include/python3.9/cpython/objimpl.h", + "include/python3.9/cpython/pyerrors.h", + "include/python3.9/cpython/pylifecycle.h", + "include/python3.9/cpython/pymem.h", + "include/python3.9/cpython/pystate.h", + "include/python3.9/cpython/sysmodule.h", + "include/python3.9/cpython/traceback.h", + "include/python3.9/cpython/tupleobject.h", + "include/python3.9/cpython/unicodeobject.h", + "include/python3.9/internal/pegen_interface.h", + "include/python3.9/internal/pycore_abstract.h", + "include/python3.9/internal/pycore_accu.h", + "include/python3.9/internal/pycore_atomic.h", + "include/python3.9/internal/pycore_bytes_methods.h", + "include/python3.9/internal/pycore_byteswap.h", + "include/python3.9/internal/pycore_call.h", + "include/python3.9/internal/pycore_ceval.h", + "include/python3.9/internal/pycore_code.h", + "include/python3.9/internal/pycore_condvar.h", + "include/python3.9/internal/pycore_context.h", + "include/python3.9/internal/pycore_dtoa.h", + "include/python3.9/internal/pycore_fileutils.h", + "include/python3.9/internal/pycore_gc.h", + "include/python3.9/internal/pycore_getopt.h", + "include/python3.9/internal/pycore_gil.h", + "include/python3.9/internal/pycore_hamt.h", + "include/python3.9/internal/pycore_hashtable.h", + "include/python3.9/internal/pycore_import.h", + "include/python3.9/internal/pycore_initconfig.h", + "include/python3.9/internal/pycore_interp.h", + "include/python3.9/internal/pycore_object.h", + "include/python3.9/internal/pycore_pathconfig.h", + "include/python3.9/internal/pycore_pyerrors.h", + "include/python3.9/internal/pycore_pyhash.h", + "include/python3.9/internal/pycore_pylifecycle.h", + "include/python3.9/internal/pycore_pymem.h", + "include/python3.9/internal/pycore_pystate.h", + "include/python3.9/internal/pycore_runtime.h", + "include/python3.9/internal/pycore_sysmodule.h", + "include/python3.9/internal/pycore_traceback.h", + "include/python3.9/internal/pycore_tupleobject.h", + "include/python3.9/internal/pycore_warnings.h", + ], + cmd = """ + OUT_DIR=$$PWD/$(@D) + rm -rf $$OUT_DIR + mkdir $$OUT_DIR + # + cd external/python + INSTALL_DIR=$$PWD/out + # + CFLAGS=-fPIC ./configure \ + --prefix=$$OUT_DIR \ + --exec_prefix=$$OUT_DIR \ + --enable-loadable-sqlite-extensions \ + --enable-optimizations \ + --enable-shared=no + + make && make install + # + if ! $$OUT_DIR/bin/python3 -c "import ssl" + then + echo "ERROR: Python was built *WITHOUT* the SSL module. This will break PyPI downloads. Please re-run this script after installing libssl-dev (see the README)." + exit 1 + fi + if ! $$OUT_DIR/bin/python3 -c "import zlib" + then + echo "ERROR: Python was built *WITHOUT* the zlib module. If needed, please re-run this script after installing zlib1g-dev (see the README)." + exit 1 + fi + """, + visibility = ["//visibility:public"], +) + +cc_library( + name = "python", + srcs = glob(["lib/*.a"]) + [":build_python"], + hdrs = glob([ + "include/**/*.h", + "include/**/**/*.h", + ]), + includes = ["include/python3.9"], + linkstatic = 1, + visibility = ["//visibility:public"], +) diff --git a/pywrapper.sh b/pywrapper.sh index 647a487..2ec3398 100755 --- a/pywrapper.sh +++ b/pywrapper.sh @@ -6,8 +6,17 @@ # bazel_out/.../[mainworkspace]. This searches for the first matching path then # exits, so it should be reasonably fast in most cases. # https://unix.stackexchange.com/questions/68414/only-find-first-few-matched-files-using-find -venv_path=$((find -L . -path "*/bazel_python_venv_installed/bin/activate" & ) | head -n 1) +venv_activate=$((find -L $PWD -path "*/bazel_python_venv_installed/bin/activate" & ) | head -n 1) +venv_path=$(dirname $(dirname $venv_activate)) # If venv_path was not found it will be empty and the below will throw an # error, alerting Bazel something went wrong. -source $venv_path || exit 1 -python $@ +source $venv_activate || exit 1 + +# Not sure should we expose $PATH or not. +export PATH=$venv_path/bin:$PATH #:$venv_path/include:$venv_path/lib:$venv_path/share:$PATH +export LD_LIBRARY_PATH=$venv_path/lib #:${LD_LIBRARY_PATH} + +# export PYTHONPATH=$venv_path:$venv_path/bin:$venv_path/include:$venv_path/lib:$venv_path/share +export PYTHONPATH=$(/usr/bin/dirname $1):$PYTHONPATH + +$venv_path/bin/python3 $@ diff --git a/setup_python.sh b/setup_python.sh index e05c139..b350012 100755 --- a/setup_python.sh +++ b/setup_python.sh @@ -25,9 +25,9 @@ then tar -xzf Python-$version.tgz cd Python-$version - ./configure --prefix=$install_dir $@ + CFLAGS=-fPIC ./configure --prefix=$install_dir $@ - make -j + make make install cd $install_dir rm -rf Python-$version @@ -49,4 +49,4 @@ then fi else echo "Aborting." -fi +fi \ No newline at end of file