wiki:CompilerSelection

Version 3 (modified by kencu (Ken), 4 years ago) (diff)

--

Quick Start

The following most-commonly used Portfile commands will choose a set appropriate compilers with the required capability for a given OS version:

Command Description Possible Values Default
compiler.c_standard C Standard Required 1989, 1999, 2011 1989
compiler.cxx_standard C++ Standard Required 1998, 2011, 2014, 2017 1998
compiler.thread_local_storage Is thread local storage required? yes or no no

For further details and more related options, please read on.

Overview

The flexibility of a Portfile allows MacPorts to support a wide variety of languages. The lowest level of support is for a Portfile to call the appropriate build command. The port lapack-manpages builds documentation by calling doxygen. Commonality among several ports can be gathered into a portgroup. For example, there is a portgroup that facilitates building projects written in Rust. However, some language have direct support in the MacPorts base.

Minimal Base Support

Perl, Python, Ruby, Awk, Bison, and Java have minimal support in the base through

configure.perl
configure.python
configure.ruby
configure.awk
configure.bison
configure.javac

These commands do nothing more than set environmental variables during the configure phase if use_configure is yes. They do not add dependencies.

Full Base Support

C and C++ are fully supported in the base. This means that, unless instructed otherwise, each Portfile will have access to a compiler for both of these languages.

  • configure.cc, configure.cxx, and configure.cpp are set.
  • The environmental variables CC and CXX are set during the configure phase if use_configure is yes.
  • If MacPorts provides the compiler, the appropriate dependencies are added.

Ideally, Xcode would provide the C and C++ compilers. This ideal, however, cannot always be achieved. MacPorts have two alternates to provide C and C++ compilers: Clang and GCC.

Language Standards

Both C and C++ evolve. A project can require a more recent C standard or C++ standard than is provided by the Xcode compiler.

C Standards supported by Clang, GCC, and Xcode:

C Standard Clang Xcode Clang Xcode GCC
1989 (C89) - - - -
1999 (C99) - - - -
2011 (C11) 3.1 318.0.61 4.3 4.9

C++ Standards supported by Clang, GCC, and Xcode:

C++ Standard Clang Xcode Clang Xcode GCC
1998 (C++98) - - - -
2011 (C++11) 3.3 500.2.75 5.0 4.8.1
2014 (C++14) 3.4 600.0.54 6.1 5
2017 (C++17) 5.0 902.0.39.1 9.3 7

Parallelism

The compilers provided by Xcode do not support all of the methods of parallelism that ports may require.

None of the compilers provided by Xcode support any version OpenMP. OpenMP Standards supported by Clang, GCC, and Xcode:

OpenMP Version Clang Xcode Clang Xcode GCC
2.5 3.8 Future? Future? 4.2
3.0 3.8 Future? Future? 4.4
3.1 3.8 Future? Future? 4.7
4.0 Partial Future? Future? 4.9
4.5 Partial Future? Future? ???

None of the compilers provided by Xcode implement MPI. To implement it, MPICH and Open MPI provide wrappers for Clang, GCC, and Xcode.

The compilers provided by Xcode only support thread-local storage if the OS supports it, which did not happen until Mac OS X Lion. GCC and Clang can emulate thread-local storage even on versions of macOS that do not support it.

C++ Standard Library

There are three possible C++ standard libraries on macOS.

C++ standard libraries supported by Clang, GCC, and Xcode:

C++ Standard Library Supported by Clang Supported by Xcode Supported by GCC Supports C++11
libc++ Yes (-stdlib=libc++) Yes (-stdlib=libc++) No Yes
libstdc++ in /usr/lib/ Yes (-stdlib=libstdc++) Yes (-stdlib=libstdc++) No No
libstdc++ provided by MacPorts Yes (-stdlib=macports-libstdc++) No Yes Yes

Getting the Right Compiler in the Portfile

Names of valid Compilers:

