Repository: spack/spack

Issue:
gcc/java requires zip
Installing gcc on Ubuntu 16.04 system fails unless the `zip` package is installed. Since Spack provides `zip`, `gcc` should depend on `zip` if it builds Java.



Discussion:
can you add a build dependency?

```
depends_on('zip', when='+java', type='build')
```

There is no `zip` package in Spack. GCC also doesn't have a `+java` variant.

Oops -- I must have mistaken `zlib` or so for `zip`.

With `+java` I meant the GCC configuration options that enables Java as language. It's listed explicitly in the package source, but indeed not as variant.


Resolving patch:
diff --git a/var/spack/repos/builtin/packages/gcc/package.py b/var/spack/repos/builtin/packages/gcc/package.py
--- a/var/spack/repos/builtin/packages/gcc/package.py
+++ b/var/spack/repos/builtin/packages/gcc/package.py
@@ -23,22 +23,24 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
 from spack import *
+from llnl.util import tty
 
-from contextlib import closing
-from glob import glob
+import glob
+import os
+import shutil
 import sys
-from os.path import isfile
 
 
 class Gcc(AutotoolsPackage):
-    """The GNU Compiler Collection includes front ends for C, C++,
-       Objective-C, Fortran, and Java."""
-    homepage = "https://gcc.gnu.org"
+    """The GNU Compiler Collection includes front ends for C, C++, Objective-C,
+    Fortran, Ada, and Go, as well as libraries for these languages."""
 
-    url = "http://ftp.gnu.org/gnu/gcc/gcc-4.9.2/gcc-4.9.2.tar.bz2"
+    homepage = 'https://gcc.gnu.org'
+    url      = 'http://ftp.gnu.org/gnu/gcc/gcc-7.1.0/gcc-7.1.0.tar.bz2'
     list_url = 'http://ftp.gnu.org/gnu/gcc/'
     list_depth = 1
 
+    version('7.1.0', '6bf56a2bca9dac9dbbf8e8d1036964a8')
     version('6.3.0', '677a7623c7ef6ab99881bc4e048debb6')
     version('6.2.0', '9768625159663b300ae4de2f4745fcc4')
     version('6.1.0', '8fb6cb98b8459f5863328380fbf06bd1')
@@ -56,23 +58,35 @@ class Gcc(AutotoolsPackage):
     version('4.6.4', 'b407a3d1480c11667f293bfb1f17d1a4')
     version('4.5.4', '27e459c2566b8209ab064570e1b378f7')
 
+    # Builds all default languages by default.
+    # Ada, Go, Jit, and Objective-C++ are not default languages.
+    # In that respect, the name 'all' is rather misleading.
+    variant('languages',
+            default='all',
+            values=('all', 'ada', 'brig', 'c', 'c++', 'fortran',
+                    'go', 'java', 'jit', 'lto', 'objc', 'obj-c++'),
+            multi=True,
+            description='Compilers and runtime libraries to build')
     variant('binutils',
             default=sys.platform != 'darwin',
-            description="Build via binutils")
+            description='Build via binutils')
     variant('piclibs',
             default=False,
-            description="Build PIC versions of libgfortran.a and libstdc++.a")
-
-    depends_on("mpfr")
-    depends_on("gmp")
-    depends_on("mpc", when='@4.5:')
-    depends_on("isl", when='@5.0:')
-    depends_on("binutils~libiberty", when='+binutils')
-    depends_on("zip", type='build')
+            description='Build PIC versions of libgfortran.a and libstdc++.a')
+
+    # https://gcc.gnu.org/install/prerequisites.html
+    depends_on('gmp@4.3.2:')
+    depends_on('mpfr@2.4.2:')
+    depends_on('mpc@0.8.1:', when='@4.5:')
+    depends_on('isl@0.15:', when='@5.0:')
+    depends_on('zlib', when='@6:')
+    depends_on('gnat', when='languages=ada')
+    depends_on('binutils~libiberty', when='+binutils')
+    depends_on('zip', type='build', when='languages=java')
 
     # TODO: integrate these libraries.
-    # depends_on("ppl")
-    # depends_on("cloog")
+    # depends_on('ppl')
+    # depends_on('cloog')
 
     # TODO: Add a 'test' deptype
     # https://github.com/LLNL/spack/issues/1279
@@ -82,60 +96,115 @@ class Gcc(AutotoolsPackage):
     # depends_on('autogen@5.5.4:', type='test')
     # depends_on('guile@1.4.1:', type='test')
 
