1# Copyright 2020 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Verifies that a list of libraries is installed on the system. 16 17Takes a list of arguments with every two subsequent arguments being a logical 18tuple of (path, check_soname). The path to the library and either True or False 19to indicate whether to check the soname field on the shared library. 20 21Example Usage: 22./check_cuda_libs.py /path/to/lib1.so True /path/to/lib2.so False 23""" 24import os 25import os.path 26import platform 27import subprocess 28import sys 29 30# pylint: disable=g-import-not-at-top,g-importing-member 31try: 32 from shutil import which 33except ImportError: 34 from distutils.spawn import find_executable as which 35# pylint: enable=g-import-not-at-top,g-importing-member 36 37 38class ConfigError(Exception): 39 pass 40 41 42def _is_windows(): 43 return platform.system() == "Windows" 44 45 46def check_cuda_lib(path, check_soname=True): 47 """Tests if a library exists on disk and whether its soname matches the filename. 48 49 Args: 50 path: the path to the library. 51 check_soname: whether to check the soname as well. 52 53 Raises: 54 ConfigError: If the library does not exist or if its soname does not match 55 the filename. 56 """ 57 if not os.path.isfile(path): 58 raise ConfigError("No library found under: " + path) 59 objdump = which("objdump") 60 if check_soname and objdump is not None and not _is_windows(): 61 # Decode is necessary as in py3 the return type changed from str to bytes 62 output = subprocess.check_output([objdump, "-p", path]).decode("utf-8") 63 output = [line for line in output.splitlines() if "SONAME" in line] 64 sonames = [line.strip().split(" ")[-1] for line in output] 65 if not any(soname == os.path.basename(path) for soname in sonames): 66 raise ConfigError("None of the libraries match their SONAME: " + path) 67 68 69def main(): 70 try: 71 args = [argv for argv in sys.argv[1:]] 72 if len(args) % 2 == 1: 73 raise ConfigError("Expected even number of arguments") 74 checked_paths = [] 75 for i in range(0, len(args), 2): 76 path = args[i] 77 check_cuda_lib(path, check_soname=args[i + 1] == "True") 78 checked_paths.append(path) 79 # pylint: disable=superfluous-parens 80 print(os.linesep.join(checked_paths)) 81 # pylint: enable=superfluous-parens 82 except ConfigError as e: 83 sys.stderr.write(str(e)) 84 sys.exit(1) 85 86 87if __name__ == "__main__": 88 main() 89