On many systems pkgsrc supports, gcc is the standard compiler. In general, different versions of each OS have different gcc versions, and some packages require newer gcc versions, in order to support newer language standards (e.g. c++11, written in the style of USE_LANGUAGES), or because older versions don't work (infrequently).

This page discusses issues related to version selection, and intends to be a design document for how pkgsrc should address this problem, to be converted into historical design rationale once implemented. It freely takes content from extensive mailinglist discussions, and attempts to follow the rough consensus that has emerged.

Base system gcc vs pkgsrc gcc

Systems using gcc (e.g. NetBSD) have a compiler as /usr/bin/gcc, and this is usable by pkgsrc without any bootstrapping activity. One can build gcc versions (typically newer versions) from pkgsrc, resulting in a compiler within ${PREFIX}, e.g. /usr/pkg/gcc6/bin/gcc. This compiler can then be used to compile other packages.

The issue with using base system gcc is typically that it is too old, such as gcc 4.5 with NetBSD 6, which cannot compile c++11. Another example is gcc 4.8 with NetBSD 7. While this can compile most c++11 programs, it cannot be used for firefox or glibmm (and therefore any package that links against glibmm).

Issues when using pkgsrc gcc are that

Specific constraints and requirements

This section attempts to gather all the requirements.

Design

The above requirements could in theory be satisfied in many ways, but most of them are too complicated. We present a design that aims to be sound while mimimizing complexity.

Remaining issues

gcc dependencies introduction

Because gcc can have dependencies, there could be packages built with the system compiler that are then later used with the chosen version. For now, we defer worrying about these problems (judging that they will be less serious than the current situation where all c++11 programs fail to build on NetBSD 6).

\todo: Perhaps change gcc 4.8 and 4.9 to enable gcc-inplace-math by default. Perhaps decide that if we want to build gcc, we want to build 5 or 6, and 4.9 is no longer of interest as a bootstrap target.

\todo: Analyze what build-time and install-time dependencies actually exist. Include old GNU/Linux in this analysis.

\todo: Consider if dropping nls would help. (On NetBSD, it seems that base system libraries are used, so it would not help.)

\todo: Consider failing if optins that we want one way are another, when bootstrapping.

managing gcc dependencies

There are multiple paths forward.

\todo Choose one. Straw proposal is "Don't worry" and recursive variable for the initial implementation.

Separate prefix

Build compilers in a separate prefix, or a subprefix, so that the compiler and the packages needed to build it will not be used by any normal packages. This completely avoids the issue of building a package one way in bootstrap and another not in bootstrap, at the cost of two builds and writing the separate-prefix code.

Don't worry

Don't worry that packages used to bootstrap the needed compiler are compiled with an older compiler. Don't worry that they might be different depending on build order. If we have an actual problem, deal with it. This requires choosing an approach to omit compiler selection logic when building the compiler:

Mark bootstrap packages

Mark packages used to build gcc as PKGSRC_GCC_BOOTSTRAP=yes. Conditionalize this on OPSYS if necessary. Don't force the compiler if this is set.

Alternatively, manage a per-OS list of packages in a central mk file.

Pass a recursive variable

As above, but set PKGSRC_GCC_BOOTSTRAP=yes in the evniroment of the call to build the compiler, so that all dependencies inherit permission to skip compiler selection logic. (Alternatively, use some other mechanism such as passing a make variable explicitly.)

Differing GCC and GXX versions

Perhaps it is a mistake to allow the chosen GCC and GXX versions to differ. If we require them to be the same, then essentially all systems with a base system compiler older than gcc 5 will have to bootstrap the compiler. For now, we allow them to differ and will permit the defaults to differ.

gcc versions and number of buildable packages

A gcc version that is too old will not build a number of packages. Anything older than 4.8 fails for c++11. 4.8 fails on some c++11 packages, such as firefox and glibmm.

