wiki:UsingTheRightCompiler

Version 8 (modified by ryandesign (Ryan Carsten Schmidt), 14 years ago) (diff)

refinements

Introduction

Most software is built using a C compiler called gcc, and the various versions of Xcode for Mac OS X come with different versions of gcc. For example, with Xcode 2.5 on Mac OS X 10.4, gcc 3.3 and 4.0 are available, with 4.0 being the default. With Xcode 3.1 on Mac OS X 10.5, gcc 4.2 is also available; with Xcode 3.2 on Mac OS X 10.6, gcc 4.2 is the default compiler.

The problem with the default compiler

The default version of gcc can be run simply as "gcc". But this default 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.

Software by default builds using "gcc" (or, equivalently, "cc") and this can be a problem if the user has changed what this is. 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.

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 Mac 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:

  • gcc
  • gcc-3.3
  • gcc-4.0
  • gcc-4.2
  • llvm-gcc-4.2
  • clang
  • apple-gcc-3.3
  • apple-gcc-4.0
  • apple-gcc-4.2
  • macports-gcc-3.3
  • macports-gcc-3.4
  • macports-gcc-4.0
  • macports-gcc-4.1
  • macports-gcc-4.2
  • macports-gcc-4.3
  • macports-gcc-4.4

Compiler names beginning with "macports" use ports in MacPorts (e.g. "macports-gcc-4.2" corresponds to the gcc42 port). So do those whose names begin with "apple" (e.g. "apple-gcc-4.0" corresponds to the apple-gcc40 port). The remaining compiler names refer to compilers installed by Xcode (e.g. "gcc-4.0" is the gcc 4.0.1 compiler installed by Xcode). Note that 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.

These variables can also be overridden when running a particular command. So, for example, to build openssl using the version of gcc-4.2 installed with the Developer Tools, you can run

port install openssl configure.compiler=gcc-4.2

However users should not change the compiler a port uses, and doing so is unsupported.

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 \
http://svn.macosforge.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.