XZ package: enable building on Windows (#35095)

* Convert XZ to multi build system
* Add MSBuild builder to XZ to support Windows compatibility
This commit is contained in:
John W. Parent 2023-02-15 12:17:32 -05:00 committed by GitHub
parent dd434ec413
commit 417d8ef547
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,12 +3,16 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import os
import re import re
from spack.build_systems.autotools import AutotoolsBuilder
from spack.build_systems.msbuild import MSBuildBuilder
from spack.package import * from spack.package import *
class Xz(AutotoolsPackage, SourceforgePackage): class Xz(MSBuildPackage, AutotoolsPackage, SourceforgePackage):
"""XZ Utils is free general-purpose data compression software with """XZ Utils is free general-purpose data compression software with
high compression ratio. XZ Utils were written for POSIX-like systems, high compression ratio. XZ Utils were written for POSIX-like systems,
but also work on some not-so-POSIX systems. XZ Utils are the successor but also work on some not-so-POSIX systems. XZ Utils are the successor
@ -44,9 +48,11 @@ class Xz(AutotoolsPackage, SourceforgePackage):
# xz-5.2.7/src/liblzma/common/common.h:56 uses attribute __symver__ instead of # xz-5.2.7/src/liblzma/common/common.h:56 uses attribute __symver__ instead of
# __asm__(.symver) for newer GCC releases. # __asm__(.symver) for newer GCC releases.
conflicts("%intel", when="@5.2.7", msg="icc does not support attribute __symver__") conflicts("%intel", when="@5.2.7", msg="icc does not support attribute __symver__")
conflicts("platform=windows", when="+pic") # no pic on Windows
# prior to 5.2.3, build system is for MinGW only, not currently supported by Spack
conflicts("platform=windows", when="@:5.2.3")
def configure_args(self): build_system(conditional("msbuild", when="platform=windows"), "autotools", default="autotools")
return self.enable_or_disable("libs")
def flag_handler(self, name, flags): def flag_handler(self, name, flags):
if name == "cflags" and "+pic" in self.spec: if name == "cflags" and "+pic" in self.spec:
@ -63,7 +69,60 @@ def determine_version(cls, exe):
match = re.search(r"xz \(XZ Utils\) (\S+)", output) match = re.search(r"xz \(XZ Utils\) (\S+)", output)
return match.group(1) if match else None return match.group(1) if match else None
class AutotoolsBuilder(AutotoolsBuilder):
def configure_args(self):
return self.enable_or_disable("libs")
@run_after("install") @run_after("install")
def darwin_fix(self): def darwin_fix(self):
if self.spec.satisfies("platform=darwin"): if self.spec.satisfies("platform=darwin"):
fix_darwin_install_name(self.prefix.lib) fix_darwin_install_name(self.prefix.lib)
class MSBuildBuilder(MSBuildBuilder):
@property
def build_directory(self):
def get_file_string_number(f):
s = re.findall(r"\d+$", f)
return (int(s[0]) if s else -1, f)
win_dir = os.path.join(super().build_directory, "windows")
compiler_dirs = []
with working_dir(win_dir):
for obj in os.scandir():
if obj.is_dir():
compiler_dirs.append(obj.name)
newest_compiler = max(compiler_dirs, key=get_file_string_number)
return os.path.join(win_dir, newest_compiler)
def is_64bit(self):
return "64" in self.pkg.spec.target.family
def msbuild_args(self):
plat = "x64" if self.is_64bit() else "x86"
if self.pkg.spec.satisfies("libs=shared,static"):
f = "xz_win.sln"
elif self.pkg.spec.satisfies("libs=shared"):
f = "liblzma_dll.vcxproj"
else:
f = "liblzma.vcxproj"
return [self.define("Configuration", "Release"), self.define("Platform", plat), f]
def install(self, pkg, spec, prefix):
with working_dir(self.build_directory):
# Ensure we have libs directory
mkdirp(prefix.lib)
libs_to_find = []
if "libs=shared" in self.pkg.spec:
libs_to_find.extend(["*.dll", "*.lib"])
else:
libs_to_find.append("*.lib")
for lib in libs_to_find:
libs_to_install = glob.glob(
os.path.join(self.build_directory, "**", lib), recursive=True
)
for library in libs_to_install:
install(library, prefix.lib)
with working_dir(pkg.stage.source_path):
install_tree(os.path.join("src", "liblzma", "api"), prefix.include)