mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 23:26:32 +00:00

* Removes all Perl scripts and modules * Adds Python3 scripts which mimic the behavior of the Perl scripts * Removes Perl from CMake; Adds Python3 requirement to CMake * The check-instruction-set.pl script is Knights Corner specific. The script is removed and not replicated with a corresponding Python3 script. Relevant Discourse: https://discourse.llvm.org/t/error-compiling-clang-with-offloading-support/79223/4 Fixes: https://github.com/llvm/llvm-project/issues/62289
169 lines
5.2 KiB
Python
169 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
|
|
#
|
|
# //===----------------------------------------------------------------------===//
|
|
# //
|
|
# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# // See https://llvm.org/LICENSE.txt for license information.
|
|
# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
# //
|
|
# //===----------------------------------------------------------------------===//
|
|
#
|
|
|
|
import argparse
|
|
import os
|
|
import platform
|
|
import re
|
|
import sys
|
|
from libomputils import (
|
|
ScriptError,
|
|
error,
|
|
execute_command,
|
|
print_info_line,
|
|
print_error_line,
|
|
)
|
|
|
|
|
|
def get_deps_readelf(filename):
|
|
"""Get list of dependencies from readelf"""
|
|
deps = []
|
|
# Force readelf call to be in English
|
|
os.environ["LANG"] = "C"
|
|
r = execute_command(["readelf", "-d", filename])
|
|
if r.returncode != 0:
|
|
error("readelf -d {} failed".format(filename))
|
|
neededRegex = re.compile(r"\(NEEDED\)\s+Shared library: \[([a-zA-Z0-9_.-]+)\]")
|
|
for line in r.stdout.split(os.linesep):
|
|
match = neededRegex.search(line)
|
|
if match:
|
|
deps.append(match.group(1))
|
|
return deps
|
|
|
|
|
|
def get_deps_otool(filename):
|
|
"""Get list of dependencies from otool"""
|
|
deps = []
|
|
r = execute_command(["otool", "-L", filename])
|
|
if r.returncode != 0:
|
|
error("otool -L {} failed".format(filename))
|
|
libRegex = re.compile(r"([^ \t]+)\s+\(compatibility version ")
|
|
thisLibRegex = re.compile(r"@rpath/{}".format(os.path.basename(filename)))
|
|
for line in r.stdout.split(os.linesep):
|
|
match = thisLibRegex.search(line)
|
|
if match:
|
|
# Don't include the library itself as a needed dependency
|
|
continue
|
|
match = libRegex.search(line)
|
|
if match:
|
|
deps.append(match.group(1))
|
|
continue
|
|
return deps
|
|
|
|
|
|
def get_deps_link(filename):
|
|
"""Get list of dependecies from link (Windows OS)"""
|
|
depsSet = set([])
|
|
f = filename.lower()
|
|
args = ["link", "/DUMP"]
|
|
if f.endswith(".lib"):
|
|
args.append("/DIRECTIVES")
|
|
elif f.endswith(".dll") or f.endswith(".exe"):
|
|
args.append("/DEPENDENTS")
|
|
else:
|
|
error("unrecognized file extension: {}".format(filename))
|
|
args.append(filename)
|
|
r = execute_command(args)
|
|
if r.returncode != 0:
|
|
error("{} failed".format(args.command))
|
|
if f.endswith(".lib"):
|
|
regex = re.compile(r"\s*[-/]defaultlib:(.*)\s*$")
|
|
for line in r.stdout.split(os.linesep):
|
|
line = line.lower()
|
|
match = regex.search(line)
|
|
if match:
|
|
depsSet.add(match.group(1))
|
|
else:
|
|
started = False
|
|
markerStart = re.compile(r"Image has the following depend")
|
|
markerEnd = re.compile(r"Summary")
|
|
markerEnd2 = re.compile(r"Image has the following delay load depend")
|
|
for line in r.stdout.split(os.linesep):
|
|
if not started:
|
|
if markerStart.search(line):
|
|
started = True
|
|
continue
|
|
else: # Started parsing the libs
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
if markerEnd.search(line) or markerEnd2.search(line):
|
|
break
|
|
depsSet.add(line.lower())
|
|
return list(depsSet)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Check library dependencies")
|
|
parser.add_argument(
|
|
"--bare",
|
|
action="store_true",
|
|
help="Produce plain, bare output: just a list"
|
|
" of libraries, a library per line",
|
|
)
|
|
parser.add_argument(
|
|
"--expected",
|
|
metavar="CSV_LIST",
|
|
help="CSV_LIST is a comma-separated list of expected"
|
|
' dependencies (or "none"). checks the specified'
|
|
" library has only expected dependencies.",
|
|
)
|
|
|
|
parser.add_argument("library", help="The library file to check")
|
|
commandArgs = parser.parse_args()
|
|
# Get dependencies
|
|
deps = []
|
|
|
|
system = platform.system()
|
|
if system == "Windows":
|
|
deps = get_deps_link(commandArgs.library)
|
|
elif system == "Darwin":
|
|
deps = get_deps_otool(commandArgs.library)
|
|
else:
|
|
deps = get_deps_readelf(commandArgs.library)
|
|
deps = sorted(deps)
|
|
|
|
# If bare output specified, then just print the dependencies one per line
|
|
if commandArgs.bare:
|
|
print(os.linesep.join(deps))
|
|
return
|
|
|
|
# Calculate unexpected dependencies if expected list specified
|
|
unexpected = []
|
|
if commandArgs.expected:
|
|
# none => any dependency is unexpected
|
|
if commandArgs.expected == "none":
|
|
unexpected = list(deps)
|
|
else:
|
|
expected = [d.strip() for d in commandArgs.expected.split(",")]
|
|
unexpected = [d for d in deps if d not in expected]
|
|
|
|
# Regular output
|
|
print_info_line("Dependencies:")
|
|
for dep in deps:
|
|
print_info_line(" {}".format(dep))
|
|
if unexpected:
|
|
print_error_line("Unexpected Dependencies:")
|
|
for dep in unexpected:
|
|
print_error_line(" {}".format(dep))
|
|
error("found unexpected dependencies")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except ScriptError as e:
|
|
print_error_line(str(e))
|
|
sys.exit(1)
|
|
|
|
# end of file
|