diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -341,6 +341,23 @@ Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ +Android Support +^^^^^^^^^^^^^^^ + +- Android target triples are usually suffixed with a version. Clang searches for + target-specific runtime and standard libraries in directories named after the + target (e.g. if you're building with ``-target aarch64-none-linux-android21``, + Clang will look for ``lib/aarch64-none-linux-android21`` under its resource + directory to find runtime libraries). If an exact match isn't found, Clang + would previously fall back to a directory without any version (which would be + ``lib/aarch64-none-linux-android`` in our example). Clang will now look for + directories for lower versions and use the newest version it finds instead, + e.g. if you have ``lib/aarch64-none-linux-android21`` and + ``lib/aarch64-none-linux-android29``, ``-target aarch64-none-linux-android23`` + will use the former and ``-target aarch64-none-linux-android30`` will use the + latter. Falling back to a versionless directory will now emit a warning, and + the fallback will be removed in Clang 19. + Windows Support ^^^^^^^^^^^^^^^ - Fixed an assertion failure that occurred due to a failure to propagate diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -749,4 +749,10 @@ InGroup>; def note_drv_available_multilibs : Note< "available multilibs are:%0">; + +def warn_android_unversioned_fallback : Warning< + "Using unversioned Android target directory %0 for target %1. Unversioned" + " directories will not be used in Clang 19. Provide a versioned directory" + " for the target version or lower instead.">, + InGroup>; } diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -182,6 +182,9 @@ EffectiveTriple = std::move(ET); } + std::optional + getFallbackAndroidTargetPath(StringRef BaseDir) const; + mutable std::optional cxxStdlibType; mutable std::optional runtimeLibType; mutable std::optional unwindLibType; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -677,6 +677,50 @@ return Args.MakeArgString(getCompilerRT(Args, Component, Type)); } +// Android target triples contain a target version. If we don't have libraries +// for the exact target version, we should fall back to the next newest version +// or a versionless path, if any. +std::optional +ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const { + llvm::Triple TripleWithoutLevel(getTriple()); + TripleWithoutLevel.setEnvironmentName("android"); // remove any version number + const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str(); + unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor(); + unsigned BestVersion = 0; + + SmallString<32> TripleDir; + bool UsingUnversionedDir = false; + std::error_code EC; + for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef DirName = llvm::sys::path::filename(LI->path()); + StringRef DirNameSuffix = DirName; + if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) { + if (DirNameSuffix.empty() && TripleDir.empty()) { + TripleDir = DirName; + UsingUnversionedDir = true; + } else { + unsigned Version; + if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion && + Version < TripleVersion) { + BestVersion = Version; + TripleDir = DirName; + UsingUnversionedDir = false; + } + } + } + } + + if (TripleDir.empty()) + return {}; + + SmallString<128> P(BaseDir); + llvm::sys::path::append(P, TripleDir); + if (UsingUnversionedDir) + D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString(); + return std::string(P); +} + std::optional ToolChain::getTargetSubDirPath(StringRef BaseDir) const { auto getPathForTriple = @@ -713,15 +757,8 @@ return *Path; } - // Android targets may include an API level at the end. We still want to fall - // back on a path without the API level. - if (getTriple().isAndroid() && - getTriple().getEnvironmentName() != "android") { - llvm::Triple TripleWithoutLevel = getTriple(); - TripleWithoutLevel.setEnvironmentName("android"); - if (auto Path = getPathForTriple(TripleWithoutLevel)) - return *Path; - } + if (getTriple().isAndroid()) + return getFallbackAndroidTargetPath(BaseDir); return {}; } diff --git a/clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android21/libc++.so b/clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android23/libc++.so rename from clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android21/libc++.so rename to clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android23/libc++.so diff --git a/clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android21/libc++.so b/clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android29/libc++.so rename from clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android21/libc++.so rename to clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android29/libc++.so diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android23/libclang_rt.builtins.a rename from clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a rename to clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android23/libclang_rt.builtins.a diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android29/libclang_rt.builtins.a rename from clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a rename to clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android29/libclang_rt.builtins.a diff --git a/clang/test/Driver/android-installed-libcxx.cpp b/clang/test/Driver/android-installed-libcxx.cpp --- a/clang/test/Driver/android-installed-libcxx.cpp +++ b/clang/test/Driver/android-installed-libcxx.cpp @@ -13,6 +13,7 @@ // RUN: mkdir -p %t2/include/c++/v1 // RUN: mkdir -p %t2/sysroot // RUN: mkdir -p %t2/include/aarch64-none-linux-android/c++/v1 +// RUN: mkdir -p %t2/include/aarch64-none-linux-android23/c++/v1 // RUN: %clang -target aarch64-none-linux-android -ccc-install-dir %/t2/bin \ // RUN: --sysroot=%t2/sysroot -stdlib=libc++ -fsyntax-only \ @@ -24,3 +25,14 @@ // ANDROID-DIR: "-internal-isystem" "[[DIR]][[SEP:/|\\\\]]..[[SEP]]include[[SEP]]aarch64-none-linux-android[[SEP]]c++[[SEP]]v1" // ANDROID-DIR-SAME: "-internal-isystem" "[[DIR]][[SEP]]..[[SEP]]include[[SEP]]c++[[SEP]]v1" + +// RUN: %clang -target aarch64-none-linux-android23 -ccc-install-dir %/t2/bin \ +// RUN: --sysroot=%t2/sysroot -stdlib=libc++ -fsyntax-only \ +// RUN: %s -### 2>&1 | FileCheck --check-prefix=ANDROID23-DIR -DDIR=%/t2/bin %s + +// RUN: %clang -target aarch64-none-linux-android28 -ccc-install-dir %/t2/bin \ +// RUN: --sysroot=%t2/sysroot -stdlib=libc++ -fsyntax-only \ +// RUN: %s -### 2>&1 | FileCheck --check-prefix=ANDROID23-DIR -DDIR=%/t2/bin %s + +// ANDROID23-DIR: "-internal-isystem" "[[DIR]][[SEP:/|\\\\]]..[[SEP]]include[[SEP]]aarch64-none-linux-android23[[SEP]]c++[[SEP]]v1" +// ANDROID23-DIR-SAME: "-internal-isystem" "[[DIR]][[SEP]]..[[SEP]]include[[SEP]]c++[[SEP]]v1" diff --git a/clang/test/Driver/android-unversioned-fallback-warning.cpp b/clang/test/Driver/android-unversioned-fallback-warning.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Driver/android-unversioned-fallback-warning.cpp @@ -0,0 +1,33 @@ +// Check that we emit warnings for using unversioned Android target directories +// as appropriate. + +// RUN: mkdir -p %t/bin +// RUN: mkdir -p %t/include/aarch64-none-linux-android/c++/v1 +// RUN: mkdir -p %t/include/aarch64-none-linux-android23/c++/v1 +// RUN: mkdir -p %t/include/c++/v1 +// RUN: mkdir -p %t/lib/aarch64-none-linux-android +// RUN: mkdir -p %t/lib/aarch64-none-linux-android23 +// RUN: mkdir -p %t/resource/lib/aarch64-none-linux-android +// RUN: mkdir -p %t/resource/lib/aarch64-none-linux-android23 + +// Using an unversioned directory for an unversioned triple isn't a warning. +// RUN: %clang -target aarch64-none-linux-android -ccc-install-dir %t/bin \ +// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \ +// RUN: FileCheck --check-prefix=NO-WARNING %s +// NO-WARNING-NOT: Using unversioned Android target directory + +// RUN: %clang -target aarch64-none-linux-android21 -ccc-install-dir %t/bin \ +// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \ +// RUN: FileCheck --check-prefix=ANDROID21 -DDIR=%t -DSEP=%{fs-sep} %s +// ANDROID21-DAG: Using unversioned Android target directory [[DIR]]/bin[[SEP]]..[[SEP]]include[[SEP]]aarch64-none-linux-android +// ANDROID21-DAG: Using unversioned Android target directory [[DIR]]/bin[[SEP]]..[[SEP]]lib[[SEP]]aarch64-none-linux-android +// ANDROID21-DAG: Using unversioned Android target directory [[DIR]]/resource[[SEP]]lib[[SEP]]aarch64-none-linux-android + +// 23 or newer should use the versioned directory +// RUN: %clang -target aarch64-none-linux-android23 -ccc-install-dir %t/bin \ +// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \ +// RUN: FileCheck --check-prefix=NO-WARNING %s + +// RUN: %clang -target aarch64-none-linux-android28 -ccc-install-dir %t/bin \ +// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \ +// RUN: FileCheck --check-prefix=NO-WARNING %s diff --git a/clang/test/Driver/linux-per-target-runtime-dir.c b/clang/test/Driver/linux-per-target-runtime-dir.c --- a/clang/test/Driver/linux-per-target-runtime-dir.c +++ b/clang/test/Driver/linux-per-target-runtime-dir.c @@ -17,12 +17,25 @@ // RUN: %clang --target=aarch64-unknown-linux-android21 -print-file-name=libc++.so 2>&1 \ // RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \ // RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID21 %s -// CHECK-LIBCXX-ANDROID21: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android21{{/|\\}}libc++.so +// CHECK-LIBCXX-ANDROID21: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libc++.so // RUN: %clang --target=aarch64-unknown-linux-android23 -print-file-name=libc++.so 2>&1 \ // RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \ // RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID23 %s -// CHECK-LIBCXX-ANDROID23: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libc++.so +// CHECK-LIBCXX-ANDROID23: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android23{{/|\\}}libc++.so + +// RUN: %clang --target=aarch64-unknown-linux-android26 -print-file-name=libc++.so 2>&1 \ +// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \ +// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID23 %s + +// RUN: %clang --target=aarch64-unknown-linux-android29 -print-file-name=libc++.so 2>&1 \ +// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \ +// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID29 %s +// CHECK-LIBCXX-ANDROID29: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android29{{/|\\}}libc++.so + +// RUN: %clang --target=aarch64-unknown-linux-android31 -print-file-name=libc++.so 2>&1 \ +// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \ +// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID29 %s // RUN: %clang --target=aarch64-unknown-linux-android -print-file-name=libc++.so 2>&1 \ // RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \ @@ -45,13 +58,29 @@ // RUN: --target=aarch64-unknown-linux-android21 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID21 %s -// CHECK-FILE-NAME-ANDROID21: lib{{/|\\}}aarch64-unknown-linux-android21{{/|\\}}libclang_rt.builtins.a +// CHECK-FILE-NAME-ANDROID21: lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libclang_rt.builtins.a // RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ // RUN: --target=aarch64-unknown-linux-android23 \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID23 %s -// CHECK-FILE-NAME-ANDROID23: lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libclang_rt.builtins.a +// CHECK-FILE-NAME-ANDROID23: lib{{/|\\}}aarch64-unknown-linux-android23{{/|\\}}libclang_rt.builtins.a + +// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ +// RUN: --target=aarch64-unknown-linux-android26 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID23 %s + +// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ +// RUN: --target=aarch64-unknown-linux-android29 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID29 %s +// CHECK-FILE-NAME-ANDROID29: lib{{/|\\}}aarch64-unknown-linux-android29{{/|\\}}libclang_rt.builtins.a + +// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ +// RUN: --target=aarch64-unknown-linux-android31 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID29 %s // RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ // RUN: --target=aarch64-unknown-linux-android \