summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/7zip/package.py
blob: ccc79470866a45780f372f13e6d8b6e19a9b61d8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# 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
                    ]