wiki:UsingTheRightCompiler

Version 17 (modified by ryandesign (Ryan Carsten Schmidt), 11 years ago) (diff)

rewrite some paragraphs

Introduction

Much of the software in MacPorts is built using a C or C++ compiler, and the various versions of Xcode for OS X come with different compiler suites and versions. With Xcode 2.5 on OS X 10.4, gcc 3.3 and 4.0 are available, with 4.0 being the default. With Xcode 3.1 on OS X 10.5, gcc 4.2 is also available. With Xcode 3.2 on OS X 10.6, llvm-gcc-4.2 and clang are also available; gcc 4.2 is the default. With Xcode 4.0 and 4.1 on OS X 10.6 or 10.7, llvm-gcc-4.2 is the default. With Xcode 4.2 or later, clang is the default and gcc is no longer included. The Xcode 4.6 release notes state that it is the last version of Xcode that will include llvm-gcc-4.2, which will leave only clang.

The problem with the default compiler

The default version of gcc can be run simply as "gcc". There's also "cc" which points to the default compiler (which might not necessarily be gcc). The default gcc can be changed using the "gcc_select" command. Some users may have used this command to change their default gcc, for example on Leopard to test new functionality in gcc 4.2, or on Tiger to downgrade to gcc 3.3 to compile old software that is not compatible with gcc 4.

If not instructed otherwise, software builds using "gcc" or "cc" and this can be a problem if the user has changed what this is. For example, on the one hand, gcc 4 may be too new to compile some very old software, but on the other hand gcc 3.3 is probably too old to compile a lot of modern software. The problem is further complicated by the various gcc ports which can be installed using MacPorts, which have different capabilities than the Apple versions of gcc. For example, only the Apple versions can create universal binaries in a single step. The gcc_select port can be used to make any of them the default compiler. So we cannot rely on "gcc" being any particular version of gcc with any particular capabilities, and "cc" varies by Xcode version as well.

Most port authors will not have used "gcc_select" and will therefore have the usual default version of gcc on their machine, and will not have tested to see what happens if a different gcc is selected. To remove this testing burden from maintainers, and to prevent users from running into unanticipated problems, MacPorts arranges for ports to always compile using the correct default version for the current operating system, and does not use the unpredictable "gcc". It does this by specifying the desired compiler's complete path in the CC environment variable during the port's configure phase. For example, on OS X 10.4 and 10.5, CC is set to the value "/usr/bin/gcc-4.0" so that there is no ambiguity.

In fact there are more variables than just CC: there's also CXX for the C++ compiler and CPP for the C pre-processor. During the configure phase, MacPorts sets each of these variables to the right value for the user's OS. It does this through the use of a number of similarly-named Tcl variables: ${configure.cc}, ${configure.cxx} and ${configure.cpp}.

Selecting a different compiler

For most ports, the default compiler chosen by MacPorts is the one that should be used, unless that compiler doesn't work with that port for some reason. In that case, the maintainer can select a different compiler for that port by overwriting ${configure.cc} and friends, but what you probably want to do instead is overwrite the ${configure.compiler} variable, which sets all the related variables for you simultaneously. MacPorts knows about a handful of compilers:

  • cc
  • gcc
  • gcc-3.3
  • gcc-4.0
  • gcc-4.2
  • llvm-gcc-4.2
  • clang
  • apple-gcc-4.0
  • apple-gcc-4.2
  • macports-gcc
  • macports-gcc-4.2
  • macports-gcc-4.3
  • macports-gcc-4.4
  • macports-gcc-4.5
  • macports-gcc-4.6
  • macports-gcc-4.7
  • macports-gcc-4.8
  • macports-llvm-gcc-4.2
  • macports-clang
  • macports-clang-2.9
  • macports-clang-3.0
  • macports-clang-3.1
  • macports-clang-3.2
  • macports-clang-3.3
  • macports-dragonegg-3.0
  • macports-dragonegg-3.1
  • macports-dragonegg-3.2
  • macports-dragonegg-3.3

Compiler names beginning with "macports" use ports in MacPorts (e.g. "macports-gcc-4.7" corresponds to the gcc47 port). So do those whose names begin with "apple" (e.g. "apple-gcc-4.2" corresponds to the apple-gcc42 port). The remaining compiler names refer to compilers installed by Xcode (e.g. "gcc-4.2" is the gcc 4.2.1 compiler installed by Xcode). Note that until the release of MacPorts 2.2, if you set ${configure.compiler} to a compiler provided by a MacPorts port, you must also declare a library dependency on that port.

For the MacPorts gcc 4 compilers, additional environment variables FC, F77 and F90 are set to the path of the Fortran compiler. These variables are not set for the other compilers because they do not include a Fortran compiler.

Ports with nonstandard or nonexistent configure scripts

Setting the CC, CXX and CPP environment variables at configure time is all that most software needs in order to use the compiler we want. But some ports have unusual configure scripts that don't obey these settings, and some ports don't have a configure script at all. For such ports, it can be necessary to set the variables at build time:

build.args-append       CC=${configure.cc} \
                        CXX=${configure.cxx} \
                        CPP=${configure.cpp}

Some ports' Makefiles do not use the CC variable and always try to run "gcc" or "cc". In these cases, patches are needed. For example, "gcc" or "cc" can be replaced with "$(CC)" in the Makefile, possibly in combination with setting ${build.args} as above. Such patches should usually be sent upstream for inclusion in the next version of the software.

How to test

Unless you look closely at the build output in debug mode, it can be hard to know whether a port is using ${configure.cc} as it should. Here is one way to make it obvious:

  1. Create a directory /opt/local/bin/no_default_gcc
  2. Create a script in that directory called "cc" that always prints an error message
  3. Create symlinks "c++", "cpp", "g++", and "gcc", all pointing to the "cc" script
  4. Edit the value of "binpath" in /opt/local/etc/macports/macports.conf so that it begins with "/opt/local/bin/no_default_gcc:"

Now anytime a port tries to use one of these unversioned programs, the above script will be found instead of the actual program and the compile will stop with an error.

Steps 1 through 3 can be done by checking out this directory from the MacPorts Subversion repository:

svn checkout \
https://svn.macports.org/repository/macports/users/ryandesign/no_default_gcc \
/opt/local/bin/no_default_gcc

If you encounter a port which triggers this error but you don't want to fix it immediately, you can bypass it by editing macports.conf and removing "/opt/local/bin/no_default_gcc:" from the "binpath" again.