+    # See https://golang.org/doc/install/gccgo#Releases
+    provides('golang', when='languages=go')
+    # 'when' does not currently support multiple parts of a spec.
+    # See https://github.com/LLNL/spack/pull/4151
+    # provides('golang',        when='languages=go @4.6:')
+    # provides('golang@:1',     when='languages=go @4.7.1:')
+    # provides('golang@:1.1',   when='languages=go @4.8:')
+    # provides('golang@:1.1.2', when='languages=go @4.8.2:')
+    # provides('golang@:1.2',   when='languages=go @4.9:')
+    # provides('golang@:1.4',   when='languages=go @5:')
+    # provides('golang@:1.6.1', when='languages=go @6:')
+    # provides('golang@:1.8',   when='languages=go @7:')
+
+    # For a list of valid languages for a specific release,
+    # run the following command in the GCC source directory:
+    #    $ grep ^language= gcc/*/config-lang.in
+    # See https://gcc.gnu.org/install/configure.html
+
+    # Support for processing BRIG 1.0 files was added in GCC 7
+    # BRIG is a binary format for HSAIL:
+    # (Heterogeneous System Architecture Intermediate Language).
+    # See https://gcc.gnu.org/gcc-7/changes.html
+    conflicts('languages=brig', when='@:6')
+
+    # BRIG does not seem to be supported on macOS
+    conflicts('languages=brig', when='platform=darwin')
+
+    # GCC 4.8 added a 'c' language. I'm sure C was always built,
+    # but this is the first version that accepts 'c' as a valid language.
+    conflicts('languages=c', when='@:4.7')
+
+    # GCC 4.6 added support for the Go programming language.
+    # See https://gcc.gnu.org/gcc-4.6/changes.html
+    conflicts('languages=go', when='@:4.5')
+
+    # Go is not supported on macOS
+    conflicts('languages=go', when='platform=darwin')
+
+    # The GCC Java frontend and associated libjava runtime library
+    # have been removed from GCC as of GCC 7.
+    # See https://gcc.gnu.org/gcc-7/changes.html
+    conflicts('languages=java', when='@7:')
+
+    # GCC 5 added the ability to build GCC as a Just-In-Time compiler.
+    # See https://gcc.gnu.org/gcc-5/changes.html
+    conflicts('languages=jit', when='@:4')
+
     if sys.platform == 'darwin':
+        patch('darwin/gcc-7.1.0-headerpad.patch', when='@5:')
+        patch('darwin/gcc-6.1.0-jit.patch', when='@5:')
         patch('darwin/gcc-4.9.patch1', when='@4.9.0:4.9.3')
         patch('darwin/gcc-4.9.patch2', when='@4.9.0:4.9.3')
-    else:
-        provides('golang', when='@4.7.1:')
 
     patch('piclibs.patch', when='+piclibs')
     patch('gcc-backport.patch', when='@4.7:4.9.2,5:5.3')
 
-    def configure_args(self):
+    build_directory = 'spack-build'
+
+    def patch(self):
         spec = self.spec
         prefix = self.spec.prefix
 
-        enabled_languages = set(('c', 'c++', 'fortran', 'java', 'objc'))
-
-        if spec.satisfies("@4.7.1:") and sys.platform != 'darwin' and \
-           not (spec.satisfies('@:4.9.3') and 'ppc64le' in spec.architecture):
-            enabled_languages.add('go')
-
         # Fix a standard header file for OS X Yosemite that
         # is GCC incompatible by replacing non-GCC compliant macros
         if 'yosemite' in spec.architecture:
-            if isfile(r'/usr/include/dispatch/object.h'):
+            if os.path.isfile('/usr/include/dispatch/object.h'):
                 new_dispatch_dir = join_path(prefix, 'include', 'dispatch')
                 mkdirp(new_dispatch_dir)
-                cp = which('cp')
                 new_header = join_path(new_dispatch_dir, 'object.h')
-                cp(r'/usr/include/dispatch/object.h', new_header)
+                shutil.copyfile('/usr/include/dispatch/object.h', new_header)
                 filter_file(r'typedef void \(\^dispatch_block_t\)\(void\)',
                             'typedef void* dispatch_block_t',
                             new_header)
 
+    def configure_args(self):
+        spec = self.spec
+
         # Generic options to compile GCC
         options = [
-            '--libdir={0}'.format(prefix.lib64),
             '--disable-multilib',
-            '--enable-languages={0}'.format(','.join(enabled_languages)),
+            '--enable-languages={0}'.format(
+                ','.join(spec.variants['languages'].value)),
             '--with-mpfr={0}'.format(spec['mpfr'].prefix),
             '--with-gmp={0}'.format(spec['gmp'].prefix),
             '--enable-lto',
             '--with-quad'
         ]
 
+        # Use installed libz
+        if self.version >= Version('6'):
+            options.append('--with-system-zlib')
+
+        # Enabling language "jit" requires --enable-host-shared.
+        if 'languages=jit' in spec:
+            options.append('--enable-host-shared')
+
         # Binutils
         if spec.satisfies('+binutils'):
