diff options
-rw-r--r-- | build/cmake/android.toolchain.cmake | 18 | ||||
-rw-r--r-- | build/core/build-binary.mk | 20 | ||||
-rw-r--r-- | docs/BuildSystemMaintainers.md | 56 | ||||
-rw-r--r-- | docs/changelogs/Changelog-r22.md | 20 | ||||
-rwxr-xr-x | ndk/checkbuild.py | 46 | ||||
-rw-r--r-- | ndk/test/test_devices.py | 2 | ||||
-rw-r--r-- | ndk/testing/standalone_toolchain.py | 13 | ||||
-rw-r--r-- | ndk/toolchains.py | 2 |
8 files changed, 128 insertions, 49 deletions
diff --git a/build/cmake/android.toolchain.cmake b/build/cmake/android.toolchain.cmake index 48a29bd74..1f6302bb2 100644 --- a/build/cmake/android.toolchain.cmake +++ b/build/cmake/android.toolchain.cmake @@ -342,8 +342,12 @@ set(ANDROID_COMPILER_FLAGS_RELEASE) set(ANDROID_LINKER_FLAGS) set(ANDROID_LINKER_FLAGS_EXE) -if(ANDROID_LD STREQUAL lld) - list(APPEND ANDROID_LINKER_FLAGS -fuse-ld=lld) +if(ANDROID_LD STREQUAL deprecated) + if(ANDROID_ABI STREQUAL arm64-v8a) + list(APPEND ANDROID_LINKER_FLAGS -fuse-ld=bfd) + else() + list(APPEND ANDROID_LINKER_FLAGS -fuse-ld=gold) + endif() endif() # Don't re-export libgcc symbols in every binary. @@ -468,12 +472,12 @@ list(APPEND ANDROID_COMPILER_FLAGS # default hash ("fast"). # # Note that because we cannot see the user's flags, we can't detect this very -# accurately. Users that explicitly use -fuse-ld=lld instead of ANDROID_LD will -# not be able to debug. -if(ANDROID_LD STREQUAL lld) - list(APPEND ANDROID_LINKER_FLAGS -Wl,--build-id=sha1) -else() +# accurately. Users that explicitly use -fuse-ld=bfd instead of ANDROID_LD will +# have broken builds. +if(ANDROID_LD STREQUAL deprecated) list(APPEND ANDROID_LINKER_FLAGS -Wl,--build-id) +else() + list(APPEND ANDROID_LINKER_FLAGS -Wl,--build-id=sha1) endif() list(APPEND ANDROID_LINKER_FLAGS -Wl,--fatal-warnings) diff --git a/build/core/build-binary.mk b/build/core/build-binary.mk index 7aaba38e2..bab405240 100644 --- a/build/core/build-binary.mk +++ b/build/core/build-binary.mk @@ -496,23 +496,25 @@ CLEAN_OBJS_DIRS += $(LOCAL_OBJS_DIR) # linker_ldflags := -using_lld := false -ifeq ($(APP_LD),lld) - linker_ldflags := -fuse-ld=lld - using_lld := true +using_lld := true +ifeq ($(APP_LD),deprecated) + ifeq ($(TARGET_ARCH_ABI),arm64-v8a) + linker_ldflags := -fuse-ld=bfd + else + linker_ldflags := -fuse-ld=gold + endif + using_lld := false endif combined_ldflags := $(TARGET_LDFLAGS) $(NDK_APP_LDFLAGS) $(LOCAL_LDFLAGS) ndk_fuse_ld_flags := $(filter -fuse-ld=%,$(combined_ldflags)) ndk_used_linker := $(lastword $(ndk_fuse_ld_flags)) ifeq ($(ndk_used_linker),-fuse-ld=lld) + # In case the user has set APP_LD=deprecated but also enabled it for a + # specific module. using_lld := true else - # In case the user has set APP_LD=lld but also disabled it for a specific - # module. - ifneq ($(ndk_used_linker),) - using_lld := false - endif + using_lld := false endif # https://github.com/android/ndk/issues/885 diff --git a/docs/BuildSystemMaintainers.md b/docs/BuildSystemMaintainers.md index 922d84405..b2b057ce4 100644 --- a/docs/BuildSystemMaintainers.md +++ b/docs/BuildSystemMaintainers.md @@ -21,14 +21,16 @@ executables and scripts will differ. ## Introduction -The NDK uses [Clang] as its C/C++ compiler and [Binutils] for linking, -archiving, and object file manipulation. Binutils provides both BFD and gold for -linking. LLVM's [LLD] is also included for testing. AOSP uses LLD by default for -most projects and the NDK is expected to move to it in the future. +The NDK predominantly uses [LLVM] tools for building C/C++ code. These include +[Clang] for compilation, [LLD] for linking, and other [LLVM tools] as well as +some parts of [Binutils] for other tasks. Binutils will soon be entirely +replaced by its LLVM equivalents within the NDK, but it remains available during +the transition. [Binutils]: https://www.gnu.org/software/binutils [Clang]: https://clang.llvm.org/ [LLD]: https://lld.llvm.org/ +[LLVM tools]: https://llvm.org/docs/CommandGuide/ ### Architectures [Architectures]: #architectures @@ -198,23 +200,29 @@ Versions] sections. ## Linkers -Gold is used by default for most architectures, but BFD is used for AArch64 as -Gold emits broken debug information for that architecture (see [Issue 70838247] -for more details). +LLD is the default linker. + +Gold is the fallback linker for most architectures, but BFD is used for AArch64 +as Gold emits broken debug information for that architecture (see [Issue +70838247] for more details). + +The linker used by Clang can be selected with the `-fuse-ld=<linker>` argument, +passed during linking. For example, to use gold instead of LLD, pass +`-fuse-ld=gold` when linking. No argument is required to use LLD. + +The default linkers are installed to +`<NDK>/toolchains/llvm/prebuilt/<host-tag>/bin/<triple>-ld` and +`<NDK>/toolchains/llvm/prebuilt/<host-tag>/<triple>/bin/ld`. BFD and gold are +installed as `ld.bfd` or `ld.gold` in the same locations. The triple-prefixed +executables in the common bin directory should be preferred to the +triple-specific bin directory because the triple-specific directory will be +removed when binutils is removed from the NDK. Note: It is usually not necessary to invoke the linkers directly since Clang will do so automatically. Clang will also automatically link CRT objects and default libraries and set up other target-specific options, so it is generally better to use Clang for linking. -The default linkers are installed to -`<NDK>/toolchains/llvm/prebuilt/<host-tag>/bin/<triple>-ld` and -`<NDK>/toolchains/llvm/prebuilt/<host-tag>/<triple>/bin/ld`. To use BFD or gold -explicitly, use `ld.bfd` or `ld.gold` from the same locations. `ld.lld` is not -installed to the triple directory and is not triple-prefixed, but rather is only -installed as `<NDK>/toolchains/llvm/prebuilt/<host-tag>/bin/ld.lld` because the -one binary supports all ABIs. - Warning: Using LLD with GNU `strip` or `objcopy` breaks RelRO. LLVM `strip` and `objcopy` must be used with LLD. See [Issue 843] and the [Binutils] section of this document for more information. @@ -236,16 +244,24 @@ but are not limited to: * readelf * strip -For some of these tools, LLVM equivalents are available. They typically have the +For each of these tools, LLVM equivalents are available. They typically have the same name but are prefixed with `llvm-`. For example, `llvm-strip` is used instead of `<triple>-strip` or the `strip` binary from the triple-specific directory. +Note that binutils `as` is used by Clang if the `-fno-integrated-as` argument is +used. + Android is moving away from GNU Binutils in favor of LLVM tools. This is a work -in progress, but it is likely that a future release of the NDK will deprecate -and eventually remove GNU Binutils. For now, ensure that your build system works -with `llvm-strip` and `llvm-objcopy` as they are required when using LLD ([Issue -843]). +in progress, but it is likely that binutils will be deprecated in the next +release of the NDK and removed in the late 2020 LTS release. + +At present, the only binutils tool still used by the NDK's build systems is +`ar`. There may be some issues using `llvm-ar` as a drop in replacement for `ar` +on Darwin that are still being investigated. See [Issue 1209] for more +information. + +[Issue 1209]: https://github.com/android/ndk/issues/1209 ## Sysroot diff --git a/docs/changelogs/Changelog-r22.md b/docs/changelogs/Changelog-r22.md index 0b102a579..bdeb8f04f 100644 --- a/docs/changelogs/Changelog-r22.md +++ b/docs/changelogs/Changelog-r22.md @@ -9,16 +9,14 @@ For Android Studio issues, follow the docs on the [Android Studio site]. ## Announcements -* [LLD](https://lld.llvm.org/) is now available for testing. AOSP has switched - to using LLD by default and the NDK will follow (timeline unknown). Test LLD - in your app by passing `-fuse-ld=lld` when linking. Note that [Issue 843] - will affect builds using LLD with binutils strip and objcopy as opposed to - llvm-strip and llvm-objcopy. +* [LLD](https://lld.llvm.org/) is now the default linker. Gold and BFD will + likely be removed in the next LTS release (Q3-Q4 2020). See the Changes + section below for more information. * [Issue 843]: Build system maintainers should begin testing with LLVM's binutils. Android has switched to using these by default (with the exception of llvm-ar, as we're still investigating some issues on macOS), and GNU - binutils will be removed in a future release. + binutils will likely be removed in the next LTS release (Q3-Q4 2020). ## Changes @@ -38,6 +36,16 @@ For Android Studio issues, follow the docs on the [Android Studio site]. r19, file a bug with your build system maintainer. See the [Build System Maintainers Guide] for information on using the NDK in your own build system. +* LLD is now used by default. If your build is not yet compatible with LLD, you + can continue using the deprecated linkers, set `APP_LD=deprecated` for + ndk-build, `ANDROID_LD=deprecated` for CMake, or use an explicit + `-fuse-ld=gold` or `-fuse-ld=bfd` in your custom build system. If you + encounter issues be sure to file a bug, because this will not be an option in + a subsequent release. + + Note that [Issue 843] will affect builds using LLD with binutils strip and + objcopy as opposed to llvm-strip and llvm-objcopy. + [Build System Maintainers Guide]: https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md ## Known Issues diff --git a/ndk/checkbuild.py b/ndk/checkbuild.py index 6a1e82830..eaf7f1c80 100755 --- a/ndk/checkbuild.py +++ b/ndk/checkbuild.py @@ -1956,6 +1956,52 @@ class BaseToolchain(ndk.builds.Module): binutils_dir = self.get_dep('binutils').get_install_path(arch=arch) copy_tree(binutils_dir, install_dir) + # Replace the default ld executable with lld. + triple = ndk.abis.arch_to_triple(arch) + bin_dir = Path(install_dir) / 'bin' + arch_bin_dir = Path(install_dir) / triple / 'bin' + + bin_ld = bin_dir / f'{triple}-ld{exe}' + arch_ld = arch_bin_dir / f'ld{exe}' + lld = bin_dir / f'ld.lld{exe}' + + bin_ld.unlink() + shutil.copyfile(lld, bin_ld) + shutil.copystat(lld, bin_ld) + + arch_ld.unlink() + shutil.copyfile(lld, arch_ld) + shutil.copystat(lld, arch_ld) + + # LLD isn't really meant to be moved, so it doesn't have an RPATH + # for the arch-specific directory. Ideally we wouldn't copy to this + # directory at all, but Clang only searches the arch-specific + # directory, so if we don't have this it'll wrongly fall back to + # /usr/bin/ld. + # + # We'll fix Clang before we remove the directory entirely when we + # remove binutils, but for now just copy the dependent libraries + # with it. + if not self.host.is_windows: + src_lib64 = bin_dir.parent / 'lib64' + dst_lib64 = arch_bin_dir.parent / 'lib64' + # The directory already exists for LP64 ABIs, but not for LP32 + # ABIs. + dst_lib64.mkdir(exist_ok=True) + + libcxx = versioned_so(self.host, 'libc++', '1') + shutil.copyfile(src_lib64 / libcxx, dst_lib64 / libcxx) + shutil.copystat(src_lib64 / libcxx, dst_lib64 / libcxx) + + libcxxabi = versioned_so(self.host, 'libc++', '1') + shutil.copyfile(src_lib64 / libcxxabi, dst_lib64 / libcxxabi) + shutil.copystat(src_lib64 / libcxxabi, dst_lib64 / libcxxabi) + else: + src = bin_dir / 'libwinpthread-1.dll' + dest = arch_bin_dir / 'libwinpthread-1.dll' + shutil.copyfile(src, dest) + shutil.copystat(src, dest) + platforms = self.get_dep('platforms') assert isinstance(platforms, Platforms) for api in platforms.get_apis(): diff --git a/ndk/test/test_devices.py b/ndk/test/test_devices.py index f953d830f..164d5176e 100644 --- a/ndk/test/test_devices.py +++ b/ndk/test/test_devices.py @@ -43,7 +43,7 @@ class MockDevice(ndk.test.devices.Device): class TestBuildConfiguration(ndk.test.spec.BuildConfiguration): def __init__(self, abi: Abi, api: Optional[int]): # Linker option is irrelevant for determining device compatibility. - super().__init__(abi, api, LinkerOption.Default) + super().__init__(abi, api, LinkerOption.Lld) class DeviceTest(unittest.TestCase): diff --git a/ndk/testing/standalone_toolchain.py b/ndk/testing/standalone_toolchain.py index 6708d52ee..6461287e5 100644 --- a/ndk/testing/standalone_toolchain.py +++ b/ndk/testing/standalone_toolchain.py @@ -68,14 +68,17 @@ def make_standalone_toolchain(ndk_path: str, arch: str, api: int, def test_standalone_toolchain(install_dir: str, test_source: str, - flags: List[str], - linker: LinkerOption) -> Tuple[bool, str]: + flags: List[str], linker: LinkerOption, + abi: ndk.abis.Abi) -> Tuple[bool, str]: compiler_name = 'clang++' compiler = os.path.join(install_dir, 'bin', compiler_name) cmd = [compiler, test_source, '-Wl,--no-undefined', '-Wl,--fatal-warnings'] - if linker == LinkerOption.Lld: - cmd.append('-fuse-ld=lld') + if linker == LinkerOption.Deprecated: + if abi == ndk.abis.Abi('arm64-v8a'): + cmd.append('-fuse-ld=bfd') + else: + cmd.append('-fuse-ld=gold') cmd += flags if os.name == 'nt': # The Windows equivalent of exec doesn't know file associations so it @@ -97,6 +100,6 @@ def run_test(ndk_path: str, abi: ndk.abis.Abi, api: int, linker: LinkerOption, if not success: return success, out return test_standalone_toolchain(install_dir, test_source, flags, - linker) + linker, abi) finally: shutil.rmtree(install_dir) diff --git a/ndk/toolchains.py b/ndk/toolchains.py index 669f2527d..c1e949746 100644 --- a/ndk/toolchains.py +++ b/ndk/toolchains.py @@ -35,7 +35,7 @@ HOST_TRIPLE_MAP = { @enum.unique class LinkerOption(enum.Enum): - Default = 'default' + Deprecated = 'deprecated' Lld = 'lld' |