Compare commits

..

9 Commits

Author SHA1 Message Date
Robert Dower b5d8cf5341 archive repository 2025-08-07 13:27:48 -07:00
Brett T. Warden cd8d0065aa Detect Intel Simplified Software License 2025-06-04 15:15:13 -07:00
William Douglas 6aaa12ff76 Add qmake5 build pattern
Add support for qmake5 build pattern that uses the qmake binary in
/usr/lib64/qt5.

Signed-off-by: William Douglas <william.douglas@intel.com>
2025-05-30 13:31:57 -07:00
William Douglas 65cf152900 Add the Provide: pypi in most cases
Usually the pypi ecosystem will do the right thing and respond with a
name but in cases where it does not (bad network, bad json, message
without a name), still figure out a reasonable Provide to add.

Signed-off-by: William Douglas <william.douglas@intel.com>
2025-05-27 13:27:28 -07:00
William Douglas 99a7985f29 Add has_license config
In cases where a package's license subpackage disappears, prefer
failing the build as it should have some manual investigation.

Signed-off-by: William Douglas <william.douglas@intel.com>
2025-05-09 10:33:35 -07:00
William Douglas 9594167cc7 Add fixes for flake8 warnings
Signed-off-by: William Douglas <william.douglas@intel.com>
2025-04-18 15:51:15 -07:00
William Douglas c62c42a21d Reject /usr and /usr/ as possible rpm files
These should not be handled paths for autospec. This is a bit of a
hack to work around the rpm build logs being incomplete however and
might be worth reverting if the log issue is fixed.