-            static_bootstrap_flags = "-static-libstdc++ -static-libgcc"
+            static_bootstrap_flags = '-static-libstdc++ -static-libgcc'
             binutils_options = [
-                "--with-sysroot=/", "--with-stage1-ldflags=%s %s" %
-                (self.rpath_args, static_bootstrap_flags),
-                "--with-boot-ldflags=%s %s" %
-                (self.rpath_args, static_bootstrap_flags), "--with-gnu-ld",
-                "--with-ld=%s/bin/ld" % spec['binutils'].prefix,
-                "--with-gnu-as",
-                "--with-as=%s/bin/as" % spec['binutils'].prefix
+                '--with-sysroot=/',
+                '--with-stage1-ldflags={0} {1}'.format(
+                    self.rpath_args, static_bootstrap_flags),
+                '--with-boot-ldflags={0} {1}'.format(
+                    self.rpath_args, static_bootstrap_flags),
+                '--with-gnu-ld',
+                '--with-ld={0}/ld'.format(spec['binutils'].prefix.bin),
+                '--with-gnu-as',
+                '--with-as={0}/as'.format(spec['binutils'].prefix.bin),
             ]
             options.extend(binutils_options)
 
@@ -153,8 +222,6 @@ def configure_args(self):
 
         return options
 
-    build_directory = 'spack-build'
-
     @property
     def build_targets(self):
         if sys.platform == 'darwin':
@@ -163,8 +230,8 @@ def build_targets(self):
 
     @property
     def spec_dir(self):
-        # e.g. lib64/gcc/x86_64-unknown-linux-gnu/4.9.2
-        spec_dir = glob("%s/lib64/gcc/*/*" % self.prefix)
+        # e.g. lib/gcc/x86_64-unknown-linux-gnu/4.9.2
+        spec_dir = glob.glob('{0}/gcc/*/*'.format(self.prefix.lib))
         return spec_dir[0] if spec_dir else None
 
     @run_after('install')
@@ -172,17 +239,17 @@ def write_rpath_specs(self):
         """Generate a spec file so the linker adds a rpath to the libs
            the compiler used to build the executable."""
         if not self.spec_dir:
-            tty.warn("Could not install specs for %s." %
-                     self.spec.format('$_$@'))
+            tty.warn('Could not install specs for {0}.'.format(
+                     self.spec.format('$_$@')))
             return
 
         gcc = self.spec['gcc'].command
-        lines = gcc('-dumpspecs', output=str).strip().split("\n")
+        lines = gcc('-dumpspecs', output=str).strip().split('\n')
         specs_file = join_path(self.spec_dir, 'specs')
-        with closing(open(specs_file, 'w')) as out:
+        with open(specs_file, 'w') as out:
             for line in lines:
-                out.write(line + "\n")
-                if line.startswith("*link:"):
-                    out.write("-rpath %s/lib:%s/lib64 \\\n" %
-                              (self.prefix, self.prefix))
+                out.write(line + '\n')
+                if line.startswith('*link:'):
+                    out.write(r'-rpath {0}:{1} \n'.format(
+                              self.prefix.lib, self.prefix.lib64))
         set_install_permissions(specs_file)
diff --git a/var/spack/repos/builtin/packages/gnat/package.py b/var/spack/repos/builtin/packages/gnat/package.py
new file mode 100644
--- /dev/null
+++ b/var/spack/repos/builtin/packages/gnat/package.py
@@ -0,0 +1,51 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
+from spack import *
+
+
+class Gnat(MakefilePackage):
+    """The GNAT Ada compiler. Ada is a modern programming language designed
+    for large, long-lived applications - and embedded systems in particular
+    - where reliability and efficiency are essential."""
+
+    homepage = "https://libre.adacore.com/tools/gnat-gpl-edition/"
+
+    # NOTE: This is a binary installer intended to bootstrap GCC's Ada compiler
+
+    # There may actually be a way to install GNAT from source. If you go to
+    # the GNAT Download page: https://libre.adacore.com/download/
+    # select "Free Software or Academic Development", select your platform,
+    # expand GNAT Ada, and expand Sources, you'll see links to download the
+    # source code for GNAT and all of its dependencies. Most of these
+    # dependencies are already in Spack.
+
+    # This is the GPL release for Linux x86-64
+    version('2016', '9741107cca1a6a4ddb0d5e8de824a90c', extension='tar.gz',
+            url="http://mirrors.cdn.adacore.com/art/5739cefdc7a447658e0b016b")
+
+    phases = ['install']
+
+    def install(self, spec, prefix):
+        make('ins-all', 'prefix={0}'.format(prefix))


Test patch: