Skip to content

Commit 58288c6

Browse files
committed
[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
1 parent 9a04bc4 commit 58288c6

File tree

11 files changed

+150
-13
lines changed

11 files changed

+150
-13
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,23 @@ X86 Support
341341
Arm and AArch64 Support
342342
^^^^^^^^^^^^^^^^^^^^^^^
343343

344+
Android Support
345+
^^^^^^^^^^^^^^^
346+
347+
- Android target triples are usually suffixed with a version. Clang searches for
348+
target-specific runtime and standard libraries in directories named after the
349+
target (e.g. if you're building with ``-target aarch64-none-linux-android21``,
350+
Clang will look for ``lib/aarch64-none-linux-android21`` under its resource
351+
directory to find runtime libraries). If an exact match isn't found, Clang
352+
would previously fall back to a directory without any version (which would be
353+
``lib/aarch64-none-linux-android`` in our example). Clang will now look for
354+
directories for lower versions and use the newest version it finds instead,
355+
e.g. if you have ``lib/aarch64-none-linux-android21`` and
356+
``lib/aarch64-none-linux-android29``, ``-target aarch64-none-linux-android23``
357+
will use the former and ``-target aarch64-none-linux-android30`` will use the
358+
latter. Falling back to a versionless directory will now emit a warning, and
359+
the fallback will be removed in Clang 19.
360+
344361
Windows Support
345362
^^^^^^^^^^^^^^^
346363
- Fixed an assertion failure that occurred due to a failure to propagate

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,4 +749,10 @@ def warn_drv_missing_multilib : Warning<
749749
InGroup<DiagGroup<"missing-multilib">>;
750750
def note_drv_available_multilibs : Note<
751751
"available multilibs are:%0">;
752+
753+
def warn_android_unversioned_fallback : Warning<
754+
"Using unversioned Android target directory %0 for target %1. Unversioned"
755+
" directories will not be used in Clang 19. Provide a versioned directory"
756+
" for the target version or lower instead.">,
757+
InGroup<DiagGroup<"android-unversioned-fallback">>;
752758
}

clang/include/clang/Driver/ToolChain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ class ToolChain {
182182
EffectiveTriple = std::move(ET);
183183
}
184184

185+
std::optional<std::string>
186+
getFallbackAndroidTargetPath(StringRef BaseDir) const;
187+
185188
mutable std::optional<CXXStdlibType> cxxStdlibType;
186189
mutable std::optional<RuntimeLibType> runtimeLibType;
187190
mutable std::optional<UnwindLibType> unwindLibType;

clang/lib/Driver/ToolChain.cpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,50 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
677677
return Args.MakeArgString(getCompilerRT(Args, Component, Type));
678678
}
679679

680+
// Android target triples contain a target version. If we don't have libraries
681+
// for the exact target version, we should fall back to the next newest version
682+
// or a versionless path, if any.
683+
std::optional<std::string>
684+
ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {
685+
llvm::Triple TripleWithoutLevel(getTriple());
686+
TripleWithoutLevel.setEnvironmentName("android"); // remove any version number
687+
const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();
688+
unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();
689+
unsigned BestVersion = 0;
690+
691+
SmallString<32> TripleDir;
692+
bool UsingUnversionedDir = false;
693+
std::error_code EC;
694+
for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;
695+
!EC && LI != LE; LI = LI.increment(EC)) {
696+
StringRef DirName = llvm::sys::path::filename(LI->path());
697+
StringRef DirNameSuffix = DirName;
698+
if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {
699+
if (DirNameSuffix.empty() && TripleDir.empty()) {
700+
TripleDir = DirName;
701+
UsingUnversionedDir = true;
702+
} else {
703+
unsigned Version;
704+
if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&
705+
Version < TripleVersion) {
706+
BestVersion = Version;
707+
TripleDir = DirName;
708+
UsingUnversionedDir = false;
709+
}
710+
}
711+
}
712+
}
713+
714+
if (TripleDir.empty())
715+
return {};
716+
717+
SmallString<128> P(BaseDir);
718+
llvm::sys::path::append(P, TripleDir);
719+
if (UsingUnversionedDir)
720+
D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();
721+
return std::string(P);
722+
}
723+
680724
std::optional<std::string>
681725
ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
682726
auto getPathForTriple =
@@ -713,15 +757,8 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
713757
return *Path;
714758
}
715759

