| Autoconf, Automake, and Libtool | ||
|---|---|---|
| <<< Previous | Cross Compilation with GNU Autotools | Next >>> |
It is possible to build a program which uses GNU Autotools on one system and to run it on a different type of system. In other words, it is possible to build programs using a cross compiler. In this section, we explain what this means, how to build programs this way, and how to write your configure scripts to support it. Building a program on one system and running it on another is sometimes referred to as a Canadian Cross [1] .
We'll start with an example of a Canadian Cross, to make sure that the concepts are clear. Using a GNU/Linux system, you can build a program which will run on a Solaris system. You would use a GNU/Linux cross Solaris compiler to build the program. You could not run the resulting programs on your GNU/Linux system. After all, they are Solaris programs. Instead, you would have to copy the result over to a Solaris system before you could run it.
Naturally, you could simply build the program on the Solaris system in the first place. However, perhaps the Solaris system is not available for some reason; perhaps you don't actually have one, but you want to build the tools for somebody else to use. Or perhaps your GNU/Linux system is much faster than your Solaris system.
A Canadian Cross build is most frequently used when building programs to run on a non-Unix system, such as DOS or Windows. It may be simpler to configure and build on a Unix system than to support the GNU Autotools tools on a non-Unix system.
When building a Canadian Cross, there are at least two different systems involved: the system on which the tools are being built, and the system on which the tools will run. The system on which the tools are being built is called the build system. The system on which the tools will run is called the host system. For example, if you are building a Solaris program on a GNU/Linux system, as in the previous example, the build system would be GNU/Linux, and the host system would be Solaris.
Note that we already discussed the host system above; see the section called Host and Target. It is, of course, possible to build a cross compiler using a Canadian Cross (i.e., build a cross compiler using a cross compiler). In this case, the system for which the resulting cross compiler generates code is the target system.
An example of building a cross compiler using a Canadian Cross would be building a Windows cross MIPS ELF compiler on a GNU/Linux system. In this case the build system would be GNU/Linux, the host system would be Windows, and the target system would be MIPS ELF.
In order to configure a program for a Canadian Cross build, you must first build and install the set of cross tools you will use to build the program. These tools will be build cross host tools. That is, they will run on the build system, and will produce code that runs on the host system. It is easy to confuse the meaning of build and host here. Always remember that the build system is where you are doing the build, and the host system is where the resulting program will run. Therefore, you need a build cross host compiler.
In general, you must have a complete cross environment in order to do the build. This normally means a cross compiler, cross assembler, and so forth, as well as libraries and header files for the host system. Setting up a complete cross environment can be complex, and is beyond the scope of this book. You may be able to get more information from the crossgcc mailing list and FAQ; see http://www.objsw.com/CrossGCC/.
When you run configure for a Canadian Cross, you must use both the --build and --host options. The --build option is used to specify the configuration name of the build system. This can normally be the result of running the config.guess shell script, and when using a Unix shell it is reasonable to use --build=`config.guess`. The --host option is used to specify the configuration name of the host system.
As we explained earlier, config.guess is used to set the default value for the --host option (see the section called Using the Target Type). We can now see that since config.guess returns the type of system on which it is run, it really identifies the build system. Since the host system is normally the same as the build system (or, in other words, people do not normally build using a cross compiler), it is reasonable to use the result of config.guess as the default for the host system when the --host option is not used.
It might seem that if the --host option were used without the --build option that the configure script could run config.guess to determine the build system, and presume a Canadian Cross if the result of config.guess differed from the --host option. However, for historical reasons, some configure scripts are routinely run using an explicit --host option, rather than using the default from config.guess. As noted earlier, it is difficult or impossible to reliably compare configuration names (see the section called Using the Target Type). Therefore, by convention, if the --host option is used, but the --build option is not used, then the build system defaults to the host system. (This convention may be changing in the Autoconf 2.5 release. Check the release notes.)
You must explicitly specify the cross tools which you want to use to build the program. This is done by setting environment variables before running the configure script. You must normally set at least the environment variables CC, AR, and RANLIB to the cross tools which you want to use to build. For some programs, you must set additional cross tools as well, such as AS, LD, or NM. You would set these environment variables to the build cross host tools which you are going to use.
For example, if you are building a Solaris program on a GNU/Linux system, and your GNU/Linux cross Solaris compiler were named solaris-gcc, then you would set the environment variable CC to solaris-gcc.
If you want to make it possible to build a program which you are developing using a cross compiler, you must take some care when writing your configure.in and make rules. Simple cases will normally work correctly. However, it is not hard to write configure tests which will fail when building with a cross compiler, so some care is required to avoid this.
You should write your configure scripts to support building with a cross compiler if you can, because that will permit others to build your program on a fast compilation server.
In a configure.in file, after calling AC_PROG_CC, you can find out whether the program is being built by a cross compiler by examining the shell variable cross_compiling. If the compiler is a cross compiler, which means that this is a Canadian Cross, cross_compiling will be yes. In a normal configuration, cross_compiling will be no.
You ordinarily do not need to know the type of the build system in a configure script. However, if you do need that information, you can get it by using the macro AC_CANONICAL_SYSTEM, the same macro which is used to determine the target system. This macro will set the variables build, build_alias, build_cpu, build_vendor, and build_os, which correspond to the similar target and host variables, except that they describe the build system. See the section called Using the Target Type.
When writing tests in configure.in, you must remember that you want to test the host environment, not the build environment. Macros which use the compiler, such as like AC_CHECK_FUNCS, will test the host environment. That is because the tests will be done by running the compiler, which is actually a build cross host compiler. If the compiler can find the function, that means that the function is present in the host environment.
Tests like test -f /dev/ptyp0, on the other hand, will test the build environment. Remember that the configure script is running on the build system, not the host system. If your configure scripts examines files, those files will be on the build system. Whatever you determine based on those files may or may not be the case on the host system.
Most Autoconf macros will work correctly when building with a cross compiler. The main exception is AC_TRY_RUN. This macro tries to compile and run a test program. This will fail when building with a cross compiler, because the program will be compiled for the host system, which means that it will not run on the build system.
The AC_TRY_RUN macro provides an optional argument to tell the configure script what to do when building with a cross compiler. If that argument is not present, you will get a warning when you run autoconf:
warning: AC_TRY_RUN called without default to allow cross compiling
|
This tells you that the resulting configure script will not work when building with a cross compiler.
In some cases while it may better to perform a test at configure time, it is also possible to perform the test at run time (see the section called Testing system features at application runtime in the chapter called Writing New Macros for Autoconf). In such a case you can use the cross compiling argument to AC_TRY_RUN to tell your program that the test could not be performed at configure time.
There are a few other autoconf macros which will not work correctly when building with a cross compiler: a partial list is AC_FUNC_GETPGRP, AC_FUNC_SETPGRP, AC_FUNC_SETVBUF_REVERSED, and AC_SYS_RESTARTABLE_SYSCALLS. The AC_CHECK_SIZEOF macro is generally not very useful when building with a cross compiler; it permits an optional argument indicating the default size, but there is no way to know what the correct default should be.
The main cross compiling issue in a Makefile arises when you want to use a subsidiary program to generate code or data which you will then include in your real program. If you compile this subsidiary program using $(CC) in the usual way, you will not be able to run it. This is because $(CC) will build a program for the host system, but the program is being built on the build system. You must instead use a compiler for the build system, rather than the host system. This compiler is conventionally called $(CC_FOR_BUILD).
A configure script should normally permit the user to define CC_FOR_BUILD explicitly in the environment. Your configure script should help by selecting a reasonable default value. If the configure script is not being run with a cross compiler (i.e., the cross_compiling shell variable is no after calling AC_PROG_CC), then the proper default for CC_FOR_BUILD is simply $(CC). Otherwise, a reasonable default is simply cc.
Note that you should not include config.h in a file you are compiling with $(CC_FOR_BUILD). The configure script will build config.h with information for the host system. However, you are compiling the file using a compiler for the build system (a native compiler). Subsidiary programs are normally simple filters which do no user interaction, and it is often possible to write them in a highly portable fashion so that the absence of config.h is not crucial.
The gcc Makefile.in shows a complex situation in which certain files, such as rtl.c, must be compiled into both subsidiary programs run on the build system and into the final program. This approach may be of interest for advanced GNU Autotools hackers. Note that, at least in GCC 2.95, the build system compiler is rather confusingly called HOST_CC.
| [1] | The name Canadian Cross comes from the most complex case, in which three different types of systems are used. At the time that these issues were being hashed out, Canada had three national political parties. |
| <<< Previous | Home | Next >>> |
| Using the Target Type | Up | Installing GNU Autotools |