|
| 1 | +# GNU Fortran Universal Build |
| 2 | + |
| 3 | +This directory contains the scripts used to build a fully universal |
| 4 | +GNU Fortran for macOS. The scripts will build for the `/opt/gfortran` |
| 5 | +destination with macOS 11 target and SDK. (Most scripts have a single |
| 6 | +`prefix` parameter, but some don't). The build requires macOS 11 |
| 7 | +or higher and Apple silicon machine with Rosetta 2 installed. |
| 8 | + |
| 9 | +The scripts are described in the order they should be run. |
| 10 | + |
| 11 | +* `deps.sh` - downloads and builds GCC dependencies. |
| 12 | + They are built statically, so they do not need to be distributed |
| 13 | + with the compiler. They will be installed in the `deps` |
| 14 | + subdirectory. |
| 15 | + Note: for Rosetta 2 safety `gmp` is built with `westmere` target to |
| 16 | + avoid illegal instruction faults in Rosetta due to AVX. |
| 17 | + |
| 18 | +* `build.sh` - builds GCC + GNU Fortran for all four combinations. |
| 19 | + |
| 20 | + The first step is to build stubs for all system tools, |
| 21 | + because cross-compilation requires `<arch>-<build>-<tool>` even |
| 22 | + though all tools are universal, so the stubs simply execute |
| 23 | + `/usr/bin/<tool>` instead (see the `stubs` directory). |
| 24 | + |
| 25 | + Then the native arm64 and x86_64 compilers are built (for simplicity |
| 26 | + we treat x86_64 as native) then the corresponding cross-compilers |
| 27 | + targetting the other architecture. The resulting directories have |
| 28 | + this structure: |
| 29 | + |
| 30 | + * `obj-<host_arch>-<target_arch>` location of the GCC build |
| 31 | + * `dst-<host_arch>-<target_arch>` location of the installation |
| 32 | + |
| 33 | + After each successful build the result is installed in the prefix |
| 34 | + location, becuase the cross-compiler build uses GCC built in the |
| 35 | + native step from the installed location. |
| 36 | + |
| 37 | + Note: all `@rpath`s are removed and replaced with target locations, |
| 38 | + becuase run-time libraries are notoriously fragile when using |
| 39 | + `@rpath` (works for the compilers, but not the run-time). |
| 40 | + |
| 41 | + `UPDATE=1` env var can be set in repeated calls to `build.sh` to |
| 42 | + avoid re-building already built `dst-*-*` directories. |
| 43 | + |
| 44 | +* `mkuniversal.sh` - uses the `dst-*-*` directories to create a final |
| 45 | + `dst-universal` directory. It is based on the cross-compiled |
| 46 | + builds (because the native builds include `g++` which is not |
| 47 | + necessary and opens a whole can of worms we don't want). Then all |
| 48 | + binaries for the same target are `lipo`ed from both architectures - |
| 49 | + both the drivers in `bin` and `libexec`. Then the simple `gfortran` |
| 50 | + driver-driver is built (from `stubs`). |
| 51 | + |
| 52 | +This process is more or less based on Apple's old `gcc` and the way we |
| 53 | +created universal GNU Fortran back then for PowerPC and Intel, which |
| 54 | +was copnceptually built this way. Unfortunately, the original |
| 55 | +`driverdriver.c` can no longer be used, because the GCC driver API has |
| 56 | +changed dramatically in 2010 so we provide a very rudimentary |
| 57 | +driver-driver which only filters duplicate `-arch` flags and raises an |
| 58 | +error if different archs are used. |
| 59 | + |
| 60 | +An alternative `dr.sh` is provided to support multi-arch compilation |
| 61 | +in one call via `-arch arm64 -arch x86_64`, but that is not |
| 62 | +well-tested and instead of linking a full GCC driver, it relies on a |
| 63 | +hack where the GCC driver will list output files into a file specified |
| 64 | +by `_GCC_WRITE_OUTFILES` which are then `lipo`ed together. |
| 65 | + |
| 66 | +Note: all builds use `--enable-version-specific-runtime-libs` to |
| 67 | +ensure that both the native compilers and the cross-compilers use the |
| 68 | +same run-time library locations. Technically, we could `lipo` both |
| 69 | +`lib` locations into one (which is what we did when we used the native |
| 70 | +prefix location), but the rationale is that not using the native |
| 71 | +location is safer. |
| 72 | + |
| 73 | +Simon Urbanek |
| 74 | + |
| 75 | +February 2023 |
0 commit comments