Snap for 8564071 from 6890dd6e12e7206b0214e3c1178f3f852ec37437 to mainline-art-release

Change-Id: Ib94e15e610fb6fd7e8c070007a37d3e4c72fc6a8
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index b4474d7..ac25bc0 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "fae8e5e15f060bc1fb11c26eac168eaf8a50632b"
-  }
-}
+    "sha1": "8090d6853624a04b859e8ab2e467bae88a8d4ef6"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 993f360..5bd0a2a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,24 +15,17 @@
     strategy:
       matrix:
         os: [macos-latest, ubuntu-latest, windows-latest]
-        clang: [["11.0", "clang_11_0"]]
+        clang: [["13.0", "clang_13_0"]]
         rust: ["1.40.0"]
     steps:
       - name: Checkout Repository
         uses: actions/checkout@v2
       # LLVM and Clang
-      - name: Cache LLVM and Clang
-        id: cache-llvm
-        uses: actions/cache@v2
-        with:
-          path: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}
-          key: ${{ matrix.os }}-llvm-${{ matrix.clang[0] }}
       - name: Install LLVM and Clang
         uses: KyleMayes/install-llvm-action@v1
         with:
           version: ${{ matrix.clang[0] }}
           directory: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}
-          cached: ${{ steps.cache-llvm.outputs.cache-hit }}
       # Rust
       - name: Install Rust
         uses: actions-rs/toolchain@v1
@@ -41,17 +34,11 @@
       # Test
       - name: Cargo Test (Dynamic)
         uses: actions-rs/cargo@v1
-        env:
-          LIBCLANG_PATH: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}/lib
-          LLVM_CONFIG_PATH: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}/bin/llvm-config
         with:
           command: test
           args: --verbose --features ${{ matrix.clang[1] }} -- --nocapture
       - name: Cargo Test (Runtime)
         uses: actions-rs/cargo@v1
-        env:
-          LIBCLANG_PATH: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}/lib
-          LLVM_CONFIG_PATH: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}/bin/llvm-config
         with:
           command: test
           args: --verbose --features "${{ matrix.clang[1] }} runtime" -- --nocapture
