summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/tcl/package.py
blob: 7e2d57c764df011214e7098205d0023b4594ee04 (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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Copyright 2013-2018 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 os

from spack.util.environment import is_system_path
from spack import *


class Tcl(AutotoolsPackage):
    """Tcl (Tool Command Language) is a very powerful but easy to
       learn dynamic programming language, suitable for a very wide
       range of uses, including web and desktop applications,
       networking, administration, testing and many more. Open source
       and business-friendly, Tcl is a mature yet evolving language
       that is truly cross platform, easily deployed and highly
       extensible."""
    homepage = "http://www.tcl.tk"
    url      = "http://prdownloads.sourceforge.net/tcl/tcl8.6.5-src.tar.gz"

    version('8.6.8', '81656d3367af032e0ae6157eff134f89')
    version('8.6.6', '5193aea8107839a79df8ac709552ecb7')
    version('8.6.5', '0e6426a4ca9401825fbc6ecf3d89a326')
    version('8.6.4', 'd7cbb91f1ded1919370a30edd1534304')
    version('8.6.3', 'db382feca91754b7f93da16dc4cdad1f')
    version('8.5.19', '0e6426a4ca9401825fbc6ecf3d89a326')

    extendable = True

    depends_on('zlib')

    configure_directory = 'unix'

    def setup_environment(self, spack_env, run_env):
        # When using Tkinter from within spack provided python+tk, python
        # will not be able to find Tcl/Tk unless TCL_LIBRARY is set.
        run_env.set('TCL_LIBRARY', join_path(self.prefix, self.tcl_lib_dir))

    def install(self, spec, prefix):
        with working_dir(self.build_directory):
            make('install')

            # http://wiki.tcl.tk/17463
            if self.spec.satisfies('@8.6:'):
                make('install-headers')

            # Some applications like Expect require private Tcl headers.
            make('install-private-headers')

            # Copy source to install tree
            # A user-provided install option might re-do this
            # https://github.com/spack/spack/pull/4102/files
            installed_src = join_path(
                self.spec.prefix, 'share', self.name, 'src')
            stage_src = os.path.realpath(self.stage.source_path)
            install_tree(stage_src, installed_src)

            # Replace stage dir -> installed src dir in tclConfig
            filter_file(
                stage_src, installed_src,
                join_path(self.spec.prefix, 'lib', 'tclConfig.sh'))

        # Don't install binaries in src/ tree
        with working_dir(join_path(installed_src, self.configure_directory)):
            make('clean')

    @run_after('install')
    def symlink_tclsh(self):
        with working_dir(self.prefix.bin):
            symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh')

    # ========================================================================
    # Set up environment to make install easy for tcl extensions.
    # ========================================================================

    @property
    def libs(self):
        return LibraryList([])

    @property
    def command(self):
        """Returns the tclsh command.

        :returns: The tclsh command
        :rtype: Executable
        """
        return Executable(os.path.realpath(self.prefix.bin.tclsh))

    @property
    def tcl_lib_dir(self):
        """The Tcl version-specific library directory where all extensions are
        installed."""
        return 'lib'

    @property
    def tcl_builtin_lib_dir(self):
        """The Tcl version-specific library directory where all builtin
        extensions are installed."""
        return join_path(self.tcl_lib_dir,
                         'tcl{0}'.format(self.version.up_to(2)))

    def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
        """Set TCLLIBPATH to include the tcl-shipped directory for
        extensions and any other tcl extension it depends on.
        For further info see: https://wiki.tcl.tk/1787"""

        # If we set TCLLIBPATH, we must also ensure that the corresponding
        # tcl is found in the build environment. This to prevent cases
        # where a system provided tcl is run against the standard libraries
        # of a Spack built tcl. See issue #7128 that relates to python but
        # it boils down to the same situation we have here.
        path = os.path.dirname(self.command.path)
        if not is_system_path(path):
            spack_env.prepend_path('PATH', path)

        tcl_paths = [join_path(self.prefix, self.tcl_builtin_lib_dir)]

        for d in dependent_spec.traverse(deptype=('build', 'run', 'test')):
            if d.package.extends(self.spec):
                tcl_paths.append(join_path(d.prefix, self.tcl_lib_dir))

        # WARNING: paths in $TCLLIBPATH must be *space* separated,
        # its value is meant to be a Tcl list, *not* an env list
        # as explained here: https://wiki.tcl.tk/1787:
        # "TCLLIBPATH is a Tcl list, not some platform-specific
        # colon-separated or semi-colon separated format"
        tcllibpath = ' '.join(tcl_paths)
        spack_env.set('TCLLIBPATH', tcllibpath)

        # For run time environment set only the path for
        # dependent_spec and prepend it to TCLLIBPATH
        if dependent_spec.package.extends(self.spec):
            dependent_tcllibpath = join_path(dependent_spec.prefix,
                                             self.tcl_lib_dir)
            run_env.prepend_path('TCLLIBPATH', dependent_tcllibpath,
                                 separator=' ')