[clang] 58288c6 - [driver] Search for compatible Android runtime directories

Shoaib Meenai via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 18 16:25:05 PDT 2023


Author: Shoaib Meenai
Date: 2023-09-18T16:14:18-07:00
New Revision: 58288c6c1214f8a3a0e32e003406437652e098bd

URL: https://github.com/llvm/llvm-project/commit/58288c6c1214f8a3a0e32e003406437652e098bd
DIFF: https://github.com/llvm/llvm-project/commit/58288c6c1214f8a3a0e32e003406437652e098bd.diff

LOG: [driver] Search for compatible Android runtime directories

Android triples include a version number, which makes direct triple
comparisons for per-target runtime directory searching not always work.
Instead, look for the triple with the highest compatible version number
and use that per-target runtime directory instead. This maintains the
existing fallback to a triple without any version number, but I'm hoping
we can remove that in the future. https://discourse.llvm.org/t/62717
discusses this further.

The one remaining triple mismatch after this is that Android armv7
triples usually have an environment of `androideabi`, which Clang
normalizes to `android`. If you use the `androideabi` triple when
building the runtimes with a per-target runtimes dir, the directory will
get created with `androideabi` in its name, but Clang's triple search
uses the normalized triple and will look for an `android` directory
instead. https://reviews.llvm.org/D140925 will fix that by normalizing
triples when creating the per-target runtimes directories as well.

Reviewed By: phosek, pirama

Differential Revision: https://reviews.llvm.org/D158476

Added: 
    clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android23/libc++.so
    clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android29/libc++.so
    clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android23/libclang_rt.builtins.a
    clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android29/libclang_rt.builtins.a
    clang/test/Driver/android-unversioned-fallback-warning.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/include/clang/Driver/ToolChain.h
    clang/lib/Driver/ToolChain.cpp
    clang/test/Driver/android-installed-libcxx.cpp
    clang/test/Driver/linux-per-target-runtime-dir.c

Removed: 
    clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android21/libc++.so
    clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d48bcb24e74ddb8..130dbe870f26d9a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -341,6 +341,23 @@ X86 Support
 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
index 9349ff85ca8a1d3..61ac792d6fda46a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -749,4 +749,10 @@ def warn_drv_missing_multilib : Warning<
   InGroup<DiagGroup<"missing-multilib">>;
 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<DiagGroup<"android-unversioned-fallback">>;
 }

diff  --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index 96d76c2384a9aa6..2d0c1f826c1728a 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -182,6 +182,9 @@ class ToolChain {
     EffectiveTriple = std::move(ET);
   }
 
+  std::optional<std::string>
+  getFallbackAndroidTargetPath(StringRef BaseDir) const;
+
   mutable std::optional<CXXStdlibType> cxxStdlibType;
   mutable std::optional<RuntimeLibType> runtimeLibType;
   mutable std::optional<UnwindLibType> unwindLibType;

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 3a7e90e6b637707..31245964c4baab3 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -677,6 +677,50 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
   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<std::string>
+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<std::string>
 ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
   auto getPathForTriple =
@@ -713,15 +757,8 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
       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
similarity index 100%
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/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a b/clang/test/Driver/Inputs/basic_android_libcxx_tree/usr/lib/aarch64-unknown-linux-android29/libc++.so
similarity index 100%
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/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-android23/libclang_rt.builtins.a b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android23/libclang_rt.builtins.a
new file mode 100644
index 000000000000000..e69de29bb2d1d64

diff  --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android29/libclang_rt.builtins.a b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android29/libclang_rt.builtins.a
new file mode 100644
index 000000000000000..e69de29bb2d1d64

diff  --git a/clang/test/Driver/android-installed-libcxx.cpp b/clang/test/Driver/android-installed-libcxx.cpp
index 4d139a1fb3693e6..14856e26e273074 100644
--- 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
index 000000000000000..c6c21d63fd41313
--- /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
index c5c871236044b27..8c721d82821f6ad 100644
--- 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 \


        


More information about the cfe-commits mailing list