716-
// Android targets may include an API level at the end. We still want to fall
717-
// back on a path without the API level.
718-
if (getTriple().isAndroid() &&
719-
getTriple().getEnvironmentName() != "android") {
720-
llvm::Triple TripleWithoutLevel = getTriple();
721-
TripleWithoutLevel.setEnvironmentName("android");
722-
if (auto Path = getPathForTriple(TripleWithoutLevel))
723-
return *Path;
724-
}
760+
if (getTriple().isAndroid())
761+
return getFallbackAndroidTargetPath(BaseDir);
725762

726763
return {};
727764
}

clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android23/libclang_rt.builtins.a

Whitespace-only changes.

clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android29/libclang_rt.builtins.a

Whitespace-only changes.

clang/test/Driver/android-installed-libcxx.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// RUN: mkdir -p %t2/include/c++/v1
1414
// RUN: mkdir -p %t2/sysroot
1515
// RUN: mkdir -p %t2/include/aarch64-none-linux-android/c++/v1
16+
// RUN: mkdir -p %t2/include/aarch64-none-linux-android23/c++/v1
1617

1718
// RUN: %clang -target aarch64-none-linux-android -ccc-install-dir %/t2/bin \
1819
// RUN: --sysroot=%t2/sysroot -stdlib=libc++ -fsyntax-only \
@@ -24,3 +25,14 @@
2425

2526
// ANDROID-DIR: "-internal-isystem" "[[DIR]][[SEP:/|\\\\]]..[[SEP]]include[[SEP]]aarch64-none-linux-android[[SEP]]c++[[SEP]]v1"
2627
// ANDROID-DIR-SAME: "-internal-isystem" "[[DIR]][[SEP]]..[[SEP]]include[[SEP]]c++[[SEP]]v1"
28+
29+
// RUN: %clang -target aarch64-none-linux-android23 -ccc-install-dir %/t2/bin \
30+
// RUN: --sysroot=%t2/sysroot -stdlib=libc++ -fsyntax-only \
31+
// RUN: %s -### 2>&1 | FileCheck --check-prefix=ANDROID23-DIR -DDIR=%/t2/bin %s
32+
33+
// RUN: %clang -target aarch64-none-linux-android28 -ccc-install-dir %/t2/bin \
34+
// RUN: --sysroot=%t2/sysroot -stdlib=libc++ -fsyntax-only \
35+
// RUN: %s -### 2>&1 | FileCheck --check-prefix=ANDROID23-DIR -DDIR=%/t2/bin %s
36+
37+
// ANDROID23-DIR: "-internal-isystem" "[[DIR]][[SEP:/|\\\\]]..[[SEP]]include[[SEP]]aarch64-none-linux-android23[[SEP]]c++[[SEP]]v1"
38+
// ANDROID23-DIR-SAME: "-internal-isystem" "[[DIR]][[SEP]]..[[SEP]]include[[SEP]]c++[[SEP]]v1"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Check that we emit warnings for using unversioned Android target directories
2+
// as appropriate.
3+
4+
// RUN: mkdir -p %t/bin
5+
// RUN: mkdir -p %t/include/aarch64-none-linux-android/c++/v1
6+
// RUN: mkdir -p %t/include/aarch64-none-linux-android23/c++/v1
7+
// RUN: mkdir -p %t/include/c++/v1
8+
// RUN: mkdir -p %t/lib/aarch64-none-linux-android
9+
// RUN: mkdir -p %t/lib/aarch64-none-linux-android23
10+
// RUN: mkdir -p %t/resource/lib/aarch64-none-linux-android
11+
// RUN: mkdir -p %t/resource/lib/aarch64-none-linux-android23
12+
13+
// Using an unversioned directory for an unversioned triple isn't a warning.
14+
// RUN: %clang -target aarch64-none-linux-android -ccc-install-dir %t/bin \
15+
// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \
16+
// RUN: FileCheck --check-prefix=NO-WARNING %s
17+
// NO-WARNING-NOT: Using unversioned Android target directory
18+
19+
// RUN: %clang -target aarch64-none-linux-android21 -ccc-install-dir %t/bin \
20+
// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \
21+
// RUN: FileCheck --check-prefix=ANDROID21 -DDIR=%t -DSEP=%{fs-sep} %s
22+
// ANDROID21-DAG: Using unversioned Android target directory [[DIR]]/bin[[SEP]]..[[SEP]]include[[SEP]]aarch64-none-linux-android
23+
// ANDROID21-DAG: Using unversioned Android target directory [[DIR]]/bin[[SEP]]..[[SEP]]lib[[SEP]]aarch64-none-linux-android
24+
// ANDROID21-DAG: Using unversioned Android target directory [[DIR]]/resource[[SEP]]lib[[SEP]]aarch64-none-linux-android
25+
26+
// 23 or newer should use the versioned directory
27+
// RUN: %clang -target aarch64-none-linux-android23 -ccc-install-dir %t/bin \
28+
// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \
29+
// RUN: FileCheck --check-prefix=NO-WARNING %s
30+
31+
// RUN: %clang -target aarch64-none-linux-android28 -ccc-install-dir %t/bin \
32+
// RUN: -resource-dir %t/resource -### -c %s 2>&1 | \
33+
// RUN: FileCheck --check-prefix=NO-WARNING %s