Signed-off-by: William Douglas <william.douglas@intel.com>
2025-04-18 15:51:15 -07:00
William Douglas a88ffdc2a7 Update APX flags
Signed-off-by: William Douglas <william.douglas@intel.com>
2025-04-04 14:28:44 -07:00
William Douglas 936534a889 abireport: run nm output through c++filt
Signed-off-by: William Douglas <william.douglas@intel.com>
2025-04-02 14:36:34 -07:00
13 changed files with 189 additions and 32 deletions
+7
View File
@@ -0,0 +1,7 @@
## DISCONTINUATION OF PROJECT.
This project will no longer be maintained by Intel.
Intel will not provide or guarantee development of or support for this project, including but not limited to, maintenance, bug fixes, new releases or updates. Patches to this project are no longer accepted by Intel. If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the community, please create your own fork of the project.
Contact: webadmin@linux.intel.com
+1 -1
View File
@@ -155,7 +155,7 @@ def is_file_valid(path):
def dump_symbols(path):
"""Get symbols from a file."""
cmd = "nm --defined-only -g --dynamic \"{}\"".format(path)
cmd = "nm --defined-only -g --dynamic \"{}\" | c++filt".format(path)
lines = None
ret = set()
+7
View File
@@ -277,6 +277,9 @@ def package(args, url, name, archives, workingdir):
# specfile template is assumed "correct" and any failures need to be manually addressed
break
filemanager.load_specfile(specfile)
if 'license' in specfile.packages and not conf.config_opts['has_license']:
conf.config_opts['has_license'] = True
conf.rewrite_config_opts()
specfile.write_spec()
filemanager.newfiles_printed = 0
mock_chroot = "/var/lib/mock/clear-{}/root/builddir/build/BUILDROOT/" \
@@ -297,6 +300,10 @@ def package(args, url, name, archives, workingdir):
conf.create_buildreq_cache(content.version, requirements.buildreqs_cache)
print_build_failed()
sys.exit(1)
elif 'license' not in specfile.packages and conf.config_opts['has_license']:
print_fatal("package -license subpackage deleted")
conf.create_buildreq_cache(content.version, requirements.buildreqs_cache)
sys.exit(1)
elif os.path.isfile("README.clear"):
try:
print("\nREADME.clear CONTENTS")
+2
View File
@@ -215,6 +215,8 @@ class Build(object):
elif infiles == 1 and "not matching the package arch" not in line:
# exclude blank lines from consideration...
file = line.strip()
if file in ("/usr", "/usr/"):
self.must_restart += 1
if file and file[0] == "/":
filemanager.push_file(file, content.name)
+9 -4
View File
@@ -709,6 +709,7 @@ class Requirements(object):
"""Use pypi for getting package requires and metadata."""
# First look for a local override
pypi_json = ""
pypi_name = pypidata.get_pypi_name(name)
pypi_file = os.path.join(config.download_path, "pypi.json")
if os.path.isfile(pypi_file):
with open(pypi_file, "r") as pfile:
@@ -716,16 +717,20 @@ class Requirements(object):
else:
# Try and grab the pypi details for the package
if config.alias:
name = config.alias
pypi_name = pypidata.get_pypi_name(name)
pypi_name = config.alias
pypi_name = pypidata.get_pypi_name(pypi_name)
pypi_json = pypidata.get_pypi_metadata(pypi_name)
if pypi_json:
if not pypi_json:
self.pypi_provides = pypi_name
else:
try:
package_pypi = json.loads(pypi_json)
except json.JSONDecodeError:
package_pypi = {}
package_pypi = {"name": pypi_name}
if package_pypi.get("name"):
self.pypi_provides = package_pypi["name"]
else:
self.pypi_provides = pypi_name
if package_pypi.get("requires"):
for pkg in package_pypi["requires"]:
self.add_requires(f"pypi({pkg})", config.os_packages, override=True, subpkg="python3")
+1
View File
@@ -193,6 +193,7 @@ class Config(object):
"no_glob": "Do not use the replacement pattern for file matching",
"allow_exe": "Allow Windows executables (*.exe, *.dll) to be packaged",
"use_ninja": "Use ninja build files",
"has_license": "Require license subpackage for successful build",
}
# simple_pattern_pkgconfig patterns
# contains patterns for parsing build.log for missing dependencies
-7
View File
@@ -71,14 +71,8 @@ def sanitize_counts():
"""Validate test counts are within sane bounds."""
global total_tests
global total_pass
global total_fail
global total_xfail
global total_skip
global counted_tests
global counted_pass
global counted_fail
global counted_xfail
global counted_skip
if total_tests > 0 and total_pass == 0:
total_pass = total_tests - total_fail - total_skip - total_xfail
@@ -170,7 +164,6 @@ def parse_log(log, pkgname=''):
global total_fail
global total_xfail
global total_skip
global counted_tests
global counted_pass
global counted_fail
global counted_xfail
+1 -6
View File
@@ -55,8 +55,6 @@ def add_license(lic, translations, blacklist):
presence in the blacklist. Returns False if no license were added, True
otherwise.
"""
global licenses
global license_files
lic = lic.strip().strip(',')
result = False
@@ -177,7 +175,7 @@ def scan_for_licenses(srcdir, config, pkg_name):
"about_bsd.txt"]
# look for files that start with copying or licen[cs]e (but are
# not likely scripts) or end with licen[cs]e
target_pat = re.compile(r"^((copying)|(licen[cs]e)|(e[dp]l-v\d+))|(licen[cs]e)(\.(txt|xml))?$")
target_pat = re.compile(r"^((copying)|(licen[cs]e)|(e[dp]l-v\d+))|(licen[cs]e)(\.(txt|xml))?|(intel simplified software license.*\.txt)$")
for dirpath, dirnames, files in os.walk(srcdir):
for name in files:
if name.lower() in targets or target_pat.search(name.lower()):
@@ -208,9 +206,6 @@ def scan_for_licenses(srcdir, config, pkg_name):
def load_specfile(specfile):
"""Get licenses from the specfile content."""
global licenses
global license_files
global hashes
specfile.licenses = licenses if licenses else [default_license]
specfile.license_files = sorted(license_files)
specfile.hashes = hashes
+3 -4
View File
@@ -96,7 +96,7 @@ class GPGCli(object):
util.write_out(os.path.join(_gpghome, 'gpg.conf'), GNUPGCONF)
if pubkey is not None:
args = self.args + ['--import', pubkey]
output, err, code = self.exec_cmd(args)
_, err, code = self.exec_cmd(args)
if code == -9:
raise Exception('Command {} timeout after {} seconds'.format(' '.join(args), CMD_TIMEOUT))
elif code != 0:
@@ -212,16 +212,15 @@ class Verifier(object):
@staticmethod
def calc_sum(filepath, digest_algo):
"""Use digest_algo to calculate block sum of a file."""
BLOCK_SIZE = 4096
block_size = 4096
with open(filepath, 'rb') as fp:
digest = digest_algo()
for block in iter(lambda: fp.read(BLOCK_SIZE), b''):
for block in iter(lambda: fp.read(block_size), b''):
digest.update(block)
return digest.hexdigest()
def print_result(self, result, err_msg=''):
"""Display verification results."""
global EMAIL
package_name = ''
if self.url is not None:
package_name = os.path.basename(self.url)
+12 -5
View File
@@ -27,6 +27,15 @@ def pkg_search(name):
return False
def fixup_pypi_prefix(name):
"""Try and chop off the 'pypi-' or 'python-' prefix for names."""
name = name.lower().replace('-', '_')
for prefix in ["pypi_", "python_"]:
if name.startswith(prefix):
name = name[len(prefix):]
return name
def get_pypi_name(name, miss=False):
"""Try and verify the pypi name for a given package name."""
# normalize the name for matching as pypi is case insensitve for search
@@ -35,11 +44,9 @@ def get_pypi_name(name, miss=False):
if pkg_search(name):
return name
# Maybe we have a prefix
for prefix in ["pypi_", "python_"]:
if name.startswith(prefix):
name = name[len(prefix):]
if pkg_search(name):
return name
name = fixup_pypi_prefix(name)
if pkg_search(name):
return name
# Some cases where search fails (Sphinx)
# Just try the name we were given
if miss:
+57 -4
View File
@@ -37,9 +37,9 @@ AVX512_CFLAGS = "-march=x86-64-v4 -mprefer-vector-width=512"
AVX512_FCFLAGS = "-march=x86-64-v4 -mprefer-vector-width=256"
AVX512_LCFLAGS = "-march=x86-64-v4"
AVX512_LFLAGS = "-Wl,-z,x86-64-v4"
APX_CFLAGS = "-march=x86-64-v3 -mapxf -mavx10.1"
APX_LCFLAGS = "-march=x86-64-v3"
APX_LFLAGS = "-Wl,-z,x86-64-v3"
APX_CFLAGS = "-march=x86-64-v4 -mapxf"
APX_LCFLAGS = "-march=x86-64-v4"
APX_LFLAGS = "-Wl,-z,x86-64-v4"
class Specfile(object):
@@ -1166,7 +1166,7 @@ class Specfile(object):
self.write_build_prepend()
self._write_strip("GOAMD64=v3")
self._write_strip(f'CFLAGS="$CLEAR_INTERMEDIATE_CFLAGS {APX_CFLAGS} {APX_LFLAGS} "')
self._write_strip(f'CXXFLAGS="$CLEAR_INTERMEDIATE_CXXFLAGS {AVX2_CFLAGS} {AVX2_LFLAGS} "')
self._write_strip(f'CXXFLAGS="$CLEAR_INTERMEDIATE_CXXFLAGS {APX_CFLAGS} {APX_LFLAGS} "')
self._write_strip(f'FFLAGS="$CLEAR_INTERMEDIATE_FFLAGS {APX_CFLAGS} {APX_LFLAGS} "')
self._write_strip(f'FCFLAGS="$CLEAR_INTERMEDIATE_FCFLAGS {APX_CFLAGS} "')
self._write_strip(f'LDFLAGS="$CLEAR_INTERMEDIATE_LDFLAGS {APX_LCFLAGS} "')
@@ -1806,6 +1806,59 @@ class Specfile(object):
self.write_cmake_install()
def write_qmake5_pattern(self):
"""Write qmake5 build pattern to spec file."""
extra_qmake_args = ""
if self.config.config_opts['use_clang']:
extra_qmake_args = "-spec linux-clang "
if self.config.config_opts['use_lto']:
extra_qmake_args += "-config ltcg -config fat-static-lto "
else:
extra_qmake_args += "QMAKE_CFLAGS+=-fno-lto QMAKE_CXXFLAGS+=-fno-lto "
self.write_prep()
self._write_strip("%build")
self.write_build_prepend()
self.write_proxy_exports()
self._write_strip("export LANG=C.UTF-8")
self.write_variables()
if self.config.subdir:
self._write_strip("pushd " + self.config.subdir)
self._write_strip('export QMAKE_CFLAGS="$CFLAGS"')
self._write_strip('export QMAKE_CXXFLAGS="$CXXFLAGS"')
self._write_strip('export QMAKE_LFLAGS="$LDFLAGS"')
self._write_strip('export QMAKE_LIBDIR=/usr/lib64')
self._write_strip('export QMAKE_CFLAGS_RELEASE=')
self._write_strip('export QMAKE_CXXFLAGS_RELEASE=')
# Add the qtbase tools to the path
self._write_strip('export PATH=/usr/lib64/qt5/bin:$PATH')
if self.config.make_command:
qmake = self.config.make_command
else:
qmake = "qmake"
self._write_strip(f"{qmake} {extra_qmake_args} {self.config.extra_configure}")
self._write_strip("test -r config.log && cat config.log")
self.write_make_line()
if self.config.subdir:
self._write_strip("popd")
if self.config.config_opts['use_avx2']:
self._write_strip("pushd ../buildavx2/" + self.config.subdir)
self._write(f"{qmake} 'QT_CPU_FEATURES.x86_64 += avx avx2 bmi bmi2 f16c fma lzcnt popcnt'\\\n")
self._write(f' QMAKE_CFLAGS+="{AVX2_CFLAGS} {AVX2_LFLAGS}" QMAKE_CXXFLAGS+="{AVX2_CFLAGS} {AVX2_LFLAGS}" \\\n')
self._write(f' QMAKE_LFLAGS+="{AVX2_LCFLAGS}" {extra_qmake_args} {self.config.extra_configure}\n')
self.write_make_line()
self._write_strip("popd")
self.write_build_append()
self._write_strip("\n")
self.write_make_install()
def write_qmake_pattern(self):
"""Write qmake build pattern to spec file."""
extra_qmake_args = ""
-1
View File
@@ -156,7 +156,6 @@ def _file_write(self, s):
def translate(package):
"""Convert terms to their alternate definition."""
global dictionary
for item in dictionary:
if item.startswith(package + "="):
return item.split("=")[1]
+89
View File
@@ -499,6 +499,95 @@ class TestBuildreq(unittest.TestCase):
self.assertEqual(self.reqs.requires['python3'], pypi_requires)
self.assertEqual(ssummary, summary)
def test_scan_for_configure_pypi_no_name_in_json(self):
"""
Test scan_for_configure when distutils is being used for the build
pattern to test connecting to pypi but not getting a name back.
"""
orig_summary = buildreq.specdescription.default_summary
orig_sscore = buildreq.specdescription.default_summary_score
orig_pypi_name = buildreq.pypidata.get_pypi_name
orig_pypi_meta = buildreq.pypidata.get_pypi_metadata
name = "pypi-name"
content = json.dumps({})
buildreq.pypidata.pkg_search = MagicMock(return_value=False)
buildreq.pypidata.get_pypi_metadata = MagicMock(return_value=content)
with tempfile.TemporaryDirectory() as tmpd:
conf = config.Config(tmpd)
conf.config_opts['use_ninja'] = False
os.mkdir(os.path.join(tmpd, 'subdir'))
open(os.path.join(tmpd, 'subdir', 'pyproject.toml'), 'w').close()
self.reqs.scan_for_configure(os.path.join(tmpd, 'subdir'), name, conf)
post_summary = buildreq.specdescription.default_summary
buildreq.specdescription.default_summary = orig_summary
buildreq.specdescription.default_summary_score = orig_sscore
buildreq.pypidata.get_pypi_name = orig_pypi_name
buildreq.pypidata.get_pypi_metadata = orig_pypi_meta
self.assertEqual(self.reqs.pypi_provides, "name")
self.assertEqual(post_summary, orig_summary)
def test_scan_for_configure_pypi_no_json(self):
"""
Test scan_for_configure when distutils is being used for the build
pattern to test being unable to connect to pypi.
"""
orig_summary = buildreq.specdescription.default_summary
orig_sscore = buildreq.specdescription.default_summary_score
orig_pypi_name = buildreq.pypidata.get_pypi_name
orig_pypi_meta = buildreq.pypidata.get_pypi_metadata
name = "pypi-name"
buildreq.pypidata.pkg_search = MagicMock(return_value=False)
buildreq.pypidata.get_pypi_metadata = MagicMock(return_value="")
with tempfile.TemporaryDirectory() as tmpd:
conf = config.Config(tmpd)
conf.config_opts['use_ninja'] = False
os.mkdir(os.path.join(tmpd, 'subdir'))
open(os.path.join(tmpd, 'subdir', 'pyproject.toml'), 'w').close()
self.reqs.scan_for_configure(os.path.join(tmpd, 'subdir'), name, conf)
post_summary = buildreq.specdescription.default_summary
buildreq.specdescription.default_summary = orig_summary
buildreq.specdescription.default_summary_score = orig_sscore
buildreq.pypidata.get_pypi_name = orig_pypi_name
buildreq.pypidata.get_pypi_metadata = orig_pypi_meta
self.assertEqual(self.reqs.pypi_provides, "name")
self.assertEqual(post_summary, orig_summary)
def test_scan_for_configure_pypi_bad_json(self):
"""
Test scan_for_configure when distutils is being used for the build
pattern to test being given bad json data.
"""
orig_summary = buildreq.specdescription.default_summary
orig_sscore = buildreq.specdescription.default_summary_score
orig_pypi_name = buildreq.pypidata.get_pypi_name
orig_pypi_meta = buildreq.pypidata.get_pypi_metadata
orig_json_loads = buildreq.json.loads
name = "pypi-name"
content = json.dumps({})
buildreq.pypidata.pkg_search = MagicMock(return_value=False)
buildreq.pypidata.get_pypi_metadata = MagicMock(return_value=content)
buildreq.json.loads = MagicMock(side_effect=json.JSONDecodeError("", "", 0))
with tempfile.TemporaryDirectory() as tmpd:
conf = config.Config(tmpd)
conf.config_opts['use_ninja'] = False
os.mkdir(os.path.join(tmpd, 'subdir'))
open(os.path.join(tmpd, 'subdir', 'pyproject.toml'), 'w').close()
self.reqs.scan_for_configure(os.path.join(tmpd, 'subdir'), name, conf)
post_summary = buildreq.specdescription.default_summary
buildreq.specdescription.default_summary = orig_summary
buildreq.specdescription.default_summary_score = orig_sscore
buildreq.pypidata.get_pypi_name = orig_pypi_name
buildreq.pypidata.get_pypi_metadata = orig_pypi_meta
buildreq.json.loads = orig_json_loads
self.assertEqual(self.reqs.pypi_provides, "name")
self.assertEqual(post_summary, orig_summary)
def test_scan_for_configure_pypi_override(self):
"""
Test scan_for_configure when distutils is being used for the build