A version that is too new also fails to build packages. Jason Bacon posted counts to tech-pkg indicate that 5 is close to 4.8 in the number of packages built, and that moving to 6 causes hundreds of additional failures. (Keep in mind that currently, building with 4.8 will build 4.9 for firefox, but in the future will not.)

www/pkgsrc/packages/sharedapps/pkg-2017Q3/RHEL6-gcc48/All   16461
www/pkgsrc/packages/sharedapps/pkg-2017Q3/RHEL6-gcc6/All    15849

www/pkgsrc/packages/sharedapps/pkg-2017Q3/RHEL7-gcc48/All   16414
www/pkgsrc/packages/sharedapps/pkg-2017Q3/RHEL7-gcc5/All    16338

Therefore, the current answer to "What is the best version to use" is 5.

Default versions for various systems

Note that if for any particular system's set of installed packages (or bulk build), a newer gcc has to be built, it does not hurt to have built it earlier.

When the base system is old (e.g., gcc 4.5 in NetBSD 6, or 4.1, in NetBSD 5), then it is clear that a newer version must be built. For these, PKGSRC_GXX_VERSION should default to a newish gcc, avoiding being so new as to cause building issues. PKGSRC_GCC_VERSION should probably default to the system version if it can build all C99 programs, or match PKGSRC_GXX_VERSION, if the system version is too old. Perhaps gcc 4.5 would be used, but 4.1 not used. \todo Discuss.

When the base system is almost new enough, the decision about the default is more complicated. A key example is gcc 4.8, found in NetBSD 7. Firefox requires gcc 4.9, and all programs using c++14 also need a newer version. One options is to choose 4.8, resulting in firefox failing, as well as all c++14 programs. Another is to choose 4.9, but this makes little sense because c++14 programs will still fail, and the general rule of moving to the most recent generally-acceptable version applies, which currently leads to gcc5. This is in effect a declaration that "almost new enough" does not count as new enough. Thus the plan for NetBSD 7 is to set PKGSRC_GCC_VERSION to 4.8 and PKGSRC_GXX_VERSION to 5.

When the base system is new enough, e.g. gcc 5, 6 or 7 it should simply be used. By "new enough", we mean that almost no programs in pkgsrc fail to build with it (because it is too old), which implies that it supports (almost all) C++14 programs. Our current definiton of new enough is gcc 5.

Limited mixed versions

One approach would be to allow limited mixed versions, where individual programs could force a specific version to be bootstrapped and used, so that e.g. firefox could use 4.9 even though most programs use 4.8, which is what happens now on NetBSD 7. This would rely on being able to link c++ with 4.9 including some things built with 4.8 (which is done presently). However, this approach would become unsound with a library rather than an end program. We reject this as too much complexity for avoiding building a newer compiler in limited situations.

Fortran

Fortran support is currently somewhat troubled.. It seems obvious to extend to PGKSRC_GFORTRAN_VERSION, and have that match PKGSRC_GCC_VERSION or PKGSRC_GXX_VERSION, but the Fortran situation is not worsened by the above design.

When building a gcc version, we get gfortran. Perhaps, because of fortran, we should require a single version, vs a C and a C++ version.

\todo Discuss.

C++ libraries used by C programs

The choice of one version for C++ and one for C (e.g. 5, 4.8 on netbsd-7) breaks down if a C program links against a library that is written in C++ but provides a C API, because we still need the C++ version's stdlib.

\todo Define a variable for such packages to have in their buildlink3, which will not add c++ to USE_LANGUAGES but will force PKGSRC_GXX_VERSION to be used. Or decide that this is a good reason to really just have one compiler version.

Path forward

(This assumes per-package marking of bootstrap packages, but is reasonably obviously extended to the other schemes.)

Later steps

Data

This section has data points that are relevant to the discussion.

amd64/i386

It is believed that pkgsrc gcc generally builds on these systems. gcc6 builds on netbsd-5/i386.

macppc

On macppc, lang/gcc5 fails on netsbd-6 and netbsd-7, but succeeds on netbsd-8.