clang/test/Driver/linux-per-target-runtime-dir.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,25 @@
1717
// RUN: %clang --target=aarch64-unknown-linux-android21 -print-file-name=libc++.so 2>&1 \
1818
// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \
1919
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID21 %s
20-
// CHECK-LIBCXX-ANDROID21: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android21{{/|\\}}libc++.so
20+
// CHECK-LIBCXX-ANDROID21: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libc++.so
2121

2222
// RUN: %clang --target=aarch64-unknown-linux-android23 -print-file-name=libc++.so 2>&1 \
2323
// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \
2424
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID23 %s
25-
// CHECK-LIBCXX-ANDROID23: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libc++.so
25+
// CHECK-LIBCXX-ANDROID23: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android23{{/|\\}}libc++.so
26+
27+
// RUN: %clang --target=aarch64-unknown-linux-android26 -print-file-name=libc++.so 2>&1 \
28+
// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \
29+
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID23 %s
30+
31+
// RUN: %clang --target=aarch64-unknown-linux-android29 -print-file-name=libc++.so 2>&1 \
32+
// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \
33+
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID29 %s
34+
// CHECK-LIBCXX-ANDROID29: ..{{/|\\}}lib{{/|\\}}aarch64-unknown-linux-android29{{/|\\}}libc++.so
35+
36+
// RUN: %clang --target=aarch64-unknown-linux-android31 -print-file-name=libc++.so 2>&1 \
37+
// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \
38+
// RUN: | FileCheck --check-prefix=CHECK-LIBCXX-ANDROID29 %s
2639

2740
// RUN: %clang --target=aarch64-unknown-linux-android -print-file-name=libc++.so 2>&1 \
2841
// RUN: -ccc-install-dir %S/Inputs/basic_android_libcxx_tree/usr/bin \
@@ -45,13 +58,29 @@
4558
// RUN: --target=aarch64-unknown-linux-android21 \
4659
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
4760
// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID21 %s
48-
// CHECK-FILE-NAME-ANDROID21: lib{{/|\\}}aarch64-unknown-linux-android21{{/|\\}}libclang_rt.builtins.a
61+
// CHECK-FILE-NAME-ANDROID21: lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libclang_rt.builtins.a
4962

5063
// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \
5164
// RUN: --target=aarch64-unknown-linux-android23 \
5265
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
5366
// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID23 %s
54-
// CHECK-FILE-NAME-ANDROID23: lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libclang_rt.builtins.a
67+
// CHECK-FILE-NAME-ANDROID23: lib{{/|\\}}aarch64-unknown-linux-android23{{/|\\}}libclang_rt.builtins.a
68+
69+
// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \
70+
// RUN: --target=aarch64-unknown-linux-android26 \
71+
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
72+
// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID23 %s
73+
74+
// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \
75+
// RUN: --target=aarch64-unknown-linux-android29 \
76+
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
77+
// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID29 %s
78+
// CHECK-FILE-NAME-ANDROID29: lib{{/|\\}}aarch64-unknown-linux-android29{{/|\\}}libclang_rt.builtins.a
79+
80+
// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \
81+
// RUN: --target=aarch64-unknown-linux-android31 \
82+
// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
83+
// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID29 %s
5584

5685
// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \
5786
// RUN: --target=aarch64-unknown-linux-android \

0 commit comments

Comments
 (0)