Regular Expression Description
^apple-gcc-(4\.[02])$ MacPorts Apple GCC %s
^cc$ System cc
^clang$ Xcode Clang
^gcc$ System GCC
^gcc-(3\.3|4\.[02])$ Xcode GCC %s
^llvm-gcc-4\.2$ Xcode LLVM-GCC 4.2
^macports-clang$ MacPorts Clang (port select)
^macports-clang-(\d+\.\d+)$ MacPorts Clang %s
^macports-dragonegg-(\d+\.\d+)$ MacPorts DragonEgg %s
^macports-dragonegg-(\d+\.\d+)-gcc-(\d+\.\d+)$ MacPorts DragonEgg %s with GCC %s
^macports-gcc$ MacPorts GCC (port select)
^macports-gcc-(\d+(?:\.\d+)?)$ MacPorts GCC %s
^macports-llvm-gcc-4\.2$ MacPorts LLVM-GCC 4.2
^macports-g95$ MacPorts G95
^macports-mpich-default$ MacPorts MPICH Wrapper for MacPorts' Default C/C++ Compiler
^macports-openmpi-default$ MacPorts Open MPI Wrapper for MacPorts' Default C/C++ Compiler
^macports-mpich-clang$ MacPorts MPICH Wrapper for Xcode Clang
^macports-openmpi-clang$ MacPorts Open MPI Wrapper for Xcode Clang
^macports-mpich-clang-(\d+\.\d+)$ MacPorts MPICH Wrapper for Clang %s
^macports-openmpi-clang-(\d+\.\d+)$ MacPorts Open MPI Wrapper for Clang %s
^macports-mpich-gcc-(\d+(?:\.\d+)?)$ MacPorts MPICH Wrapper for GCC %s
^macports-openmpi-gcc-(\d+(?:\.\d+)?)$ MacPorts Open MPI Wrapper for GCC %s

The compiler is chosen with the following precedence:

  1. If configure.compiler is set in the Portfile, then that is the compiler that is used.
  2. If the user sets default_compilers, the compiler is chosen from that list unless the compiler is blacklisted.
  3. If the Portfile sets compiler.whitelist, the compiler is chosen from that list unless the compiler is blacklisted.
  4. If the Portfile sets compiler.fallback, the compiler is chosen from that list unless the compiler is blacklisted.
  5. A compiler is chosen (Xcode compilers if possible) that
    • is not blacklisted,
    • is known to work on the particular version of the OS, and
    • satisfies the requirements set in the Portfile.

The following are requirements that can be set in the Portfile:

Description Possible Values Default
compiler.c_standard Standard for the C programming language 1989, 1999, 2011, etc. 1989
compiler.cxx_standard Standard for the C++ programming language 1998, 2011, 2014, 2017, etc. 1998
compiler.openmp_version Version of OpenMP required blank, 2.5, 3.0, 3.1, 4.0, 4.5, etc. blank
compiler.mpi MacPorts port that provides MPI blank, mpich, or openmpi blank
compiler.thread_local_storage Is thread local storage required, e.g. __thread, _Thread_local, or std::thread_local yes or no no
configure.cxx_stdlib C++ Standard Library blank, libc++, libstdc++, or macports-libstdc++ dependent on user preference and OS version

Medium Base Support

Objective-C and Objective-C++ are supported as well.

  • configure.objc and configure.objcxx are set.
  • The environmental variables OBJC and OBJCXX are set during the configure phase if use_configure is yes.

This is achieved, however, by assuming that the Objective-C and Objective-C++ compilers as the same as the C and C++ compilers respectively.

Fortran is partially supported in the base.

  • configure.fc, configure.f90, and configure.f77 are set.
  • The environmental variables FC, F90, and F77 are set during the configure phase if use_configure is yes.
  • If MacPorts provides the compiler, the appropriate dependencies are added.

Xcode does not provide any Fortran compilers. Clang does not provide a Fortran compiler (although Flang might one day be viable). A Fortran compiler is available only if one is requested or is provided by a previously requested compiler.

  1. A Fortran compiler is requested if compiler.require_fortran is set to yes.
  2. A Fortran compiler is provided if GCC is being used as a compiler (since GCC provides GFortran anyway).

The Fortran compiler is chosen with the following precedence:

  1. If a Fortran compiler is already available (e.g. from GCC), then use it.
  2. If the Portfile sets compiler.fortran_fallback, the Fortran compiler is chosen from that list unless the compiler is blacklisted.
  3. A Fortran compiler is chosen that
    • is not blacklisted,
    • is known to work on the particular version of the OS, and
    • satisfies the requirements set in the Portfile.

Compiler Consideration: Runtime Libraries

When a GCC compiler is used, the resulting binary links against libgcc, a low-level runtime library. While there can be multiple versions of these runtimes in a single process, it is not possible to pass objects between different versions. So while MacPorts allows multiple versions of GCC to be installed at once, they must all use the same libgcc. This means that an upgrade of libgcc sometimes requires ports compiled with GCC to be rebuilt.

Passing objects between C++ standard libraries can cause crashes that are difficult to debug. The current trend is to use libc++ on all systems except on older PowerPC systems. Some notes on the C++ Standard Libraries:

  1. libc++
    • Installed by the system on Mac OS X Lion and later.
    • Is the default C++ standard library on OS X Mavericks and later.
  2. libstdc++ in /usr/lib/
    • Does not support C++11.
    • Is now deprecated.
    • Was the default C++ standard library prior to OS X Mavericks.
  3. libstdc++ provided by MacPorts