1*cc02d7e2SAndroid Build Coastguard Worker# Adapted with modifications from tensorflow/third_party/py/ 2*cc02d7e2SAndroid Build Coastguard Worker"""Repository rule for Python autoconfiguration. 3*cc02d7e2SAndroid Build Coastguard Worker 4*cc02d7e2SAndroid Build Coastguard Worker`python_configure` depends on the following environment variables: 5*cc02d7e2SAndroid Build Coastguard Worker 6*cc02d7e2SAndroid Build Coastguard Worker * `PYTHON3_BIN_PATH`: location of python binary. 7*cc02d7e2SAndroid Build Coastguard Worker * `PYTHON3_LIB_PATH`: Location of python libraries. 8*cc02d7e2SAndroid Build Coastguard Worker""" 9*cc02d7e2SAndroid Build Coastguard Worker 10*cc02d7e2SAndroid Build Coastguard Worker_BAZEL_SH = "BAZEL_SH" 11*cc02d7e2SAndroid Build Coastguard Worker_PYTHON3_BIN_PATH = "PYTHON3_BIN_PATH" 12*cc02d7e2SAndroid Build Coastguard Worker_PYTHON3_LIB_PATH = "PYTHON3_LIB_PATH" 13*cc02d7e2SAndroid Build Coastguard Worker 14*cc02d7e2SAndroid Build Coastguard Worker_HEADERS_HELP = ( 15*cc02d7e2SAndroid Build Coastguard Worker "Are Python headers installed? Try installing " + 16*cc02d7e2SAndroid Build Coastguard Worker "python3-dev on Debian-based systems. Try python3-devel " + 17*cc02d7e2SAndroid Build Coastguard Worker "on Redhat-based systems." 18*cc02d7e2SAndroid Build Coastguard Worker) 19*cc02d7e2SAndroid Build Coastguard Worker 20*cc02d7e2SAndroid Build Coastguard Workerdef _tpl(repository_ctx, tpl, substitutions = {}, out = None): 21*cc02d7e2SAndroid Build Coastguard Worker if not out: 22*cc02d7e2SAndroid Build Coastguard Worker out = tpl 23*cc02d7e2SAndroid Build Coastguard Worker repository_ctx.template( 24*cc02d7e2SAndroid Build Coastguard Worker out, 25*cc02d7e2SAndroid Build Coastguard Worker Label("//third_party/py:%s.tpl" % tpl), 26*cc02d7e2SAndroid Build Coastguard Worker substitutions, 27*cc02d7e2SAndroid Build Coastguard Worker ) 28*cc02d7e2SAndroid Build Coastguard Worker 29*cc02d7e2SAndroid Build Coastguard Workerdef _fail(msg): 30*cc02d7e2SAndroid Build Coastguard Worker """Output failure message when auto configuration fails.""" 31*cc02d7e2SAndroid Build Coastguard Worker red = "\033[0;31m" 32*cc02d7e2SAndroid Build Coastguard Worker no_color = "\033[0m" 33*cc02d7e2SAndroid Build Coastguard Worker fail("%sPython Configuration Error:%s %s\n" % (red, no_color, msg)) 34*cc02d7e2SAndroid Build Coastguard Worker 35*cc02d7e2SAndroid Build Coastguard Workerdef _is_windows(repository_ctx): 36*cc02d7e2SAndroid Build Coastguard Worker """Returns true if the host operating system is windows.""" 37*cc02d7e2SAndroid Build Coastguard Worker os_name = repository_ctx.os.name.lower() 38*cc02d7e2SAndroid Build Coastguard Worker return os_name.find("windows") != -1 39*cc02d7e2SAndroid Build Coastguard Worker 40*cc02d7e2SAndroid Build Coastguard Workerdef _execute( 41*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 42*cc02d7e2SAndroid Build Coastguard Worker cmdline, 43*cc02d7e2SAndroid Build Coastguard Worker error_msg = None, 44*cc02d7e2SAndroid Build Coastguard Worker error_details = None, 45*cc02d7e2SAndroid Build Coastguard Worker empty_stdout_fine = False): 46*cc02d7e2SAndroid Build Coastguard Worker """Executes an arbitrary shell command. 47*cc02d7e2SAndroid Build Coastguard Worker 48*cc02d7e2SAndroid Build Coastguard Worker Args: 49*cc02d7e2SAndroid Build Coastguard Worker repository_ctx: the repository_ctx object 50*cc02d7e2SAndroid Build Coastguard Worker cmdline: list of strings, the command to execute 51*cc02d7e2SAndroid Build Coastguard Worker error_msg: string, a summary of the error if the command fails 52*cc02d7e2SAndroid Build Coastguard Worker error_details: string, details about the error or steps to fix it 53*cc02d7e2SAndroid Build Coastguard Worker empty_stdout_fine: bool, if True, an empty stdout result is fine, otherwise 54*cc02d7e2SAndroid Build Coastguard Worker it's an error 55*cc02d7e2SAndroid Build Coastguard Worker Return: 56*cc02d7e2SAndroid Build Coastguard Worker the result of repository_ctx.execute(cmdline) 57*cc02d7e2SAndroid Build Coastguard Worker """ 58*cc02d7e2SAndroid Build Coastguard Worker result = repository_ctx.execute(cmdline) 59*cc02d7e2SAndroid Build Coastguard Worker if result.stderr or not (empty_stdout_fine or result.stdout): 60*cc02d7e2SAndroid Build Coastguard Worker _fail("\n".join([ 61*cc02d7e2SAndroid Build Coastguard Worker error_msg.strip() if error_msg else "Repository command failed", 62*cc02d7e2SAndroid Build Coastguard Worker result.stderr.strip(), 63*cc02d7e2SAndroid Build Coastguard Worker error_details if error_details else "", 64*cc02d7e2SAndroid Build Coastguard Worker ])) 65*cc02d7e2SAndroid Build Coastguard Worker else: 66*cc02d7e2SAndroid Build Coastguard Worker return result 67*cc02d7e2SAndroid Build Coastguard Worker 68*cc02d7e2SAndroid Build Coastguard Workerdef _read_dir(repository_ctx, src_dir): 69*cc02d7e2SAndroid Build Coastguard Worker """Returns a string with all files in a directory. 70*cc02d7e2SAndroid Build Coastguard Worker 71*cc02d7e2SAndroid Build Coastguard Worker Finds all files inside a directory, traversing subfolders and following 72*cc02d7e2SAndroid Build Coastguard Worker symlinks. The returned string contains the full path of all files 73*cc02d7e2SAndroid Build Coastguard Worker separated by line breaks. 74*cc02d7e2SAndroid Build Coastguard Worker """ 75*cc02d7e2SAndroid Build Coastguard Worker if _is_windows(repository_ctx): 76*cc02d7e2SAndroid Build Coastguard Worker src_dir = src_dir.replace("/", "\\") 77*cc02d7e2SAndroid Build Coastguard Worker find_result = _execute( 78*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 79*cc02d7e2SAndroid Build Coastguard Worker ["cmd.exe", "/c", "dir", src_dir, "/b", "/s", "/a-d"], 80*cc02d7e2SAndroid Build Coastguard Worker empty_stdout_fine = True, 81*cc02d7e2SAndroid Build Coastguard Worker ) 82*cc02d7e2SAndroid Build Coastguard Worker 83*cc02d7e2SAndroid Build Coastguard Worker # src_files will be used in genrule.outs where the paths must 84*cc02d7e2SAndroid Build Coastguard Worker # use forward slashes. 85*cc02d7e2SAndroid Build Coastguard Worker return find_result.stdout.replace("\\", "/") 86*cc02d7e2SAndroid Build Coastguard Worker else: 87*cc02d7e2SAndroid Build Coastguard Worker find_result = _execute( 88*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 89*cc02d7e2SAndroid Build Coastguard Worker ["find", src_dir, "-follow", "-type", "f"], 90*cc02d7e2SAndroid Build Coastguard Worker empty_stdout_fine = True, 91*cc02d7e2SAndroid Build Coastguard Worker ) 92*cc02d7e2SAndroid Build Coastguard Worker return find_result.stdout 93*cc02d7e2SAndroid Build Coastguard Worker 94*cc02d7e2SAndroid Build Coastguard Workerdef _genrule(src_dir, genrule_name, command, outs): 95*cc02d7e2SAndroid Build Coastguard Worker """Returns a string with a genrule. 96*cc02d7e2SAndroid Build Coastguard Worker 97*cc02d7e2SAndroid Build Coastguard Worker Genrule executes the given command and produces the given outputs. 98*cc02d7e2SAndroid Build Coastguard Worker """ 99*cc02d7e2SAndroid Build Coastguard Worker return ("genrule(\n" + ' name = "' + genrule_name + '",\n' + 100*cc02d7e2SAndroid Build Coastguard Worker " outs = [\n" + outs + "\n ],\n" + ' cmd = """\n' + 101*cc02d7e2SAndroid Build Coastguard Worker command + '\n """,\n' + ")\n") 102*cc02d7e2SAndroid Build Coastguard Worker 103*cc02d7e2SAndroid Build Coastguard Workerdef _normalize_path(path): 104*cc02d7e2SAndroid Build Coastguard Worker """Returns a path with '/' and remove the trailing slash.""" 105*cc02d7e2SAndroid Build Coastguard Worker path = path.replace("\\", "/") 106*cc02d7e2SAndroid Build Coastguard Worker if path[-1] == "/": 107*cc02d7e2SAndroid Build Coastguard Worker path = path[:-1] 108*cc02d7e2SAndroid Build Coastguard Worker return path 109*cc02d7e2SAndroid Build Coastguard Worker 110*cc02d7e2SAndroid Build Coastguard Workerdef _symlink_genrule_for_dir( 111*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 112*cc02d7e2SAndroid Build Coastguard Worker src_dir, 113*cc02d7e2SAndroid Build Coastguard Worker dest_dir, 114*cc02d7e2SAndroid Build Coastguard Worker genrule_name, 115*cc02d7e2SAndroid Build Coastguard Worker src_files = [], 116*cc02d7e2SAndroid Build Coastguard Worker dest_files = []): 117*cc02d7e2SAndroid Build Coastguard Worker """Returns a genrule to symlink(or copy if on Windows) a set of files. 118*cc02d7e2SAndroid Build Coastguard Worker 119*cc02d7e2SAndroid Build Coastguard Worker If src_dir is passed, files will be read from the given directory; otherwise 120*cc02d7e2SAndroid Build Coastguard Worker we assume files are in src_files and dest_files 121*cc02d7e2SAndroid Build Coastguard Worker """ 122*cc02d7e2SAndroid Build Coastguard Worker if src_dir != None: 123*cc02d7e2SAndroid Build Coastguard Worker src_dir = _normalize_path(src_dir) 124*cc02d7e2SAndroid Build Coastguard Worker dest_dir = _normalize_path(dest_dir) 125*cc02d7e2SAndroid Build Coastguard Worker files = "\n".join( 126*cc02d7e2SAndroid Build Coastguard Worker sorted(_read_dir(repository_ctx, src_dir).splitlines()), 127*cc02d7e2SAndroid Build Coastguard Worker ) 128*cc02d7e2SAndroid Build Coastguard Worker 129*cc02d7e2SAndroid Build Coastguard Worker # Create a list with the src_dir stripped to use for outputs. 130*cc02d7e2SAndroid Build Coastguard Worker dest_files = files.replace(src_dir, "").splitlines() 131*cc02d7e2SAndroid Build Coastguard Worker src_files = files.splitlines() 132*cc02d7e2SAndroid Build Coastguard Worker command = [] 133*cc02d7e2SAndroid Build Coastguard Worker outs = [] 134*cc02d7e2SAndroid Build Coastguard Worker for i in range(len(dest_files)): 135*cc02d7e2SAndroid Build Coastguard Worker if dest_files[i] != "": 136*cc02d7e2SAndroid Build Coastguard Worker # If we have only one file to link we do not want to use the dest_dir, as 137*cc02d7e2SAndroid Build Coastguard Worker # $(@D) will include the full path to the file. 138*cc02d7e2SAndroid Build Coastguard Worker dest = "$(@D)/" + dest_dir + dest_files[i] if len( 139*cc02d7e2SAndroid Build Coastguard Worker dest_files, 140*cc02d7e2SAndroid Build Coastguard Worker ) != 1 else "$(@D)/" + dest_files[i] 141*cc02d7e2SAndroid Build Coastguard Worker 142*cc02d7e2SAndroid Build Coastguard Worker # On Windows, symlink is not supported, so we just copy all the files. 143*cc02d7e2SAndroid Build Coastguard Worker cmd = "cp -f" if _is_windows(repository_ctx) else "ln -s" 144*cc02d7e2SAndroid Build Coastguard Worker command.append(cmd + ' "%s" "%s"' % (src_files[i], dest)) 145*cc02d7e2SAndroid Build Coastguard Worker outs.append(' "' + dest_dir + dest_files[i] + '",') 146*cc02d7e2SAndroid Build Coastguard Worker return _genrule( 147*cc02d7e2SAndroid Build Coastguard Worker src_dir, 148*cc02d7e2SAndroid Build Coastguard Worker genrule_name, 149*cc02d7e2SAndroid Build Coastguard Worker " && ".join(command), 150*cc02d7e2SAndroid Build Coastguard Worker "\n".join(outs), 151*cc02d7e2SAndroid Build Coastguard Worker ) 152*cc02d7e2SAndroid Build Coastguard Worker 153*cc02d7e2SAndroid Build Coastguard Workerdef _get_python_bin(repository_ctx, bin_path_key, default_bin_path, allow_absent): 154*cc02d7e2SAndroid Build Coastguard Worker """Gets the python bin path.""" 155*cc02d7e2SAndroid Build Coastguard Worker python_bin = repository_ctx.os.environ.get(bin_path_key, default_bin_path) 156*cc02d7e2SAndroid Build Coastguard Worker if not repository_ctx.path(python_bin).exists: 157*cc02d7e2SAndroid Build Coastguard Worker # It's a command, use 'which' to find its path. 158*cc02d7e2SAndroid Build Coastguard Worker python_bin_path = repository_ctx.which(python_bin) 159*cc02d7e2SAndroid Build Coastguard Worker else: 160*cc02d7e2SAndroid Build Coastguard Worker # It's a path, use it as it is. 161*cc02d7e2SAndroid Build Coastguard Worker python_bin_path = python_bin 162*cc02d7e2SAndroid Build Coastguard Worker if python_bin_path != None: 163*cc02d7e2SAndroid Build Coastguard Worker return str(python_bin_path) 164*cc02d7e2SAndroid Build Coastguard Worker if not allow_absent: 165*cc02d7e2SAndroid Build Coastguard Worker _fail("Cannot find python in PATH, please make sure " + 166*cc02d7e2SAndroid Build Coastguard Worker "python is installed and add its directory in PATH, or --define " + 167*cc02d7e2SAndroid Build Coastguard Worker "%s='/something/else'.\nPATH=%s" % 168*cc02d7e2SAndroid Build Coastguard Worker (bin_path_key, repository_ctx.os.environ.get("PATH", ""))) 169*cc02d7e2SAndroid Build Coastguard Worker else: 170*cc02d7e2SAndroid Build Coastguard Worker return None 171*cc02d7e2SAndroid Build Coastguard Worker 172*cc02d7e2SAndroid Build Coastguard Workerdef _get_bash_bin(repository_ctx): 173*cc02d7e2SAndroid Build Coastguard Worker """Gets the bash bin path.""" 174*cc02d7e2SAndroid Build Coastguard Worker bash_bin = repository_ctx.os.environ.get(_BAZEL_SH) 175*cc02d7e2SAndroid Build Coastguard Worker if bash_bin != None: 176*cc02d7e2SAndroid Build Coastguard Worker return bash_bin 177*cc02d7e2SAndroid Build Coastguard Worker else: 178*cc02d7e2SAndroid Build Coastguard Worker bash_bin_path = repository_ctx.which("bash") 179*cc02d7e2SAndroid Build Coastguard Worker if bash_bin_path != None: 180*cc02d7e2SAndroid Build Coastguard Worker return str(bash_bin_path) 181*cc02d7e2SAndroid Build Coastguard Worker else: 182*cc02d7e2SAndroid Build Coastguard Worker _fail( 183*cc02d7e2SAndroid Build Coastguard Worker "Cannot find bash in PATH, please make sure " + 184*cc02d7e2SAndroid Build Coastguard Worker "bash is installed and add its directory in PATH, or --define " + 185*cc02d7e2SAndroid Build Coastguard Worker "%s='/path/to/bash'.\nPATH=%s" % 186*cc02d7e2SAndroid Build Coastguard Worker (_BAZEL_SH, repository_ctx.os.environ.get("PATH", "")), 187*cc02d7e2SAndroid Build Coastguard Worker ) 188*cc02d7e2SAndroid Build Coastguard Worker 189*cc02d7e2SAndroid Build Coastguard Workerdef _get_python_lib(repository_ctx, python_bin, lib_path_key): 190*cc02d7e2SAndroid Build Coastguard Worker """Gets the python lib path.""" 191*cc02d7e2SAndroid Build Coastguard Worker python_lib = repository_ctx.os.environ.get(lib_path_key) 192*cc02d7e2SAndroid Build Coastguard Worker if python_lib != None: 193*cc02d7e2SAndroid Build Coastguard Worker return python_lib 194*cc02d7e2SAndroid Build Coastguard Worker print_lib = ( 195*cc02d7e2SAndroid Build Coastguard Worker "<<END\n" + "from __future__ import print_function\n" + 196*cc02d7e2SAndroid Build Coastguard Worker "import site\n" + "import os\n" + "\n" + "try:\n" + 197*cc02d7e2SAndroid Build Coastguard Worker " input = raw_input\n" + "except NameError:\n" + " pass\n" + "\n" + 198*cc02d7e2SAndroid Build Coastguard Worker "python_paths = []\n" + "if os.getenv('PYTHONPATH') is not None:\n" + 199*cc02d7e2SAndroid Build Coastguard Worker " python_paths = os.getenv('PYTHONPATH').split(':')\n" + "try:\n" + 200*cc02d7e2SAndroid Build Coastguard Worker " library_paths = site.getsitepackages()\n" + 201*cc02d7e2SAndroid Build Coastguard Worker "except AttributeError:\n" + 202*cc02d7e2SAndroid Build Coastguard Worker " import sysconfig\n" + 203*cc02d7e2SAndroid Build Coastguard Worker " library_paths = [sysconfig.get_path('purelib')]\n" + 204*cc02d7e2SAndroid Build Coastguard Worker "all_paths = set(python_paths + library_paths)\n" + "paths = []\n" + 205*cc02d7e2SAndroid Build Coastguard Worker "for path in all_paths:\n" + " if os.path.isdir(path):\n" + 206*cc02d7e2SAndroid Build Coastguard Worker " paths.append(path)\n" + "if len(paths) >=1:\n" + 207*cc02d7e2SAndroid Build Coastguard Worker " print(paths[0])\n" + "END" 208*cc02d7e2SAndroid Build Coastguard Worker ) 209*cc02d7e2SAndroid Build Coastguard Worker cmd = '"%s" - %s' % (python_bin, print_lib) 210*cc02d7e2SAndroid Build Coastguard Worker result = repository_ctx.execute([_get_bash_bin(repository_ctx), "-c", cmd]) 211*cc02d7e2SAndroid Build Coastguard Worker return result.stdout.strip("\n") 212*cc02d7e2SAndroid Build Coastguard Worker 213*cc02d7e2SAndroid Build Coastguard Workerdef _check_python_lib(repository_ctx, python_lib): 214*cc02d7e2SAndroid Build Coastguard Worker """Checks the python lib path.""" 215*cc02d7e2SAndroid Build Coastguard Worker cmd = 'test -d "%s" -a -x "%s"' % (python_lib, python_lib) 216*cc02d7e2SAndroid Build Coastguard Worker result = repository_ctx.execute([_get_bash_bin(repository_ctx), "-c", cmd]) 217*cc02d7e2SAndroid Build Coastguard Worker if result.return_code == 1: 218*cc02d7e2SAndroid Build Coastguard Worker _fail("Invalid python library path: %s" % python_lib) 219*cc02d7e2SAndroid Build Coastguard Worker 220*cc02d7e2SAndroid Build Coastguard Workerdef _check_python_bin(repository_ctx, python_bin, bin_path_key, allow_absent): 221*cc02d7e2SAndroid Build Coastguard Worker """Checks the python bin path.""" 222*cc02d7e2SAndroid Build Coastguard Worker cmd = '[[ -x "%s" ]] && [[ ! -d "%s" ]]' % (python_bin, python_bin) 223*cc02d7e2SAndroid Build Coastguard Worker result = repository_ctx.execute([_get_bash_bin(repository_ctx), "-c", cmd]) 224*cc02d7e2SAndroid Build Coastguard Worker if result.return_code == 1: 225*cc02d7e2SAndroid Build Coastguard Worker if not allow_absent: 226*cc02d7e2SAndroid Build Coastguard Worker _fail("--define %s='%s' is not executable. Is it the python binary?" % 227*cc02d7e2SAndroid Build Coastguard Worker (bin_path_key, python_bin)) 228*cc02d7e2SAndroid Build Coastguard Worker else: 229*cc02d7e2SAndroid Build Coastguard Worker return None 230*cc02d7e2SAndroid Build Coastguard Worker return True 231*cc02d7e2SAndroid Build Coastguard Worker 232*cc02d7e2SAndroid Build Coastguard Workerdef _get_python_include(repository_ctx, python_bin): 233*cc02d7e2SAndroid Build Coastguard Worker """Gets the python include path.""" 234*cc02d7e2SAndroid Build Coastguard Worker result = _execute( 235*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 236*cc02d7e2SAndroid Build Coastguard Worker [ 237*cc02d7e2SAndroid Build Coastguard Worker python_bin, 238*cc02d7e2SAndroid Build Coastguard Worker "-c", 239*cc02d7e2SAndroid Build Coastguard Worker "from __future__ import print_function;" + 240*cc02d7e2SAndroid Build Coastguard Worker "import sysconfig;" + 241*cc02d7e2SAndroid Build Coastguard Worker "print(sysconfig.get_path('include'))", 242*cc02d7e2SAndroid Build Coastguard Worker ], 243*cc02d7e2SAndroid Build Coastguard Worker error_msg = "Problem getting python include path for {}.".format(python_bin), 244*cc02d7e2SAndroid Build Coastguard Worker error_details = ( 245*cc02d7e2SAndroid Build Coastguard Worker "Is the Python binary path set up right? " + "(See ./configure or " + 246*cc02d7e2SAndroid Build Coastguard Worker python_bin + ".) " + _HEADERS_HELP 247*cc02d7e2SAndroid Build Coastguard Worker ), 248*cc02d7e2SAndroid Build Coastguard Worker ) 249*cc02d7e2SAndroid Build Coastguard Worker include_path = result.stdout.splitlines()[0] 250*cc02d7e2SAndroid Build Coastguard Worker _execute( 251*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 252*cc02d7e2SAndroid Build Coastguard Worker [ 253*cc02d7e2SAndroid Build Coastguard Worker python_bin, 254*cc02d7e2SAndroid Build Coastguard Worker "-c", 255*cc02d7e2SAndroid Build Coastguard Worker "import os;" + 256*cc02d7e2SAndroid Build Coastguard Worker "main_header = os.path.join(r'{}', 'Python.h');".format(include_path) + 257*cc02d7e2SAndroid Build Coastguard Worker "assert os.path.exists(main_header), main_header + ' does not exist.'", 258*cc02d7e2SAndroid Build Coastguard Worker ], 259*cc02d7e2SAndroid Build Coastguard Worker error_msg = "Unable to find Python headers for {}".format(python_bin), 260*cc02d7e2SAndroid Build Coastguard Worker error_details = _HEADERS_HELP, 261*cc02d7e2SAndroid Build Coastguard Worker empty_stdout_fine = True, 262*cc02d7e2SAndroid Build Coastguard Worker ) 263*cc02d7e2SAndroid Build Coastguard Worker return include_path 264*cc02d7e2SAndroid Build Coastguard Worker 265*cc02d7e2SAndroid Build Coastguard Workerdef _get_python_import_lib_name(repository_ctx, python_bin, bin_path_key): 266*cc02d7e2SAndroid Build Coastguard Worker """Get Python import library name (pythonXY.lib) on Windows.""" 267*cc02d7e2SAndroid Build Coastguard Worker result = _execute( 268*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 269*cc02d7e2SAndroid Build Coastguard Worker [ 270*cc02d7e2SAndroid Build Coastguard Worker python_bin, 271*cc02d7e2SAndroid Build Coastguard Worker "-c", 272*cc02d7e2SAndroid Build Coastguard Worker "import sys;" + 'print("python" + str(sys.version_info[0]) + ' + 273*cc02d7e2SAndroid Build Coastguard Worker ' str(sys.version_info[1]) + ".lib")', 274*cc02d7e2SAndroid Build Coastguard Worker ], 275*cc02d7e2SAndroid Build Coastguard Worker error_msg = "Problem getting python import library.", 276*cc02d7e2SAndroid Build Coastguard Worker error_details = ("Is the Python binary path set up right? " + 277*cc02d7e2SAndroid Build Coastguard Worker "(See ./configure or " + bin_path_key + ".) "), 278*cc02d7e2SAndroid Build Coastguard Worker ) 279*cc02d7e2SAndroid Build Coastguard Worker return result.stdout.splitlines()[0] 280*cc02d7e2SAndroid Build Coastguard Worker 281*cc02d7e2SAndroid Build Coastguard Workerdef _create_single_version_package( 282*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 283*cc02d7e2SAndroid Build Coastguard Worker variety_name, 284*cc02d7e2SAndroid Build Coastguard Worker bin_path_key, 285*cc02d7e2SAndroid Build Coastguard Worker default_bin_path, 286*cc02d7e2SAndroid Build Coastguard Worker lib_path_key, 287*cc02d7e2SAndroid Build Coastguard Worker allow_absent): 288*cc02d7e2SAndroid Build Coastguard Worker """Creates the repository containing files set up to build with Python.""" 289*cc02d7e2SAndroid Build Coastguard Worker empty_include_rule = "filegroup(\n name=\"{}_include\",\n srcs=[],\n)".format(variety_name) 290*cc02d7e2SAndroid Build Coastguard Worker 291*cc02d7e2SAndroid Build Coastguard Worker python_bin = _get_python_bin(repository_ctx, bin_path_key, default_bin_path, allow_absent) 292*cc02d7e2SAndroid Build Coastguard Worker if (python_bin == None or 293*cc02d7e2SAndroid Build Coastguard Worker _check_python_bin(repository_ctx, 294*cc02d7e2SAndroid Build Coastguard Worker python_bin, 295*cc02d7e2SAndroid Build Coastguard Worker bin_path_key, 296*cc02d7e2SAndroid Build Coastguard Worker allow_absent) == None) and allow_absent: 297*cc02d7e2SAndroid Build Coastguard Worker python_include_rule = empty_include_rule 298*cc02d7e2SAndroid Build Coastguard Worker else: 299*cc02d7e2SAndroid Build Coastguard Worker python_lib = _get_python_lib(repository_ctx, python_bin, lib_path_key) 300*cc02d7e2SAndroid Build Coastguard Worker _check_python_lib(repository_ctx, python_lib) 301*cc02d7e2SAndroid Build Coastguard Worker python_include = _get_python_include(repository_ctx, python_bin) 302*cc02d7e2SAndroid Build Coastguard Worker python_include_rule = _symlink_genrule_for_dir( 303*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 304*cc02d7e2SAndroid Build Coastguard Worker python_include, 305*cc02d7e2SAndroid Build Coastguard Worker "{}_include".format(variety_name), 306*cc02d7e2SAndroid Build Coastguard Worker "{}_include".format(variety_name), 307*cc02d7e2SAndroid Build Coastguard Worker ) 308*cc02d7e2SAndroid Build Coastguard Worker python_import_lib_genrule = "" 309*cc02d7e2SAndroid Build Coastguard Worker 310*cc02d7e2SAndroid Build Coastguard Worker # To build Python C/C++ extension on Windows, we need to link to python import library pythonXY.lib 311*cc02d7e2SAndroid Build Coastguard Worker # See https://docs.python.org/3/extending/windows.html 312*cc02d7e2SAndroid Build Coastguard Worker if _is_windows(repository_ctx): 313*cc02d7e2SAndroid Build Coastguard Worker python_include = _normalize_path(python_include) 314*cc02d7e2SAndroid Build Coastguard Worker python_import_lib_name = _get_python_import_lib_name( 315*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 316*cc02d7e2SAndroid Build Coastguard Worker python_bin, 317*cc02d7e2SAndroid Build Coastguard Worker bin_path_key, 318*cc02d7e2SAndroid Build Coastguard Worker ) 319*cc02d7e2SAndroid Build Coastguard Worker python_import_lib_src = python_include.rsplit( 320*cc02d7e2SAndroid Build Coastguard Worker "/", 321*cc02d7e2SAndroid Build Coastguard Worker 1, 322*cc02d7e2SAndroid Build Coastguard Worker )[0] + "/libs/" + python_import_lib_name 323*cc02d7e2SAndroid Build Coastguard Worker python_import_lib_genrule = _symlink_genrule_for_dir( 324*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 325*cc02d7e2SAndroid Build Coastguard Worker None, 326*cc02d7e2SAndroid Build Coastguard Worker "", 327*cc02d7e2SAndroid Build Coastguard Worker "{}_import_lib".format(variety_name), 328*cc02d7e2SAndroid Build Coastguard Worker [python_import_lib_src], 329*cc02d7e2SAndroid Build Coastguard Worker [python_import_lib_name], 330*cc02d7e2SAndroid Build Coastguard Worker ) 331*cc02d7e2SAndroid Build Coastguard Worker _tpl( 332*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 333*cc02d7e2SAndroid Build Coastguard Worker "variety", 334*cc02d7e2SAndroid Build Coastguard Worker { 335*cc02d7e2SAndroid Build Coastguard Worker "%{PYTHON_INCLUDE_GENRULE}": python_include_rule, 336*cc02d7e2SAndroid Build Coastguard Worker "%{PYTHON_IMPORT_LIB_GENRULE}": python_import_lib_genrule, 337*cc02d7e2SAndroid Build Coastguard Worker "%{VARIETY_NAME}": variety_name, 338*cc02d7e2SAndroid Build Coastguard Worker }, 339*cc02d7e2SAndroid Build Coastguard Worker out = "{}/BUILD".format(variety_name), 340*cc02d7e2SAndroid Build Coastguard Worker ) 341*cc02d7e2SAndroid Build Coastguard Worker 342*cc02d7e2SAndroid Build Coastguard Workerdef _python_autoconf_impl(repository_ctx): 343*cc02d7e2SAndroid Build Coastguard Worker """Implementation of the python_autoconf repository rule.""" 344*cc02d7e2SAndroid Build Coastguard Worker _create_single_version_package( 345*cc02d7e2SAndroid Build Coastguard Worker repository_ctx, 346*cc02d7e2SAndroid Build Coastguard Worker "_python3", 347*cc02d7e2SAndroid Build Coastguard Worker _PYTHON3_BIN_PATH, 348*cc02d7e2SAndroid Build Coastguard Worker "python3" if not _is_windows(repository_ctx) else "python.exe", 349*cc02d7e2SAndroid Build Coastguard Worker _PYTHON3_LIB_PATH, 350*cc02d7e2SAndroid Build Coastguard Worker False 351*cc02d7e2SAndroid Build Coastguard Worker ) 352*cc02d7e2SAndroid Build Coastguard Worker _tpl(repository_ctx, "BUILD") 353*cc02d7e2SAndroid Build Coastguard Worker 354*cc02d7e2SAndroid Build Coastguard Workerpython_configure = repository_rule( 355*cc02d7e2SAndroid Build Coastguard Worker implementation = _python_autoconf_impl, 356*cc02d7e2SAndroid Build Coastguard Worker environ = [ 357*cc02d7e2SAndroid Build Coastguard Worker _BAZEL_SH, 358*cc02d7e2SAndroid Build Coastguard Worker _PYTHON3_BIN_PATH, 359*cc02d7e2SAndroid Build Coastguard Worker _PYTHON3_LIB_PATH, 360*cc02d7e2SAndroid Build Coastguard Worker ], 361*cc02d7e2SAndroid Build Coastguard Worker attrs = { 362*cc02d7e2SAndroid Build Coastguard Worker "_build_tpl": attr.label( 363*cc02d7e2SAndroid Build Coastguard Worker default = Label("//third_party/py:BUILD.tpl"), 364*cc02d7e2SAndroid Build Coastguard Worker allow_single_file = True, 365*cc02d7e2SAndroid Build Coastguard Worker ), 366*cc02d7e2SAndroid Build Coastguard Worker "_variety_tpl": attr.label( 367*cc02d7e2SAndroid Build Coastguard Worker default = Label("//third_party/py:variety.tpl"), 368*cc02d7e2SAndroid Build Coastguard Worker allow_single_file = True, 369*cc02d7e2SAndroid Build Coastguard Worker ), 370*cc02d7e2SAndroid Build Coastguard Worker }, 371*cc02d7e2SAndroid Build Coastguard Worker) 372*cc02d7e2SAndroid Build Coastguard Worker"""Detects and configures the local Python. 373*cc02d7e2SAndroid Build Coastguard Worker 374*cc02d7e2SAndroid Build Coastguard WorkerIt expects the system have a working Python 3 installation. 375*cc02d7e2SAndroid Build Coastguard Worker 376*cc02d7e2SAndroid Build Coastguard WorkerAdd the following to your WORKSPACE FILE: 377*cc02d7e2SAndroid Build Coastguard Worker 378*cc02d7e2SAndroid Build Coastguard Worker```python 379*cc02d7e2SAndroid Build Coastguard Workerpython_configure(name = "local_config_python") 380*cc02d7e2SAndroid Build Coastguard Worker``` 381*cc02d7e2SAndroid Build Coastguard Worker 382*cc02d7e2SAndroid Build Coastguard WorkerArgs: 383*cc02d7e2SAndroid Build Coastguard Worker name: A unique name for this workspace rule. 384*cc02d7e2SAndroid Build Coastguard Worker""" 385