diff --git a/.github/workflows/ssh.yml b/.github/workflows/ssh.yml
new file mode 100644
index 0000000..5dfc251
--- /dev/null
+++ b/.github/workflows/ssh.yml
@@ -0,0 +1,40 @@
+name: SSH
+
+on:
+  workflow_dispatch:
+    inputs:
+      os:
+        description: "Operating System"
+        required: true
+        default: "ubuntu-latest"
+
+jobs:
+  ssh:
+    name: SSH
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [macos-latest, ubuntu-latest, windows-latest]
+        clang: [["13.0", "clang_13_0"]]
+        rust: ["1.40.0"]
+    steps:
+      - name: Checkout Repository
+        uses: actions/checkout@v2
+        if: github.event.inputs.os == matrix.os
+      # LLVM and Clang
+      - name: Install LLVM and Clang
+        uses: KyleMayes/install-llvm-action@v1
+        if: github.event.inputs.os == matrix.os
+        with:
+          version: ${{ matrix.clang[0] }}
+          directory: ${{ runner.temp }}/llvm-${{ matrix.clang[0] }}
+      # Rust
+      - name: Install Rust
+        uses: actions-rs/toolchain@v1
+        if: github.event.inputs.os == matrix.os
+        with:
+          toolchain: ${{ matrix.rust }}
+      # SSH
+      - name: Enable SSH
+        uses: mxschmitt/action-tmate@v3
+        if: github.event.inputs.os == matrix.os
diff --git a/Android.bp b/Android.bp
index 52b841f..197c57a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --run --features=runtime,clang_10_0 --dependencies --copy-out.
+// This file is generated by cargo2android.py --config cargo2android.json.
 // Do not modify this file as changes will be overridden on upgrade.
 
 package {
@@ -31,6 +31,8 @@
 rust_library_host {
     name: "libclang_sys",
     crate_name: "clang_sys",
+    cargo_env_compat: true,
+    cargo_pkg_version: "1.3.1",
     srcs: [
         "src/lib.rs",
         ":copy_clang-sys_build_out",
@@ -58,9 +60,3 @@
         "liblibloading",
     ],
 }
-
-// dependent_library ["feature_list"]
-//   cfg-if-1.0.0
-//   glob-0.3.0
-//   libc-0.2.86
-//   libloading-0.7.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4940fa..681cde4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,45 @@
+## [1.3.1] - 2022-02-03
+
+### Added
+- Added missing `clang_getToken` function
+
+## [1.3.0] - 2021-10-31
+
+### Added
+- Added support for `clang` 13.0.x
+- Added support for `clang` 12.0.x
+- Added support for the Haiku operating system
+
+## [1.2.2] - 2021-09-02
+
+### Fixed
+- Fixed handling of paths that contain characters that have special meaning in
+glob patterns (e.g., `[` or `]`)
+
+## [1.2.1] - 2021-08-24
+
+### Changed
+- Updated build script to check the install location used by the
+[Scoop](https://scoop.sh/) command-line installer on Windows
+
+### Fixed
+- Updated build script to support environments where the `PATH` environment
+variable is not set
+
+## [1.2.0] - 2021-04-08
+
+### Changed
+- Changed `Clang::find` to prefer target-prefixed binaries when a `-target`
+argument is provided (e.g., if the arguments `-target` and
+`x86_64-unknown-linux-gnu` are provided, a target-prefixed Clang executable
+such as `x86_64-unknown-linux-gnu-clang` will be preferred over a non-target
+prefixed Clang executable)
+
+### Fixed
+- Fixed build script to split paths in environment variables (e.g.,
+`LD_LIBRARY_PATH`) using the appropriate separator for the platform (previously
+`:` was used as the separator but some platforms such as Windows use `;`)
+
 ## [1.1.1] - 2021-02-19
 
 ### Changed
diff --git a/Cargo.toml b/Cargo.toml
index ece1c66..3f4fe6d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,16 +3,15 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 name = "clang-sys"
-version = "1.1.1"
+version = "1.3.1"
 authors = ["Kyle Mayes <[email protected]>"]
 build = "build.rs"
 links = "clang"
@@ -22,7 +21,7 @@
 license = "Apache-2.0"
 repository = "https://github.com/KyleMayes/clang-sys"
 [package.metadata.docs.rs]
-features = ["clang_10_0", "runtime"]
+features = ["clang_13_0", "runtime"]
 [dependencies.glob]
 version = "0.3"
 
@@ -39,6 +38,8 @@
 [features]
 clang_10_0 = ["clang_9_0"]
 clang_11_0 = ["clang_10_0"]
+clang_12_0 = ["clang_11_0"]
+clang_13_0 = ["clang_12_0"]
 clang_3_5 = []
 clang_3_6 = ["clang_3_5"]
 clang_3_7 = ["clang_3_6"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index f7abf3c..a78a106 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -3,7 +3,7 @@
 name = "clang-sys"
 authors = ["Kyle Mayes <[email protected]>"]
 
-version = "1.1.1"
+version = "1.3.1"
 
 readme = "README.md"
 license = "Apache-2.0"
@@ -31,6 +31,8 @@
 clang_9_0 = ["clang_8_0"]
 clang_10_0 = ["clang_9_0"]
 clang_11_0 = ["clang_10_0"]
+clang_12_0 = ["clang_11_0"]
+clang_13_0 = ["clang_12_0"]
 
 runtime = ["libloading"]
 static = []
@@ -47,4 +49,4 @@
 
 [package.metadata.docs.rs]
 
-features = ["clang_10_0", "runtime"]
+features = ["clang_13_0", "runtime"]
diff --git a/METADATA b/METADATA
index 1262839..c8b71ff 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/clang-sys/clang-sys-1.1.1.crate"
+    value: "https://static.crates.io/crates/clang-sys/clang-sys-1.3.1.crate"
   }
-  version: "1.1.1"
+  version: "1.3.1"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 2
-    day: 22
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/README.md b/README.md
index dbee0ea..dd73945 100644
--- a/README.md
+++ b/README.md
@@ -2,76 +2,46 @@
 
 [![Crate](https://img.shields.io/crates/v/clang-sys.svg)](https://crates.io/crates/clang-sys)
 [![Documentation](https://docs.rs/clang-sys/badge.svg)](https://docs.rs/clang-sys)
-[![CI](https://github.com/KyleMayes/clang-sys/workflows/CI/badge.svg?branch=master)](https://github.com/KyleMayes/clang-sys/actions?query=workflow%3ACI)
+[![CI](https://img.shields.io/github/workflow/status/KyleMayes/clang-sys/CI/master)](https://github.com/KyleMayes/vulkanalia/actions?query=workflow%3ACI)
+![MSRV](https://img.shields.io/badge/MSRV-1.40.0-blue)
 
 Rust bindings for `libclang`.
 
-If you are interested in a Rust wrapper for these bindings, see
-[clang-rs](https://github.com/KyleMayes/clang-rs).
-
-Supported on the stable, beta, and nightly Rust channels.<br/>
-Minimum supported Rust version: **1.40.0**
+If you are interested in a somewhat idiomatic Rust wrapper for these bindings, see [`clang-rs`](https://github.com/KyleMayes/clang-rs).
 
 Released under the Apache License 2.0.
 
-## Documentation
+## [Documentation](https://docs.rs/clang-sys)
 
-There are two versions of the documentation, one for the API exposed when
-linking dynamically or statically and one for the API exposed when linking at
-runtime (see the
-[Dependencies](https://github.com/KyleMayes/clang-sys#dependencies) section
-of the README for more information on the linking options).
+Note that the documentation on https://docs.rs for this crate assumes usage of the `runtime` Cargo feature as well as the Cargo feature for the latest supported version of `libclang` (e.g., `clang_13_0`), neither of which are enabled by default.
 
-The only difference between the APIs exposed is that when linking at runtime a
-few additional types and functions are exposed to manage the loaded `libclang`
-shared library.
+Due to the usage of the `runtime` Cargo feature, this documentation will contain some additional types and functions to manage a dynamically loaded `libclang` instance at runtime.
 
-* Runtime - [Documentation](https://kylemayes.github.io/clang-sys/runtime/clang_sys)
-* Dynamic / Static - [Documentation](https://kylemayes.github.io/clang-sys/default/clang_sys)
+Due to the usage of the Cargo feature for the latest supported version of `libclang`, this documentation will contain constants and functions that are not available in the oldest supported version of `libclang` (3.5). All of these types and functions have a documentation comment which specifies the minimum `libclang` version required to use the item.
 
 ## Supported Versions
 
-To target a version of `libclang`, enable one of the following Cargo features:
+To target a version of `libclang`, enable a Cargo features such as one of the following:
 
 * `clang_3_5` - requires `libclang` 3.5 or later
 * `clang_3_6` - requires `libclang` 3.6 or later
-* `clang_3_7` - requires `libclang` 3.7 or later
-* `clang_3_8` - requires `libclang` 3.8 or later
-* `clang_3_9` - requires `libclang` 3.9 or later
-* `clang_4_0` - requires `libclang` 4.0 or later
-* `clang_5_0` - requires `libclang` 5.0 or later
-* `clang_6_0` - requires `libclang` 6.0 or later
-* `clang_7_0` - requires `libclang` 7.0 or later
-* `clang_8_0` - requires `libclang` 8.0 or later
-* `clang_9_0` - requires `libclang` 9.0 or later
-* `clang_10_0` - requires `libclang` 10.0 or later
-* `clang_11_0` - requires `libclang` 11.0 or later
+* etc...
+* `clang_12_0` - requires `libclang` 12.0 or later
+* `clang_13_0` - requires `libclang` 13.0 or later
 
-If you do not enable one of these features, the API provided by `libclang` 3.5 will be available by
-default.
+If you do not enable one of these features, the API provided by `libclang` 3.5 will be available by default.
 
 ## Dependencies
 
-By default, this crate will attempt to link to `libclang` dynamically. In this case, this crate
-depends on the `libclang` shared library (`libclang.so` on Linux, `libclang.dylib` on macOS,
-`libclang.dll` on Windows). If you want to link to `libclang` statically instead, enable the
-`static` Cargo feature. In this case, this crate depends on the LLVM and Clang static libraries. If
-you don't want to link to `libclang` at compiletime but instead want to load it at runtime, enable
-the `runtime` Cargo feature.
+By default, this crate will attempt to link to `libclang` dynamically. In this case, this crate depends on the `libclang` shared library (`libclang.so` on Linux, `libclang.dylib` on macOS, `libclang.dll` on Windows). If you want to link to `libclang` statically instead, enable the `static` Cargo feature. In this case, this crate depends on the LLVM and Clang static libraries. If you don't want to link to `libclang` at compiletime but instead want to load it at runtime, enable the `runtime` Cargo feature.
 
-These libraries can be either be installed as a part of Clang or downloaded
-[here](http://llvm.org/releases/download.html).
+These libraries can be either be installed as a part of Clang or downloaded [here](http://llvm.org/releases/download.html).
 
-**Note:** The downloads for LLVM and Clang 3.8 and later do not include the `libclang.a` static
-library. This means you cannot link to any of these versions of `libclang` statically unless you
-build it from source.
+**Note:** The downloads for LLVM and Clang 3.8 and later do not include the `libclang.a` static library. This means you cannot link to any of these versions of `libclang` statically unless you build it from source.
 
 ### Versioned Dependencies
 
-This crate supports finding versioned instances of `libclang.so` (e.g.,`libclang-3.9.so`).
-In the case where there are multiple instances to choose from, this crate will prefer instances with
-higher versions. For example, the following instances of `libclang.so` are listed in descending
-order of preference:
+This crate supports finding versioned instances of `libclang.so` (e.g.,`libclang-3.9.so`). In the case where there are multiple instances to choose from, this crate will prefer instances with higher versions. For example, the following instances of `libclang.so` are listed in descending order of preference:
 
 1. `libclang-4.0.so`
 2. `libclang-4.so`
@@ -79,23 +49,17 @@
 4. `libclang-3.so`
 5. `libclang.so`
 
-**Note:** On BSD distributions, versioned instances of `libclang.so` matching the pattern
-`libclang.so.*` (e.g., `libclang.so.7.0`) are also included.
+**Note:** On BSD distributions, versioned instances of `libclang.so` matching the pattern `libclang.so.*` (e.g., `libclang.so.7.0`) are also included.
 
-**Note:** On Linux distributions when the `runtime` features is enabled, versioned instances of
-`libclang.so` matching the pattern `libclang.so.*` (e.g., `libclang.so.1`) are also included.
+**Note:** On Linux distributions when the `runtime` features is enabled, versioned instances of `libclang.so` matching the pattern `libclang.so.*` (e.g., `libclang.so.1`) are also included.
 
 ## Environment Variables
 
-The following environment variables, if set, are used by this crate to find the required libraries
-and executables:
+The following environment variables, if set, are used by this crate to find the required libraries and executables:
 
-* `LLVM_CONFIG_PATH` **(compiletime)** - provides a full path to an `llvm-config` executable
-  (including the executable itself [i.e., `/usr/local/bin/llvm-config-8.0`])
-* `LIBCLANG_PATH` **(compiletime)** - provides a path to a directory containing a `libclang` shared
-  library or a full path to a specific `libclang` shared library
-* `LIBCLANG_STATIC_PATH` **(compiletime)** - provides a path to a directory containing LLVM and
-  Clang static libraries
+* `LLVM_CONFIG_PATH` **(compiletime)** - provides a full path to an `llvm-config` executable (including the executable itself [i.e., `/usr/local/bin/llvm-config-8.0`])
+* `LIBCLANG_PATH` **(compiletime)** - provides a path to a directory containing a `libclang` shared library or a full path to a specific `libclang` shared library
+* `LIBCLANG_STATIC_PATH` **(compiletime)** - provides a path to a directory containing LLVM and Clang static libraries
 * `CLANG_PATH` **(runtime)** - provides a path to a `clang` executable
 
 ## Linking
@@ -110,25 +74,14 @@
 * a list of likely directories for the target platform (e.g., `/usr/local/lib` on Linux)
 * **macOS only:** the toolchain directory in the directory provided by `xcode-select --print-path`
 
-On Linux, running an executable that has been dynamically linked to `libclang` may require you to
-add a path to `libclang.so` to the `LD_LIBRARY_PATH` environment variable. The same is true on OS
-X, except the `DYLD_LIBRARY_PATH` environment variable is used instead.
+On Linux, running an executable that has been dynamically linked to `libclang` may require you to add a path to `libclang.so` to the `LD_LIBRARY_PATH` environment variable. The same is true on OS X, except the `DYLD_LIBRARY_PATH` environment variable is used instead.
 
-On Windows, running an executable that has been dynamically linked to `libclang` requires that
-`libclang.dll` can be found by the executable at runtime. See
-[here](https://msdn.microsoft.com/en-us/library/7d83bc18.aspx) for more information.
+On Windows, running an executable that has been dynamically linked to `libclang` requires that `libclang.dll` can be found by the executable at runtime. See [here](https://msdn.microsoft.com/en-us/library/7d83bc18.aspx) for more information.
 
 ### Static
 
-The availability of `llvm-config` is not optional for static linking. Ensure that an instance of
-this executable can be found on your system's path or set the `LLVM_CONFIG_PATH` environment
-variable. The required LLVM and Clang static libraries will be searched for in the same way as
-shared libraries are searched for, except the `LIBCLANG_STATIC_PATH` environment variable is used in
-place of the `LIBCLANG_PATH` environment variable.
+The availability of `llvm-config` is not optional for static linking. Ensure that an instance of this executable can be found on your system's path or set the `LLVM_CONFIG_PATH` environment variable. The required LLVM and Clang static libraries will be searched for in the same way as shared libraries are searched for, except the `LIBCLANG_STATIC_PATH` environment variable is used in place of the `LIBCLANG_PATH` environment variable.
 
 ### Runtime
 
-The `clang_sys::load` function is used to load a `libclang` shared library for use in the thread in
-which it is called. The `clang_sys::unload` function will unload the `libclang` shared library.
-`clang_sys::load` searches for a `libclang` shared library in the same way one is searched for when
-linking to `libclang` dynamically at compiletime.
+The `clang_sys::load` function is used to load a `libclang` shared library for use in the thread in which it is called. The `clang_sys::unload` function will unload the `libclang` shared library. `clang_sys::load` searches for a `libclang` shared library in the same way one is searched for when linking to `libclang` dynamically at compiletime.
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 7de080a..e4ec3b3 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,11 +1,24 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
+  "imports": [
+    {
+      "path": "external/rust/crates/libsqlite3-sys"
+    }
+  ],
   "presubmit": [
     {
-      "name": "libsqlite3-sys_device_test_src_lib"
+      "name": "keystore2_test"
     },
     {
+      "name": "legacykeystore_test"
+    }
+  ],
+  "presubmit-rust": [
+    {
       "name": "keystore2_test"
+    },
+    {
+      "name": "legacykeystore_test"
     }
   ]
 }
diff --git a/build.rs b/build.rs
index cf5baa3..bfaaff6 100644
--- a/build.rs
+++ b/build.rs
@@ -1,23 +1,11 @@
-// Copyright 2016 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
-//! Finds `libclang` static or dynamic libraries and links to them.
+//! Finds `libclang` static or shared libraries and links to them.
 //!
 //! # Environment Variables
 //!
 //! This build script can make use of several environment variables to help it
-//! find the required static or dynamic libraries.
+//! find the required static or shared libraries.
 //!
 //! * `LLVM_CONFIG_PATH` - provides a path to an `llvm-config` executable
 //! * `LIBCLANG_PATH` - provides a path to a directory containing a `libclang`
@@ -36,9 +24,9 @@
 #[path = "build/dynamic.rs"]
 pub mod dynamic;
 #[path = "build/static.rs"]
-pub mod static_;
+pub mod r#static;
 
-/// Copy the file from the supplied source to the supplied destination.
+/// Copies a file.
 #[cfg(feature = "runtime")]
 fn copy(source: &str, destination: &Path) {
     use std::fs::File;
@@ -55,7 +43,8 @@
         .unwrap();
 }
 
-/// Generates the finding and linking code so that it may be used at runtime.
+/// Copies the code used to find and link to `libclang` shared libraries into
+/// the build output directory so that it may be used when linking at runtime.
 #[cfg(feature = "runtime")]
 fn main() {
     use std::env;
@@ -69,11 +58,11 @@
     copy("build/dynamic.rs", &Path::new(&out).join("dynamic.rs"));
 }
 
-/// Finds and links to the required libraries.
+/// Finds and links to the required libraries dynamically or statically.
 #[cfg(not(feature = "runtime"))]
 fn main() {
     if cfg!(feature = "static") {
-        static_::link();
+        r#static::link();
     } else {
         dynamic::link();
     }
diff --git a/build/common.rs b/build/common.rs
index 265a0cf..bc720ca 100644
--- a/build/common.rs
+++ b/build/common.rs
@@ -1,16 +1,4 @@
-// Copyright 2018 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 extern crate glob;
 
@@ -20,9 +8,138 @@
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use glob::MatchOptions;
+use glob::{MatchOptions, Pattern};
 
-/// `libclang` directory patterns for FreeBSD and Linux.
+//================================================
+// Commands
+//================================================
+
+thread_local! {
+    /// The errors encountered by the build script while executing commands.
+    static COMMAND_ERRORS: RefCell<HashMap<String, Vec<String>>> = RefCell::default();
+}
+
+/// Adds an error encountered by the build script while executing a command.
+fn add_command_error(name: &str, path: &str, arguments: &[&str], message: String) {
+    COMMAND_ERRORS.with(|e| {
+        e.borrow_mut()
+            .entry(name.into())
+            .or_insert_with(Vec::new)
+            .push(format!(
+                "couldn't execute `{} {}` (path={}) ({})",
+                name,
+                arguments.join(" "),
+                path,
+                message,
+            ))
+    });
+}
+
+/// A struct that prints the errors encountered by the build script while
+/// executing commands when dropped (unless explictly discarded).
+///
+/// This is handy because we only want to print these errors when the build
+/// script fails to link to an instance of `libclang`. For example, if
+/// `llvm-config` couldn't be executed but an instance of `libclang` was found
+/// anyway we don't want to pollute the build output with irrelevant errors.
+#[derive(Default)]
+pub struct CommandErrorPrinter {
+    discard: bool,
+}
+
+impl CommandErrorPrinter {
+    pub fn discard(mut self) {
+        self.discard = true;
+    }
+}
+
+impl Drop for CommandErrorPrinter {
+    fn drop(&mut self) {
+        if self.discard {
+            return;
+        }
+
+        let errors = COMMAND_ERRORS.with(|e| e.borrow().clone());
+
+        if let Some(errors) = errors.get("llvm-config") {
+            println!(
+                "cargo:warning=could not execute `llvm-config` one or more \
+                times, if the LLVM_CONFIG_PATH environment variable is set to \
+                a full path to valid `llvm-config` executable it will be used \
+                to try to find an instance of `libclang` on your system: {}",
+                errors
+                    .iter()
+                    .map(|e| format!("\"{}\"", e))
+                    .collect::<Vec<_>>()
+                    .join("\n  "),
+            )
+        }
+
+        if let Some(errors) = errors.get("xcode-select") {
+            println!(
+                "cargo:warning=could not execute `xcode-select` one or more \
+                times, if a valid instance of this executable is on your PATH \
+                it will be used to try to find an instance of `libclang` on \
+                your system: {}",
+                errors
+                    .iter()
+                    .map(|e| format!("\"{}\"", e))
+                    .collect::<Vec<_>>()
+                    .join("\n  "),
+            )
+        }
+    }
+}
+
+/// Executes a command and returns the `stdout` output if the command was
+/// successfully executed (errors are added to `COMMAND_ERRORS`).
+fn run_command(name: &str, path: &str, arguments: &[&str]) -> Option<String> {
+    let output = match Command::new(path).args(arguments).output() {
+        Ok(output) => output,
+        Err(error) => {
+            let message = format!("error: {}", error);
+            add_command_error(name, path, arguments, message);
+            return None;
+        }
+    };
+
+    if output.status.success() {
+        Some(String::from_utf8_lossy(&output.stdout).into_owned())
+    } else {
+        let message = format!("exit code: {}", output.status);
+        add_command_error(name, path, arguments, message);
+        None
+    }
+}
+
+/// Executes the `llvm-config` command and returns the `stdout` output if the
+/// command was successfully executed (errors are added to `COMMAND_ERRORS`).
+pub fn run_llvm_config(arguments: &[&str]) -> Option<String> {
+    let path = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".into());
+    run_command("llvm-config", &path, arguments)
+}
+
+/// Executes the `xcode-select` command and returns the `stdout` output if the
+/// command was successfully executed (errors are added to `COMMAND_ERRORS`).
+pub fn run_xcode_select(arguments: &[&str]) -> Option<String> {
+    run_command("xcode-select", "xcode-select", arguments)
+}
+
+//================================================
+// Search Directories
+//================================================
+
+/// `libclang` directory patterns for Haiku.
+const DIRECTORIES_HAIKU: &[&str] = &[
+    "/boot/system/lib",
+    "/boot/system/develop/lib",
+    "/boot/system/non-packaged/lib",
+    "/boot/system/non-packaged/develop/lib",
+    "/boot/home/config/non-packaged/lib",
+    "/boot/home/config/non-packaged/develop/lib",
+];
+
+/// `libclang` directory patterns for Linux (and FreeBSD).
 const DIRECTORIES_LINUX: &[&str] = &[
     "/usr/lib*",
     "/usr/lib*/*",
@@ -49,118 +166,42 @@
     // LLVM + Clang can be installed as a component of Visual Studio.
     // https://github.com/KyleMayes/clang-sys/issues/121
     "C:\\Program Files*\\Microsoft Visual Studio\\*\\BuildTools\\VC\\Tools\\Llvm\\**\\bin",
+    // LLVM + Clang can be installed using Scoop (https://scoop.sh).
+    // Other Windows package managers install LLVM + Clang to previously listed
+    // system-wide directories.
+    "C:\\Users\\*\\scoop\\apps\\llvm\\current\\bin",
 ];
 
-thread_local! {
-    /// The errors encountered when attempting to execute console commands.
-    static COMMAND_ERRORS: RefCell<HashMap<String, Vec<String>>> = RefCell::default();
-}
+//================================================
+// Searching
+//================================================
 
-/// Executes the supplied console command, returning the `stdout` output if the
-/// command was successfully executed.
-fn run_command(name: &str, command: &str, arguments: &[&str]) -> Option<String> {
-    macro_rules! error {
-        ($error:expr) => {{
-            COMMAND_ERRORS.with(|e| e.borrow_mut()
-                .entry(name.into())
-                .or_insert_with(Vec::new)
-                .push(format!(
-                    "couldn't execute `{} {}` ({})",
-                    command,
-                    arguments.join(" "),
-                    $error,
-                )));
-        }};
-    }
-
-    let output = match Command::new(command).args(arguments).output() {
-        Ok(output) => output,
-        Err(error) => {
-            error!(format!("error: {}", error));
-            return None;
-        }
-    };
-
-    if !output.status.success() {
-        error!(format!("exit code: {}", output.status));
-        return None;
-    }
-
-    Some(String::from_utf8_lossy(&output.stdout).into_owned())
-}
-
-/// Executes `llvm-config`, returning the `stdout` output if the command was
-/// successfully executed.
-pub fn run_llvm_config(arguments: &[&str]) -> Option<String> {
-    let path = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".into());
-    run_command("llvm-config", &path, arguments)
-}
-
-/// A struct that prints errors encountered when attempting to execute console
-/// commands on drop if not discarded.
-#[derive(Default)]
-pub struct CommandErrorPrinter {
-    discard: bool
-}
-
-impl CommandErrorPrinter {
-    pub fn discard(mut self) {
-        self.discard = true;
-    }
-}
-
-impl Drop for CommandErrorPrinter {
-    fn drop(&mut self) {
-        if self.discard {
-            return;
-        }
-
-        let errors = COMMAND_ERRORS.with(|e| e.borrow().clone());
-
-        if let Some(errors) = errors.get("llvm-config") {
-            println!(
-                "cargo:warning=could not execute `llvm-config` one or more \
-                times, if the LLVM_CONFIG_PATH environment variable is set to \
-                a full path to valid `llvm-config` executable it will be used \
-                to try to find an instance of `libclang` on your system: {}",
-                errors.iter().map(|e| format!("\"{}\"", e)).collect::<Vec<_>>().join("\n  "),
-            )
-        }
-
-        if let Some(errors) = errors.get("xcode-select") {
-            println!(
-                "cargo:warning=could not execute `xcode-select` one or more \
-                times, if a valid instance of this executable is on your PATH \
-                it will be used to try to find an instance of `libclang` on \
-                your system: {}",
-                errors.iter().map(|e| format!("\"{}\"", e)).collect::<Vec<_>>().join("\n  "),
-            )
-        }
-    }
-}
-
-/// Returns the paths to and the filenames of the files matching the supplied
-/// filename patterns in the supplied directory.
+/// Finds the files in a directory that match one or more filename glob patterns
+/// and returns the paths to and filenames of those files.
 fn search_directory(directory: &Path, filenames: &[String]) -> Vec<(PathBuf, String)> {
-    // Join the directory to the filename patterns to obtain the path patterns.
+    // Escape the specified directory in case it contains characters that have
+    // special meaning in glob patterns (e.g., `[` or `]`).
+    let directory = Pattern::escape(directory.to_str().unwrap());
+    let directory = Path::new(&directory);
+
+    // Join the escaped directory to the filename glob patterns to obtain
+    // complete glob patterns for the files being searched for.
     let paths = filenames
         .iter()
-        .filter_map(|f| directory.join(f).to_str().map(ToOwned::to_owned));
+        .map(|f| directory.join(f).to_str().unwrap().to_owned());
 
-    // Prevent wildcards from matching path separators.
+    // Prevent wildcards from matching path separators to ensure that the search
+    // is limited to the specified directory.
     let mut options = MatchOptions::new();
     options.require_literal_separator = true;
 
     paths
-        .flat_map(|p| {
-            if let Ok(paths) = glob::glob_with(&p, options) {
-                paths.filter_map(Result::ok).collect()
-            } else {
-                vec![]
-            }
-        })
+        .map(|p| glob::glob_with(&p, options))
+        .filter_map(Result::ok)
+        .flatten()
         .filter_map(|p| {
-            let filename = p.file_name().and_then(|f| f.to_str())?;
+            let path = p.ok()?;
+            let filename = path.file_name()?.to_str().unwrap();
 
             // The `libclang_shared` library has been renamed to `libclang-cpp`
             // in Clang 10. This can cause instances of this library (e.g.,
@@ -175,9 +216,9 @@
         .collect::<Vec<_>>()
 }
 
-/// Returns the paths to and the filenames of the files matching the supplied
-/// filename patterns in the supplied directory, checking any relevant sibling
-/// directories.
+/// Finds the files in a directory (and any relevant sibling directories) that
+/// match one or more filename glob patterns and returns the paths to and
+/// filenames of those files.
 fn search_directories(directory: &Path, filenames: &[String]) -> Vec<(PathBuf, String)> {
     let mut results = search_directory(directory, filenames);
 
@@ -194,54 +235,57 @@
     results
 }
 
-/// Returns the paths to and the filenames of the `libclang` static or dynamic
-/// libraries matching the supplied filename patterns.
-pub fn search_libclang_directories(files: &[String], variable: &str) -> Vec<(PathBuf, String)> {
-    // Use the path provided by the relevant environment variable.
+/// Finds the `libclang` static or dynamic libraries matching one or more
+/// filename glob patterns and returns the paths to and filenames of those files.
+pub fn search_libclang_directories(filenames: &[String], variable: &str) -> Vec<(PathBuf, String)> {
+    // Search only the path indicated by the relevant environment variable
+    // (e.g., `LIBCLANG_PATH`) if it is set.
     if let Ok(path) = env::var(variable).map(|d| Path::new(&d).to_path_buf()) {
-        // Check if the path is referring to a matching file already.
+        // Check if the path is a matching file.
         if let Some(parent) = path.parent() {
             let filename = path.file_name().unwrap().to_str().unwrap();
-            let libraries = search_directories(parent, files);
+            let libraries = search_directories(parent, filenames);
             if libraries.iter().any(|(_, f)| f == filename) {
                 return vec![(parent.into(), filename.into())];
             }
         }
 
-        return search_directories(&path, files);
+        // Check if the path is directory containing a matching file.
+        return search_directories(&path, filenames);
     }
 
     let mut found = vec![];
 
-    // Search the `bin` and `lib` directories in directory provided by
+    // Search the `bin` and `lib` directories in the directory returned by
     // `llvm-config --prefix`.
     if let Some(output) = run_llvm_config(&["--prefix"]) {
         let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
-        found.extend(search_directories(&directory.join("bin"), files));
-        found.extend(search_directories(&directory.join("lib"), files));
-        found.extend(search_directories(&directory.join("lib64"), files));
+        found.extend(search_directories(&directory.join("bin"), filenames));
+        found.extend(search_directories(&directory.join("lib"), filenames));
+        found.extend(search_directories(&directory.join("lib64"), filenames));
     }
 
-    // Search the toolchain directory in the directory provided by
+    // Search the toolchain directory in the directory returned by
     // `xcode-select --print-path`.
     if cfg!(target_os = "macos") {
-        if let Some(output) = run_command("xcode-select", "xcode-select", &["--print-path"]) {
+        if let Some(output) = run_xcode_select(&["--print-path"]) {
             let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
             let directory = directory.join("Toolchains/XcodeDefault.xctoolchain/usr/lib");
-            found.extend(search_directories(&directory, files));
+            found.extend(search_directories(&directory, filenames));
         }
     }
 
-    // Search the directories provided by the `LD_LIBRARY_PATH` environment
-    // variable.
+    // Search the directories in the `LD_LIBRARY_PATH` environment variable.
     if let Ok(path) = env::var("LD_LIBRARY_PATH") {
-        for directory in path.split(':').map(Path::new) {
-            found.extend(search_directories(&directory, files));
+        for directory in env::split_paths(&path) {
+            found.extend(search_directories(&directory, filenames));
         }
     }
 
     // Determine the `libclang` directory patterns.
-    let directories = if cfg!(any(target_os = "freebsd", target_os = "linux")) {
+    let directories = if cfg!(target_os = "haiku") {
+        DIRECTORIES_HAIKU
+    } else if cfg!(any(target_os = "linux", target_os = "freebsd")) {
         DIRECTORIES_LINUX
     } else if cfg!(target_os = "macos") {
         DIRECTORIES_MACOS
@@ -258,7 +302,7 @@
     for directory in directories.iter().rev() {
         if let Ok(directories) = glob::glob_with(directory, options) {
             for directory in directories.filter_map(Result::ok).filter(|p| p.is_dir()) {
-                found.extend(search_directories(&directory, files));
+                found.extend(search_directories(&directory, filenames));
             }
         }
     }
diff --git a/build/dynamic.rs b/build/dynamic.rs
index c15973c..39247c8 100644
--- a/build/dynamic.rs
+++ b/build/dynamic.rs
@@ -1,16 +1,4 @@
-// Copyright 2018 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 use std::env;
 use std::fs::File;
@@ -19,7 +7,11 @@
 
 use super::common;
 
-/// Returns the ELF class from the ELF header in the supplied file.
+//================================================
+// Validation
+//================================================
+
+/// Extracts the ELF class from the ELF header in a shared library.
 fn parse_elf_header(path: &Path) -> io::Result<u8> {
     let mut file = File::open(path)?;
     let mut buffer = [0; 5];
@@ -31,34 +23,34 @@
     }
 }
 
-/// Returns the magic number from the PE header in the supplied file.
+/// Extracts the magic number from the PE header in a shared library.
 fn parse_pe_header(path: &Path) -> io::Result<u16> {
     let mut file = File::open(path)?;
 
-    // Determine the header offset.
+    // Extract the header offset.
     let mut buffer = [0; 4];
     let start = SeekFrom::Start(0x3C);
     file.seek(start)?;
     file.read_exact(&mut buffer)?;
     let offset = i32::from_le_bytes(buffer);
 
-    // Determine the validity of the header.
+    // Check the validity of the header.
     file.seek(SeekFrom::Start(offset as u64))?;
     file.read_exact(&mut buffer)?;
     if buffer != [80, 69, 0, 0] {
         return Err(Error::new(ErrorKind::InvalidData, "invalid PE header"));
     }
 
-    // Find the magic number.
+    // Extract the magic number.
     let mut buffer = [0; 2];
     file.seek(SeekFrom::Current(20))?;
     file.read_exact(&mut buffer)?;
     Ok(u16::from_le_bytes(buffer))
 }
 
-/// Validates the header for the supplied `libclang` shared library.
-fn validate_header(path: &Path) -> Result<(), String> {
-    if cfg!(any(target_os = "freebsd", target_os = "linux")) {
+/// Checks that a `libclang` shared library matches the target platform.
+fn validate_library(path: &Path) -> Result<(), String> {
+    if cfg!(any(target_os = "linux", target_os = "freebsd")) {
         let class = parse_elf_header(path).map_err(|e| e.to_string())?;
 
         if cfg!(target_pointer_width = "32") && class != 1 {
@@ -87,11 +79,14 @@
     }
 }
 
-/// Returns the components of the version in the supplied `libclang` shared
-// library filename.
+//================================================
+// Searching
+//================================================
+
+/// Extracts the version components in a `libclang` shared library filename.
 fn parse_version(filename: &str) -> Vec<u32> {
-    let version = if filename.starts_with("libclang.so.") {
-        &filename[12..]
+    let version = if let Some(version) = filename.strip_prefix("libclang.so.") {
+        version
     } else if filename.starts_with("libclang-") {
         &filename[9..filename.len() - 3]
     } else {
@@ -101,8 +96,8 @@
     version.split('.').map(|s| s.parse().unwrap_or(0)).collect()
 }
 
-/// Returns the paths to, the filenames, and the versions of the `libclang`
-// shared libraries.
+/// Finds `libclang` shared libraries and returns the paths to, filenames of,
+/// and versions of those shared libraries.
 fn search_libclang_directories(runtime: bool) -> Result<Vec<(PathBuf, String, Vec<u32>)>, String> {
     let mut files = vec![format!(
         "{}clang{}",
@@ -127,9 +122,10 @@
     }
 
     if cfg!(any(
-        target_os = "openbsd",
         target_os = "freebsd",
-        target_os = "netbsd"
+        target_os = "haiku",
+        target_os = "netbsd",
+        target_os = "openbsd",
     )) {
         // Some BSD distributions don't create a `libclang.so` symlink either,
         // but use a different naming scheme for versioned files (e.g.,
@@ -143,12 +139,12 @@
         files.push("libclang.dll".into());
     }
 
-    // Validate the `libclang` shared libraries and collect the versions.
+    // Find and validate `libclang` shared libraries and collect the versions.
     let mut valid = vec![];
     let mut invalid = vec![];
     for (directory, filename) in common::search_libclang_directories(&files, "LIBCLANG_PATH") {
         let path = directory.join(&filename);
-        match validate_header(&path) {
+        match validate_library(&path) {
             Ok(()) => {
                 let version = parse_version(&filename);
                 valid.push((directory, filename, version))
@@ -176,8 +172,8 @@
     Err(message)
 }
 
-/// Returns the directory and filename of the "best" available `libclang` shared
-/// library.
+/// Finds the "best" `libclang` shared library and returns the directory and
+/// filename of that library.
 pub fn find(runtime: bool) -> Result<(PathBuf, String), String> {
     search_libclang_directories(runtime)?
         .iter()
@@ -201,7 +197,11 @@
         .ok_or_else(|| "unreachable".into())
 }
 
-/// Find and link to `libclang` dynamically.
+//================================================
+// Linking
+//================================================
+
+/// Finds and links to a `libclang` shared library.
 #[cfg(not(feature = "runtime"))]
 pub fn link() {
     let cep = common::CommandErrorPrinter::default();
@@ -252,7 +252,7 @@
         // `libclang.so.7.0`).
         let name = match name.find(".dylib").or_else(|| name.find(".so")) {
             Some(index) => &name[0..index],
-            None => &name,
+            None => name,
         };
 
         println!("cargo:rustc-link-lib=dylib={}", name);
diff --git a/build/static.rs b/build/static.rs
index 83a8185..6af914f 100644
--- a/build/static.rs
+++ b/build/static.rs
@@ -1,54 +1,18 @@
-// Copyright 2018 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 extern crate glob;
 
 use std::path::{Path, PathBuf};
 
+use glob::Pattern;
+
 use common;
 
-/// Returns the name of an LLVM or Clang library from a path to such a library.
-fn get_library_name(path: &Path) -> Option<String> {
-    path.file_stem().map(|p| {
-        let string = p.to_string_lossy();
-        if string.starts_with("lib") {
-            string[3..].to_owned()
-        } else {
-            string.to_string()
-        }
-    })
-}
+//================================================
+// Searching
+//================================================
 
-/// Returns the LLVM libraries required to link to `libclang` statically.
-fn get_llvm_libraries() -> Vec<String> {
-    common::run_llvm_config(&["--libs"])
-        .unwrap()
-        .split_whitespace()
-        .filter_map(|p| {
-            // Depending on the version of `llvm-config` in use, listed
-            // libraries may be in one of two forms, a full path to the library
-            // or simply prefixed with `-l`.
-            if p.starts_with("-l") {
-                Some(p[2..].into())
-            } else {
-                get_library_name(Path::new(p))
-            }
-        })
-        .collect()
-}
-
-/// Clang libraries required to link to `libclang` 3.5 and later statically.
+/// Clang static libraries required to link to `libclang` 3.5 and later.
 const CLANG_LIBRARIES: &[&str] = &[
     "clang",
     "clangAST",
@@ -65,13 +29,44 @@
     "clangSerialization",
 ];
 
-/// Returns the Clang libraries required to link to `libclang` statically.
+/// Gets the name of an LLVM or Clang static library from a path.
+fn get_library_name(path: &Path) -> Option<String> {
+    path.file_stem().map(|p| {
+        let string = p.to_string_lossy();
+        if let Some(name) = string.strip_prefix("lib") {
+            name.to_owned()
+        } else {
+            string.to_string()
+        }
+    })
+}
+
+/// Gets the LLVM static libraries required to link to `libclang`.
+fn get_llvm_libraries() -> Vec<String> {
+    common::run_llvm_config(&["--libs"])
+        .unwrap()
+        .split_whitespace()
+        .filter_map(|p| {
+            // Depending on the version of `llvm-config` in use, listed
+            // libraries may be in one of two forms, a full path to the library
+            // or simply prefixed with `-l`.
+            if let Some(path) = p.strip_prefix("-l") {
+                Some(path.into())
+            } else {
+                get_library_name(Path::new(p))
+            }
+        })
+        .collect()
+}
+
+/// Gets the Clang static libraries required to link to `libclang`.
 fn get_clang_libraries<P: AsRef<Path>>(directory: P) -> Vec<String> {
-    let pattern = directory
-        .as_ref()
-        .join("libclang*.a")
-        .to_string_lossy()
-        .to_string();
+    // Escape the directory in case it contains characters that have special
+    // meaning in glob patterns (e.g., `[` or `]`).
+    let directory = Pattern::escape(directory.as_ref().to_str().unwrap());
+    let directory = Path::new(&directory);
+
+    let pattern = directory.join("libclang*.a").to_str().unwrap().to_owned();
     if let Ok(libraries) = glob::glob(&pattern) {
         libraries
             .filter_map(|l| l.ok().and_then(|l| get_library_name(&l)))
@@ -81,7 +76,8 @@
     }
 }
 
-/// Returns a directory containing `libclang` static libraries.
+/// Finds a directory containing LLVM and Clang static libraries and returns the
+/// path to that directory.
 fn find() -> PathBuf {
     let name = if cfg!(target_os = "windows") {
         "libclang.lib"
@@ -97,7 +93,11 @@
     }
 }
 
-/// Find and link to `libclang` statically.
+//================================================
+// Linking
+//================================================
+
+/// Finds and links to `libclang` static libraries.
 pub fn link() {
     let cep = common::CommandErrorPrinter::default();
 
@@ -130,7 +130,7 @@
     // MSVC doesn't need this, as it tracks dependencies inside `.lib` files.
     if cfg!(target_os = "freebsd") {
         println!("cargo:rustc-flags=-l ffi -l ncursesw -l c++ -l z");
-    } else if cfg!(target_os = "linux") {
+    } else if cfg!(any(target_os = "haiku", target_os = "linux")) {
         println!("cargo:rustc-flags=-l ffi -l ncursesw -l stdc++ -l z");
     } else if cfg!(target_os = "macos") {
         println!("cargo:rustc-flags=-l ffi -l ncurses -l c++ -l z");
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..a0f1a8e
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,5 @@
+{
+  "copy-out": true,
+  "features": "runtime,clang_10_0",
+  "run": true
+}
\ No newline at end of file
diff --git a/out/common.rs b/out/common.rs
index 265a0cf..bc720ca 100644
--- a/out/common.rs
+++ b/out/common.rs
@@ -1,16 +1,4 @@
-// Copyright 2018 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 extern crate glob;
 
@@ -20,9 +8,138 @@
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use glob::MatchOptions;
+use glob::{MatchOptions, Pattern};
 
-/// `libclang` directory patterns for FreeBSD and Linux.
+//================================================
+// Commands
+//================================================
+
+thread_local! {
+    /// The errors encountered by the build script while executing commands.
+    static COMMAND_ERRORS: RefCell<HashMap<String, Vec<String>>> = RefCell::default();
+}
+
+/// Adds an error encountered by the build script while executing a command.
+fn add_command_error(name: &str, path: &str, arguments: &[&str], message: String) {
+    COMMAND_ERRORS.with(|e| {
+        e.borrow_mut()
+            .entry(name.into())
+            .or_insert_with(Vec::new)
+            .push(format!(
+                "couldn't execute `{} {}` (path={}) ({})",
+                name,
+                arguments.join(" "),
+                path,
+                message,
+            ))
+    });
+}
+
+/// A struct that prints the errors encountered by the build script while
+/// executing commands when dropped (unless explictly discarded).
+///
+/// This is handy because we only want to print these errors when the build
+/// script fails to link to an instance of `libclang`. For example, if
+/// `llvm-config` couldn't be executed but an instance of `libclang` was found
+/// anyway we don't want to pollute the build output with irrelevant errors.
+#[derive(Default)]
+pub struct CommandErrorPrinter {
+    discard: bool,
+}
+
+impl CommandErrorPrinter {
+    pub fn discard(mut self) {
+        self.discard = true;
+    }
+}
+
+impl Drop for CommandErrorPrinter {
+    fn drop(&mut self) {
+        if self.discard {
+            return;
+        }
+
+        let errors = COMMAND_ERRORS.with(|e| e.borrow().clone());
+
+        if let Some(errors) = errors.get("llvm-config") {
+            println!(
+                "cargo:warning=could not execute `llvm-config` one or more \
+                times, if the LLVM_CONFIG_PATH environment variable is set to \
+                a full path to valid `llvm-config` executable it will be used \
+                to try to find an instance of `libclang` on your system: {}",
+                errors
+                    .iter()
+                    .map(|e| format!("\"{}\"", e))
+                    .collect::<Vec<_>>()
+                    .join("\n  "),
+            )
+        }
+
+        if let Some(errors) = errors.get("xcode-select") {
+            println!(
+                "cargo:warning=could not execute `xcode-select` one or more \
+                times, if a valid instance of this executable is on your PATH \
+                it will be used to try to find an instance of `libclang` on \
+                your system: {}",
+                errors
+                    .iter()
+                    .map(|e| format!("\"{}\"", e))
+                    .collect::<Vec<_>>()
+                    .join("\n  "),
+            )
+        }
+    }
+}
+
+/// Executes a command and returns the `stdout` output if the command was
+/// successfully executed (errors are added to `COMMAND_ERRORS`).
+fn run_command(name: &str, path: &str, arguments: &[&str]) -> Option<String> {
+    let output = match Command::new(path).args(arguments).output() {
+        Ok(output) => output,
+        Err(error) => {
+            let message = format!("error: {}", error);
+            add_command_error(name, path, arguments, message);
+            return None;
+        }
+    };
+
+    if output.status.success() {
+        Some(String::from_utf8_lossy(&output.stdout).into_owned())
+    } else {
+        let message = format!("exit code: {}", output.status);
+        add_command_error(name, path, arguments, message);
+        None
+    }
+}
+
+/// Executes the `llvm-config` command and returns the `stdout` output if the
+/// command was successfully executed (errors are added to `COMMAND_ERRORS`).
+pub fn run_llvm_config(arguments: &[&str]) -> Option<String> {
+    let path = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".into());
+    run_command("llvm-config", &path, arguments)
+}
+
+/// Executes the `xcode-select` command and returns the `stdout` output if the
+/// command was successfully executed (errors are added to `COMMAND_ERRORS`).
+pub fn run_xcode_select(arguments: &[&str]) -> Option<String> {
+    run_command("xcode-select", "xcode-select", arguments)
+}
+
+//================================================
+// Search Directories
+//================================================
+
+/// `libclang` directory patterns for Haiku.
+const DIRECTORIES_HAIKU: &[&str] = &[
+    "/boot/system/lib",
+    "/boot/system/develop/lib",
+    "/boot/system/non-packaged/lib",
+    "/boot/system/non-packaged/develop/lib",
+    "/boot/home/config/non-packaged/lib",
+    "/boot/home/config/non-packaged/develop/lib",
+];
+
+/// `libclang` directory patterns for Linux (and FreeBSD).
 const DIRECTORIES_LINUX: &[&str] = &[
     "/usr/lib*",
     "/usr/lib*/*",
@@ -49,118 +166,42 @@
     // LLVM + Clang can be installed as a component of Visual Studio.
     // https://github.com/KyleMayes/clang-sys/issues/121
     "C:\\Program Files*\\Microsoft Visual Studio\\*\\BuildTools\\VC\\Tools\\Llvm\\**\\bin",
+    // LLVM + Clang can be installed using Scoop (https://scoop.sh).
+    // Other Windows package managers install LLVM + Clang to previously listed
+    // system-wide directories.
+    "C:\\Users\\*\\scoop\\apps\\llvm\\current\\bin",
 ];
 
-thread_local! {
-    /// The errors encountered when attempting to execute console commands.
-    static COMMAND_ERRORS: RefCell<HashMap<String, Vec<String>>> = RefCell::default();
-}
+//================================================
+// Searching
+//================================================
 
-/// Executes the supplied console command, returning the `stdout` output if the
-/// command was successfully executed.
-fn run_command(name: &str, command: &str, arguments: &[&str]) -> Option<String> {
-    macro_rules! error {
-        ($error:expr) => {{
-            COMMAND_ERRORS.with(|e| e.borrow_mut()
-                .entry(name.into())
-                .or_insert_with(Vec::new)
-                .push(format!(
-                    "couldn't execute `{} {}` ({})",
-                    command,
-                    arguments.join(" "),
-                    $error,
-                )));
-        }};
-    }
-
-    let output = match Command::new(command).args(arguments).output() {
-        Ok(output) => output,
-        Err(error) => {
-            error!(format!("error: {}", error));
-            return None;
-        }
-    };
-
-    if !output.status.success() {
-        error!(format!("exit code: {}", output.status));
-        return None;
-    }
-
-    Some(String::from_utf8_lossy(&output.stdout).into_owned())
-}
-
-/// Executes `llvm-config`, returning the `stdout` output if the command was
-/// successfully executed.
-pub fn run_llvm_config(arguments: &[&str]) -> Option<String> {
-    let path = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".into());
-    run_command("llvm-config", &path, arguments)
-}
-
-/// A struct that prints errors encountered when attempting to execute console
-/// commands on drop if not discarded.
-#[derive(Default)]
-pub struct CommandErrorPrinter {
-    discard: bool
-}
-
-impl CommandErrorPrinter {
-    pub fn discard(mut self) {
-        self.discard = true;
-    }
-}
-
-impl Drop for CommandErrorPrinter {
-    fn drop(&mut self) {
-        if self.discard {
-            return;
-        }
-
-        let errors = COMMAND_ERRORS.with(|e| e.borrow().clone());
-
-        if let Some(errors) = errors.get("llvm-config") {
-            println!(
-                "cargo:warning=could not execute `llvm-config` one or more \
-                times, if the LLVM_CONFIG_PATH environment variable is set to \
-                a full path to valid `llvm-config` executable it will be used \
-                to try to find an instance of `libclang` on your system: {}",
-                errors.iter().map(|e| format!("\"{}\"", e)).collect::<Vec<_>>().join("\n  "),
-            )
-        }
-
-        if let Some(errors) = errors.get("xcode-select") {
-            println!(
-                "cargo:warning=could not execute `xcode-select` one or more \
-                times, if a valid instance of this executable is on your PATH \
-                it will be used to try to find an instance of `libclang` on \
-                your system: {}",
-                errors.iter().map(|e| format!("\"{}\"", e)).collect::<Vec<_>>().join("\n  "),
-            )
-        }
-    }
-}
-
-/// Returns the paths to and the filenames of the files matching the supplied
-/// filename patterns in the supplied directory.
+/// Finds the files in a directory that match one or more filename glob patterns
+/// and returns the paths to and filenames of those files.
 fn search_directory(directory: &Path, filenames: &[String]) -> Vec<(PathBuf, String)> {
-    // Join the directory to the filename patterns to obtain the path patterns.
+    // Escape the specified directory in case it contains characters that have
+    // special meaning in glob patterns (e.g., `[` or `]`).
+    let directory = Pattern::escape(directory.to_str().unwrap());
+    let directory = Path::new(&directory);
+
+    // Join the escaped directory to the filename glob patterns to obtain
+    // complete glob patterns for the files being searched for.
     let paths = filenames
         .iter()
-        .filter_map(|f| directory.join(f).to_str().map(ToOwned::to_owned));
+        .map(|f| directory.join(f).to_str().unwrap().to_owned());
 
-    // Prevent wildcards from matching path separators.
+    // Prevent wildcards from matching path separators to ensure that the search
+    // is limited to the specified directory.
     let mut options = MatchOptions::new();
     options.require_literal_separator = true;
 
     paths
-        .flat_map(|p| {
-            if let Ok(paths) = glob::glob_with(&p, options) {
-                paths.filter_map(Result::ok).collect()
-            } else {
-                vec![]
-            }
-        })
+        .map(|p| glob::glob_with(&p, options))
+        .filter_map(Result::ok)
+        .flatten()
         .filter_map(|p| {
-            let filename = p.file_name().and_then(|f| f.to_str())?;
+            let path = p.ok()?;
+            let filename = path.file_name()?.to_str().unwrap();
 
             // The `libclang_shared` library has been renamed to `libclang-cpp`
             // in Clang 10. This can cause instances of this library (e.g.,
@@ -175,9 +216,9 @@
         .collect::<Vec<_>>()
 }
 
-/// Returns the paths to and the filenames of the files matching the supplied
-/// filename patterns in the supplied directory, checking any relevant sibling
-/// directories.
+/// Finds the files in a directory (and any relevant sibling directories) that
+/// match one or more filename glob patterns and returns the paths to and
+/// filenames of those files.
 fn search_directories(directory: &Path, filenames: &[String]) -> Vec<(PathBuf, String)> {
     let mut results = search_directory(directory, filenames);
 
@@ -194,54 +235,57 @@
     results
 }
 
-/// Returns the paths to and the filenames of the `libclang` static or dynamic
-/// libraries matching the supplied filename patterns.
-pub fn search_libclang_directories(files: &[String], variable: &str) -> Vec<(PathBuf, String)> {
-    // Use the path provided by the relevant environment variable.
+/// Finds the `libclang` static or dynamic libraries matching one or more
+/// filename glob patterns and returns the paths to and filenames of those files.
+pub fn search_libclang_directories(filenames: &[String], variable: &str) -> Vec<(PathBuf, String)> {
+    // Search only the path indicated by the relevant environment variable
+    // (e.g., `LIBCLANG_PATH`) if it is set.
     if let Ok(path) = env::var(variable).map(|d| Path::new(&d).to_path_buf()) {
-        // Check if the path is referring to a matching file already.
+        // Check if the path is a matching file.
         if let Some(parent) = path.parent() {
             let filename = path.file_name().unwrap().to_str().unwrap();
-            let libraries = search_directories(parent, files);
+            let libraries = search_directories(parent, filenames);
             if libraries.iter().any(|(_, f)| f == filename) {
                 return vec![(parent.into(), filename.into())];
             }
         }
 
-        return search_directories(&path, files);
+        // Check if the path is directory containing a matching file.
+        return search_directories(&path, filenames);
     }
 
     let mut found = vec![];
 
-    // Search the `bin` and `lib` directories in directory provided by
+    // Search the `bin` and `lib` directories in the directory returned by
     // `llvm-config --prefix`.
     if let Some(output) = run_llvm_config(&["--prefix"]) {
         let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
-        found.extend(search_directories(&directory.join("bin"), files));
-        found.extend(search_directories(&directory.join("lib"), files));
-        found.extend(search_directories(&directory.join("lib64"), files));
+        found.extend(search_directories(&directory.join("bin"), filenames));
+        found.extend(search_directories(&directory.join("lib"), filenames));
+        found.extend(search_directories(&directory.join("lib64"), filenames));
     }
 
-    // Search the toolchain directory in the directory provided by
+    // Search the toolchain directory in the directory returned by
     // `xcode-select --print-path`.
     if cfg!(target_os = "macos") {
-        if let Some(output) = run_command("xcode-select", "xcode-select", &["--print-path"]) {
+        if let Some(output) = run_xcode_select(&["--print-path"]) {
             let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
             let directory = directory.join("Toolchains/XcodeDefault.xctoolchain/usr/lib");
-            found.extend(search_directories(&directory, files));
+            found.extend(search_directories(&directory, filenames));
         }
     }
 
-    // Search the directories provided by the `LD_LIBRARY_PATH` environment
-    // variable.
+    // Search the directories in the `LD_LIBRARY_PATH` environment variable.
     if let Ok(path) = env::var("LD_LIBRARY_PATH") {
-        for directory in path.split(':').map(Path::new) {
-            found.extend(search_directories(&directory, files));
+        for directory in env::split_paths(&path) {
+            found.extend(search_directories(&directory, filenames));
         }
     }
 
     // Determine the `libclang` directory patterns.
-    let directories = if cfg!(any(target_os = "freebsd", target_os = "linux")) {
+    let directories = if cfg!(target_os = "haiku") {
+        DIRECTORIES_HAIKU
+    } else if cfg!(any(target_os = "linux", target_os = "freebsd")) {
         DIRECTORIES_LINUX
     } else if cfg!(target_os = "macos") {
         DIRECTORIES_MACOS
@@ -258,7 +302,7 @@
     for directory in directories.iter().rev() {
         if let Ok(directories) = glob::glob_with(directory, options) {
             for directory in directories.filter_map(Result::ok).filter(|p| p.is_dir()) {
-                found.extend(search_directories(&directory, files));
+                found.extend(search_directories(&directory, filenames));
             }
         }
     }
diff --git a/out/dynamic.rs b/out/dynamic.rs
index c15973c..39247c8 100644
--- a/out/dynamic.rs
+++ b/out/dynamic.rs
@@ -1,16 +1,4 @@
-// Copyright 2018 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 use std::env;
 use std::fs::File;
@@ -19,7 +7,11 @@
 
 use super::common;
 
-/// Returns the ELF class from the ELF header in the supplied file.
+//================================================
+// Validation
+//================================================
+
+/// Extracts the ELF class from the ELF header in a shared library.
 fn parse_elf_header(path: &Path) -> io::Result<u8> {
     let mut file = File::open(path)?;
     let mut buffer = [0; 5];
@@ -31,34 +23,34 @@
     }
 }
 
-/// Returns the magic number from the PE header in the supplied file.
+/// Extracts the magic number from the PE header in a shared library.
 fn parse_pe_header(path: &Path) -> io::Result<u16> {
     let mut file = File::open(path)?;
 
-    // Determine the header offset.
+    // Extract the header offset.
     let mut buffer = [0; 4];
     let start = SeekFrom::Start(0x3C);
     file.seek(start)?;
     file.read_exact(&mut buffer)?;
     let offset = i32::from_le_bytes(buffer);
 
-    // Determine the validity of the header.
+    // Check the validity of the header.
     file.seek(SeekFrom::Start(offset as u64))?;
     file.read_exact(&mut buffer)?;
     if buffer != [80, 69, 0, 0] {
         return Err(Error::new(ErrorKind::InvalidData, "invalid PE header"));
     }
 
-    // Find the magic number.
+    // Extract the magic number.
     let mut buffer = [0; 2];
     file.seek(SeekFrom::Current(20))?;
     file.read_exact(&mut buffer)?;
     Ok(u16::from_le_bytes(buffer))
 }
 
-/// Validates the header for the supplied `libclang` shared library.
-fn validate_header(path: &Path) -> Result<(), String> {
-    if cfg!(any(target_os = "freebsd", target_os = "linux")) {
+/// Checks that a `libclang` shared library matches the target platform.
+fn validate_library(path: &Path) -> Result<(), String> {
+    if cfg!(any(target_os = "linux", target_os = "freebsd")) {
         let class = parse_elf_header(path).map_err(|e| e.to_string())?;
 
         if cfg!(target_pointer_width = "32") && class != 1 {
@@ -87,11 +79,14 @@
     }
 }
 
-/// Returns the components of the version in the supplied `libclang` shared
-// library filename.
+//================================================
+// Searching
+//================================================
+
+/// Extracts the version components in a `libclang` shared library filename.
 fn parse_version(filename: &str) -> Vec<u32> {
-    let version = if filename.starts_with("libclang.so.") {
-        &filename[12..]
+    let version = if let Some(version) = filename.strip_prefix("libclang.so.") {
+        version
     } else if filename.starts_with("libclang-") {
         &filename[9..filename.len() - 3]
     } else {
@@ -101,8 +96,8 @@
     version.split('.').map(|s| s.parse().unwrap_or(0)).collect()
 }
 
-/// Returns the paths to, the filenames, and the versions of the `libclang`
-// shared libraries.
+/// Finds `libclang` shared libraries and returns the paths to, filenames of,
+/// and versions of those shared libraries.
 fn search_libclang_directories(runtime: bool) -> Result<Vec<(PathBuf, String, Vec<u32>)>, String> {
     let mut files = vec![format!(
         "{}clang{}",
@@ -127,9 +122,10 @@
     }
 
     if cfg!(any(
-        target_os = "openbsd",
         target_os = "freebsd",
-        target_os = "netbsd"
+        target_os = "haiku",
+        target_os = "netbsd",
+        target_os = "openbsd",
     )) {
         // Some BSD distributions don't create a `libclang.so` symlink either,
         // but use a different naming scheme for versioned files (e.g.,
@@ -143,12 +139,12 @@
         files.push("libclang.dll".into());
     }
 
-    // Validate the `libclang` shared libraries and collect the versions.
+    // Find and validate `libclang` shared libraries and collect the versions.
     let mut valid = vec![];
     let mut invalid = vec![];
     for (directory, filename) in common::search_libclang_directories(&files, "LIBCLANG_PATH") {
         let path = directory.join(&filename);
-        match validate_header(&path) {
+        match validate_library(&path) {
             Ok(()) => {
                 let version = parse_version(&filename);
                 valid.push((directory, filename, version))
@@ -176,8 +172,8 @@
     Err(message)
 }
 
-/// Returns the directory and filename of the "best" available `libclang` shared
-/// library.
+/// Finds the "best" `libclang` shared library and returns the directory and
+/// filename of that library.
 pub fn find(runtime: bool) -> Result<(PathBuf, String), String> {
     search_libclang_directories(runtime)?
         .iter()
@@ -201,7 +197,11 @@
         .ok_or_else(|| "unreachable".into())
 }
 
-/// Find and link to `libclang` dynamically.
+//================================================
+// Linking
+//================================================
+
+/// Finds and links to a `libclang` shared library.
 #[cfg(not(feature = "runtime"))]
 pub fn link() {
     let cep = common::CommandErrorPrinter::default();
@@ -252,7 +252,7 @@
         // `libclang.so.7.0`).
         let name = match name.find(".dylib").or_else(|| name.find(".so")) {
             Some(index) => &name[0..index],
-            None => &name,
+            None => name,
         };
 
         println!("cargo:rustc-link-lib=dylib={}", name);
diff --git a/src/lib.rs b/src/lib.rs
index 6497715..863fa86 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,33 +1,23 @@
-// Copyright 2016 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 //! Rust bindings for `libclang`.
 //!
-//! ## Documentation
+//! ## [Documentation](https://docs.rs/clang-sys)
 //!
-//! There are two versions of the documentation, one for the API exposed when
-//! linking dynamically or statically and one for the API exposed when linking
-//! at runtime (see the
-//! [Dependencies](https://github.com/KyleMayes/clang-sys#dependencies) section
-//! of the README for more information on the linking options).
+//! Note that the documentation on https://docs.rs for this crate assumes usage
+//! of the `runtime` Cargo feature as well as the Cargo feature for the latest
+//! supported version of `libclang` (e.g., `clang_11_0`), neither of which are
+//! enabled by default.
 //!
-//! The only difference between the APIs exposed is that when linking at runtime
-//! a few additional types and functions are exposed to manage the loaded
-//! `libclang` shared library.
+//! Due to the usage of the `runtime` Cargo feature, this documentation will
+//! contain some additional types and functions to manage a dynamically loaded
+//! `libclang` instance at runtime.
 //!
-//! * Runtime - [Documentation](https://kylemayes.github.io/clang-sys/runtime/clang_sys)
-//! * Dynamic / Static - [Documentation](https://kylemayes.github.io/clang-sys/default/clang_sys)
+//! Due to the usage of the Cargo feature for the latest supported version of
+//! `libclang`, this documentation will contain constants and functions that are
+//! not available in the oldest supported version of `libclang` (3.5). All of
+//! these types and functions have a documentation comment which specifies the
+//! minimum `libclang` version required to use the item.
 
 #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
 #![cfg_attr(feature = "cargo-clippy", allow(clippy::unreadable_literal))]
@@ -135,6 +125,8 @@
         const CXCallingConv_AArch64VectorCall = 16,
         const CXCallingConv_Invalid = 100,
         const CXCallingConv_Unexposed = 200,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCallingConv_SwiftAsync = 17,
     }
 }
 
@@ -323,6 +315,12 @@
         const CXCursor_ObjCAvailabilityCheckExpr = 148,
         /// Only produced by `libclang` 7.0 and later.
         const CXCursor_FixedPointLiteral = 149,
+        /// Only produced by `libclang` 12.0 and later.
+        const CXCursor_OMPArrayShapingExpr = 150,
+        /// Only produced by `libclang` 12.0 and later.
+        const CXCursor_OMPIteratorExpr = 151,
+        /// Only produced by `libclang` 12.0 and later.
+        const CXCursor_CXXAddrspaceCastExpr = 152,
         const CXCursor_UnexposedStmt = 200,
         const CXCursor_LabelStmt = 201,
         const CXCursor_CompoundStmt = 202,
@@ -452,6 +450,18 @@
         const CXCursor_OMPDepobjDirective = 286,
         /// Only produced by `libclang` 11.0 and later.
         const CXCursor_OMPScanDirective = 287,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCursor_OMPTileDirective = 288,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCursor_OMPCanonicalLoop = 289,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCursor_OMPInteropDirective = 290,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCursor_OMPDispatchDirective = 291,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCursor_OMPMaskedDirective = 292,
+        /// Only produced by `libclang` 13.0 and later.
+        const CXCursor_OMPUnrollDirective = 293,
         const CXCursor_TranslationUnit = 300,
         const CXCursor_UnexposedAttr = 400,
         const CXCursor_IBActionAttr = 401,
@@ -1031,6 +1041,8 @@
         const CXTypeNullability_Nullable = 1,
         const CXTypeNullability_Unspecified = 2,
         const CXTypeNullability_Invalid = 3,
+        /// Only produced by `libclang` 12.0 and later.
+        const CXTypeNullability_NullableResult = 4,
     }
 }
 
@@ -1762,12 +1774,6 @@
     /// Only available on `libclang` 3.7 and later.
     #[cfg(feature = "clang_3_7")]
     pub fn clang_Cursor_getOffsetOfField(cursor: CXCursor) -> c_longlong;
-    /// Only available on `libclang` 9.0 and later.
-    #[cfg(feature = "clang_9_0")]
-    pub fn clang_Cursor_isAnonymousRecordDecl(cursor: CXCursor) -> c_uint;
-    /// Only available on `libclang` 9.0 and later.
-    #[cfg(feature = "clang_9_0")]
-    pub fn clang_Cursor_isInlineNamespace(cursor: CXCursor) -> c_uint;
     pub fn clang_Cursor_getRawCommentText(cursor: CXCursor) -> CXString;
     pub fn clang_Cursor_getReceiverType(cursor: CXCursor) -> CXType;
     pub fn clang_Cursor_getSpellingNameRange(cursor: CXCursor, index: c_uint, reserved: c_uint) -> CXSourceRange;
@@ -1787,12 +1793,24 @@
     #[cfg(feature = "clang_3_6")]
     pub fn clang_Cursor_getTemplateArgumentValue(cursor: CXCursor, index: c_uint) -> c_longlong;
     pub fn clang_Cursor_getTranslationUnit(cursor: CXCursor) -> CXTranslationUnit;
+    /// Only available on `libclang` 12.0 and later.
+    #[cfg(feature = "clang_12_0")]
+    pub fn clang_Cursor_getVarDeclInitializer(cursor: CXCursor) -> CXCursor;
     /// Only available on `libclang` 3.9 and later.
     #[cfg(feature = "clang_3_9")]
     pub fn clang_Cursor_hasAttrs(cursor: CXCursor) -> c_uint;
+    /// Only available on `libclang` 12.0 and later.
+    #[cfg(feature = "clang_12_0")]
+    pub fn clang_Cursor_hasVarDeclGlobalStorage(cursor: CXCursor) -> c_uint;
+    /// Only available on `libclang` 12.0 and later.
+    #[cfg(feature = "clang_12_0")]
+    pub fn clang_Cursor_hasVarDeclExternalStorage(cursor: CXCursor) -> c_uint;
     /// Only available on `libclang` 3.7 and later.
     #[cfg(feature = "clang_3_7")]
     pub fn clang_Cursor_isAnonymous(cursor: CXCursor) -> c_uint;
+    /// Only available on `libclang` 9.0 and later.
+    #[cfg(feature = "clang_9_0")]
+    pub fn clang_Cursor_isAnonymousRecordDecl(cursor: CXCursor) -> c_uint;
     pub fn clang_Cursor_isBitField(cursor: CXCursor) -> c_uint;
     pub fn clang_Cursor_isDynamicCall(cursor: CXCursor) -> c_int;
     /// Only available on `libclang` 5.0 and later.
@@ -1801,6 +1819,9 @@
     /// Only available on `libclang` 3.9 and later.
     #[cfg(feature = "clang_3_9")]
     pub fn clang_Cursor_isFunctionInlined(cursor: CXCursor) -> c_uint;
+    /// Only available on `libclang` 9.0 and later.
+    #[cfg(feature = "clang_9_0")]
+    pub fn clang_Cursor_isInlineNamespace(cursor: CXCursor) -> c_uint;
     /// Only available on `libclang` 3.9 and later.
     #[cfg(feature = "clang_3_9")]
     pub fn clang_Cursor_isMacroBuiltin(cursor: CXCursor) -> c_uint;
@@ -1876,35 +1897,35 @@
     pub fn clang_Type_getAlignOf(type_: CXType) -> c_longlong;
     pub fn clang_Type_getCXXRefQualifier(type_: CXType) -> CXRefQualifierKind;
     pub fn clang_Type_getClassType(type_: CXType) -> CXType;
+    /// Only available on `libclang` 8.0 and later.
+    #[cfg(feature = "clang_8_0")]
+    pub fn clang_Type_getModifiedType(type_: CXType) -> CXType;
     /// Only available on `libclang` 3.9 and later.
     #[cfg(feature = "clang_3_9")]
     pub fn clang_Type_getNamedType(type_: CXType) -> CXType;
-    pub fn clang_Type_getNumTemplateArguments(type_: CXType) -> c_int;
     /// Only available on `libclang` 8.0 and later.
     #[cfg(feature = "clang_8_0")]
-    pub fn clang_Type_getObjCObjectBaseType(type_: CXType) -> CXType;
+    pub fn clang_Type_getNullability(type_: CXType) -> CXTypeNullabilityKind;
     /// Only available on `libclang` 8.0 and later.
     #[cfg(feature = "clang_8_0")]
     pub fn clang_Type_getNumObjCProtocolRefs(type_: CXType) -> c_uint;
     /// Only available on `libclang` 8.0 and later.
     #[cfg(feature = "clang_8_0")]
-    pub fn clang_Type_getObjCProtocolDecl(type_: CXType, index: c_uint) -> CXCursor;
-    /// Only available on `libclang` 8.0 and later.
-    #[cfg(feature = "clang_8_0")]
     pub fn clang_Type_getNumObjCTypeArgs(type_: CXType) -> c_uint;
-    /// Only available on `libclang` 8.0 and later.
-    #[cfg(feature = "clang_8_0")]
-    pub fn clang_Type_getObjCTypeArg(type_: CXType, index: c_uint) -> CXType;
+    pub fn clang_Type_getNumTemplateArguments(type_: CXType) -> c_int;
     /// Only available on `libclang` 3.9 and later.
     #[cfg(feature = "clang_3_9")]
     pub fn clang_Type_getObjCEncoding(type_: CXType) -> CXString;
+    /// Only available on `libclang` 8.0 and later.
+    #[cfg(feature = "clang_8_0")]
+    pub fn clang_Type_getObjCObjectBaseType(type_: CXType) -> CXType;
+    /// Only available on `libclang` 8.0 and later.
+    #[cfg(feature = "clang_8_0")]
+    pub fn clang_Type_getObjCProtocolDecl(type_: CXType, index: c_uint) -> CXCursor;
+    /// Only available on `libclang` 8.0 and later.
+    #[cfg(feature = "clang_8_0")]
+    pub fn clang_Type_getObjCTypeArg(type_: CXType, index: c_uint) -> CXType;
     pub fn clang_Type_getOffsetOf(type_: CXType, field: *const c_char) -> c_longlong;
-    /// Only available on `libclang` 8.0 and later.
-    #[cfg(feature = "clang_8_0")]
-    pub fn clang_Type_getModifiedType(type_: CXType) -> CXType;
-    /// Only available on `libclang` 8.0 and later.
-    #[cfg(feature = "clang_8_0")]
-    pub fn clang_Type_getNullability(type_: CXType) -> CXTypeNullabilityKind;
     pub fn clang_Type_getSizeOf(type_: CXType) -> c_longlong;
     pub fn clang_Type_getTemplateArgumentAsType(type_: CXType, index: c_uint) -> CXType;
     /// Only available on `libclang` 11.0 and later.
@@ -2097,16 +2118,17 @@
     pub fn clang_getSpecializedCursorTemplate(cursor: CXCursor) -> CXCursor;
     pub fn clang_getSpellingLocation(location: CXSourceLocation, file: *mut CXFile, line: *mut c_uint, column: *mut c_uint, offset: *mut c_uint);
     pub fn clang_getTUResourceUsageName(kind: CXTUResourceUsageKind) -> *const c_char;
-    /// Only available on `libclang` 5.0 and later.
-    #[cfg(feature = "clang_5_0")]
-    pub fn clang_getTranslationUnitTargetInfo(tu: CXTranslationUnit) -> CXTargetInfo;
     pub fn clang_getTemplateCursorKind(cursor: CXCursor) -> CXCursorKind;
+    pub fn clang_getToken(tu: CXTranslationUnit, location: CXSourceLocation) -> *mut CXToken;
     pub fn clang_getTokenExtent(tu: CXTranslationUnit, token: CXToken) -> CXSourceRange;
     pub fn clang_getTokenKind(token: CXToken) -> CXTokenKind;
     pub fn clang_getTokenLocation(tu: CXTranslationUnit, token: CXToken) -> CXSourceLocation;
     pub fn clang_getTokenSpelling(tu: CXTranslationUnit, token: CXToken) -> CXString;
     pub fn clang_getTranslationUnitCursor(tu: CXTranslationUnit) -> CXCursor;
     pub fn clang_getTranslationUnitSpelling(tu: CXTranslationUnit) -> CXString;
+    /// Only available on `libclang` 5.0 and later.
+    #[cfg(feature = "clang_5_0")]
+    pub fn clang_getTranslationUnitTargetInfo(tu: CXTranslationUnit) -> CXTargetInfo;
     pub fn clang_getTypeDeclaration(type_: CXType) -> CXCursor;
     pub fn clang_getTypeKindSpelling(type_: CXTypeKind) -> CXString;
     pub fn clang_getTypeSpelling(type_: CXType) -> CXString;
@@ -2185,10 +2207,10 @@
     pub fn clang_Cursor_getParsedComment(C: CXCursor) -> CXComment;
     pub fn clang_FullComment_getAsHTML(comment: CXComment) -> CXString;
     pub fn clang_FullComment_getAsXML(comment: CXComment) -> CXString;
-    pub fn clang_HTMLStartTagComment_isSelfClosing(comment: CXComment) -> c_uint;
     pub fn clang_HTMLStartTag_getAttrName(comment: CXComment, index: c_uint) -> CXString;
     pub fn clang_HTMLStartTag_getAttrValue(comment: CXComment, index: c_uint) -> CXString;
     pub fn clang_HTMLStartTag_getNumAttrs(comment: CXComment) -> c_uint;
+    pub fn clang_HTMLStartTagComment_isSelfClosing(comment: CXComment) -> c_uint;
     pub fn clang_HTMLTagComment_getAsString(comment: CXComment) -> CXString;
     pub fn clang_HTMLTagComment_getTagName(comment: CXComment) -> CXString;
     pub fn clang_InlineCommandComment_getArgText(comment: CXComment, index: c_uint) -> CXString;
@@ -2201,11 +2223,11 @@
     pub fn clang_ParamCommandComment_getParamName(comment: CXComment) -> CXString;
     pub fn clang_ParamCommandComment_isDirectionExplicit(comment: CXComment) -> c_uint;
     pub fn clang_ParamCommandComment_isParamIndexValid(comment: CXComment) -> c_uint;
+    pub fn clang_TextComment_getText(comment: CXComment) -> CXString;
     pub fn clang_TParamCommandComment_getDepth(comment: CXComment) -> c_uint;
     pub fn clang_TParamCommandComment_getIndex(comment: CXComment, depth: c_uint) -> c_uint;
     pub fn clang_TParamCommandComment_getParamName(comment: CXComment) -> CXString;
     pub fn clang_TParamCommandComment_isParamPositionValid(comment: CXComment) -> c_uint;
-    pub fn clang_TextComment_getText(comment: CXComment) -> CXString;
     pub fn clang_VerbatimBlockLineComment_getText(comment: CXComment) -> CXString;
     pub fn clang_VerbatimLineComment_getText(comment: CXComment) -> CXString;
 }
diff --git a/src/link.rs b/src/link.rs
index 64a3528..c3b0830 100644
--- a/src/link.rs
+++ b/src/link.rs
@@ -1,16 +1,4 @@
-// Copyright 2016 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 //================================================
 // Macros
diff --git a/src/support.rs b/src/support.rs
index 8422f59..ff38d39 100644
--- a/src/support.rs
+++ b/src/support.rs
@@ -1,16 +1,4 @@
-// Copyright 2016 Kyle Mayes
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
 
 //! Provides helper functionality.
 
@@ -18,26 +6,13 @@
 use std::process::Command;
 use std::{env, io};
 
-use glob;
+use glob::{self, Pattern};
 
 use libc::c_int;
 
 use super::CXVersion;
 
 //================================================
-// Macros
-//================================================
-
-macro_rules! try_opt {
-    ($option:expr) => {{
-        match $option {
-            Some(some) => some,
-            None => return None,
-        }
-    }};
-}
-
-//================================================
 // Structs
 //================================================
 
@@ -74,20 +49,41 @@
     /// directory returned by `llvm-config --bindir` is searched. On macOS
     /// systems, `xcodebuild -find clang` will next be queried. Last, the
     /// directories in the system's `PATH` are searched.
+    ///
+    /// ## Cross-compilation
+    ///
+    /// If target arguments are provided (e.g., `-target` followed by a target
+    /// like `x86_64-unknown-linux-gnu`) then this method will prefer a
+    /// target-prefixed instance of `clang` (e.g.,
+    /// `x86_64-unknown-linux-gnu-clang` for the above example).
     pub fn find(path: Option<&Path>, args: &[String]) -> Option<Clang> {
         if let Ok(path) = env::var("CLANG_PATH") {
             return Some(Clang::new(path, args));
         }
 
+        // Determine the cross-compilation target, if any.
+
+        let mut target = None;
+        for i in 0..args.len() {
+            if args[i] == "-target" && i + 1 < args.len() {
+                target = Some(&args[i + 1]);
+            }
+        }
+
+        // Collect the paths to search for a `clang` executable in.
+
         let mut paths = vec![];
+
         if let Some(path) = path {
             paths.push(path.into());
         }
+
         if let Ok(path) = run_llvm_config(&["--bindir"]) {
             if let Some(line) = path.lines().next() {
                 paths.push(line.into());
             }
         }
+
         if cfg!(target_os = "macos") {
             if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                 if let Some(line) = path.lines().next() {
@@ -95,7 +91,25 @@
                 }
             }
         }
-        paths.extend(env::split_paths(&env::var("PATH").unwrap()));
+
+        if let Ok(path) = env::var("PATH") {
+            paths.extend(env::split_paths(&path));
+        }
+
+        // First, look for a target-prefixed `clang` executable.
+
+        if let Some(target) = target {
+            let default = format!("{}-clang{}", target, env::consts::EXE_SUFFIX);
+            let versioned = format!("{}-clang-[0-9]*{}", target, env::consts::EXE_SUFFIX);
+            let patterns = &[&default[..], &versioned[..]];
+            for path in &paths {
+                if let Some(path) = find(path, patterns) {
+                    return Some(Clang::new(path, args));
+                }
+            }
+        }
+
+        // Otherwise, look for any other `clang` executable.
 
         let default = format!("clang{}", env::consts::EXE_SUFFIX);
         let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
@@ -117,12 +131,17 @@
 /// Returns the first match to the supplied glob patterns in the supplied
 /// directory if there are any matches.
 fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
+    // Escape the directory in case it contains characters that have special
+    // meaning in glob patterns (e.g., `[` or `]`).
+    let directory = if let Some(directory) = directory.to_str() {
+        Path::new(&Pattern::escape(directory)).to_owned()
+    } else {
+        return None;
+    };
+
     for pattern in patterns {
         let pattern = directory.join(pattern).to_string_lossy().into_owned();
-        if let Some(path) = try_opt!(glob::glob(&pattern).ok())
-            .filter_map(|p| p.ok())
-            .next()
-        {
+        if let Some(path) = glob::glob(&pattern).ok()?.filter_map(|p| p.ok()).next() {
             if path.is_file() && is_executable(&path).unwrap_or(false) {
                 return Some(path);
             }
@@ -184,10 +203,10 @@
 /// Parses the version from the output of a `clang` executable if possible.
 fn parse_version(path: &Path) -> Option<CXVersion> {
     let output = run_clang(path, &["--version"]).0;
-    let start = try_opt!(output.find("version ")) + 8;
-    let mut numbers = try_opt!(output[start..].split_whitespace().next()).split('.');
-    let major = try_opt!(numbers.next().and_then(parse_version_number));
-    let minor = try_opt!(numbers.next().and_then(parse_version_number));
+    let start = output.find("version ")? + 8;
+    let mut numbers = output[start..].split_whitespace().next()?.split('.');
+    let major = numbers.next().and_then(parse_version_number)?;
+    let minor = numbers.next().and_then(parse_version_number)?;
     let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
     Some(CXVersion {
         Major: major,
@@ -201,8 +220,8 @@
     let mut clang_args = vec!["-E", "-x", language, "-", "-v"];
     clang_args.extend(args.iter().map(|s| &**s));
     let output = run_clang(path, &clang_args).1;
-    let start = try_opt!(output.find("#include <...> search starts here:")) + 34;
-    let end = try_opt!(output.find("End of search list."));
+    let start = output.find("#include <...> search starts here:")? + 34;
+    let end = output.find("End of search list.")?;
     let paths = output[start..end].replace("(framework directory)", "");
     Some(
         paths
diff --git a/tests/lib.rs b/tests/lib.rs
index 100a6c6..b50055a 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -46,3 +46,10 @@
     let clang = support::Clang::find(None, &[]).unwrap();
     println!("{:?}", clang);
 }
+
+#[test]
+fn test_support_target() {
+    let args = &["-target".into(), "x86_64-unknown-linux-gnu".into()];
+    let clang = support::Clang::find(None, args).unwrap();
+    println!("{:?}", clang);
+}