# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import os
import platform
import re
import shutil
from spack.package import *
class _7zip(SourceforgePackage, Package):
"""7-Zip is a file archiver for Windows"""
homepage = "https://sourceforge.net/projects/sevenzip"
sourceforge_mirror_path = "sevenzip/files/7z2107-src.tar.xz"
tags = ["windows"]
executables = ["7z"]
license("LGPL-2.0-only")
version("21.07", sha256="213d594407cb8efcba36610b152ca4921eda14163310b43903d13e68313e1e39")
variant(
"link_type",
default="shared",
description="build shared and/or static libraries",
values=("static", "shared"),
multi=True,
)
phases = ["build", "install"]
conflicts("platform=linux")
conflicts("platform=darwin")
conflicts("platform=cray")
# TODO: Patch on WinSDK version 10.0.20348.0 when SDK is introduced to Spack
# This patch solves a known bug in that SDK version on the 7zip side
# right now patch for all versions to prevent build errors
patch("noexcept_typedef.patch", when="platform=windows")
@classmethod
def determine_version(cls, exe):
output = Executable(exe)("--help", output=str, error=str)
match = re.search(r"7-Zip ([0-9][0-9]*.[0-9][0-9])", output)
return match.group(1) if match else None
def url_version(self, version):
ver_str = str(version).replace(".", "")
return "7z" + ver_str
@property
def _7z_src_dir(self):
return os.path.join(self.stage.source_path, "CPP", "7zip")
@property
def plat_arch(self):
"""
String referencing platform architecture
filtered through 7zip's Windows build file
"""
arch = platform.machine()
if arch.lower() == "amd64":
arch = "x64"
elif arch.lower() == "i386":
arch = "x86"
return arch
def is_64bit(self):
return "64" in str(self.pkg.spec.target.family)
def build(self, spec, prefix):
link_type = "1" if "static" in spec.variants["link_type"].value else "0"
nmake_args = [
f"PLATFORM={self.plat_arch}",
f"MY_STATIC_LINK={link_type}",
"NEW_COMPILER=1",
]
# 7zips makefile is configured in such as way that if this value is set
# compiler paths with spaces are incorrectly parsed. Compiler will be infered
# from VCVARs on Windows
os.environ.pop("CC", None)
with working_dir(self._7z_src_dir):
nmake(*nmake_args)
def install(self, spec, prefix):
"""7Zip exports no install target so we must hand install"""
arch_prefix = "x64" if self.is_64bit() else "x86"
path_roots = ["Bundles", "UI"]
exts = ["*.exe", "*.dll"]
with working_dir(self._7z_src_dir):
for root in path_roots:
pth = os.path.join(root, "*", arch_prefix)
for ext in exts:
glob_str = os.path.join(pth, ext)
files = glob.glob(glob_str)
[
shutil.copy(
os.path.join(self._7z_src_dir, x),
os.path.join(prefix, os.path.basename(x)),
)
for x in files
]