Added rustfmt config for running rustfmt in CI (#747)

* Added rustfmt_aspect to enforce formatting in the workspace

* Added config

* Added alias and updated docs

* Fixed formatting

* Regenerate documentation

* Addressed PR feedback

* Revert "Added alias and updated docs"

This reverts commit 191fb68741f4d8bec1856774ac1fb437ecb514cd.

* Updated formatting

* Revert "Regenerate documentation"

This reverts commit 4af576e881ccc6d42c675a9fde6c851827092aef.
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 06af059..9881deb 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -11,6 +11,8 @@
   ubuntu1604:
     build_targets: *default_linux_targets
     test_targets: *default_linux_targets
+    build_flags:
+      - "--config=rustfmt"
   ubuntu1804:
     build_targets: *default_linux_targets
     test_targets:
@@ -18,11 +20,15 @@
       - "@examples//..."
       # TODO: Switch manual tag to platform constraint after bazel 4.0.
       - "//test/versioned_dylib:versioned_dylib_test"
+    build_flags:
+      - "--config=rustfmt"
   ubuntu2004:
     name: "Minimum Supported Version"
     bazel: "3.5.0"
     build_targets: *default_linux_targets
     test_targets: *default_linux_targets
+    build_flags:
+      - "--config=rustfmt"
   macos:
     osx_targets: &osx_targets
       - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245
@@ -34,6 +40,8 @@
       - "-@examples//ffi/rust_calling_c/simple/..."
     build_targets: *osx_targets
     test_targets: *osx_targets
+    build_flags:
+      - "--config=rustfmt"
   rbe_ubuntu1604:
     test_targets:
       - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245
@@ -49,9 +57,12 @@
       - "-@examples//ffi/rust_calling_c/simple/..."
       # See https://github.com/bazelbuild/bazel/issues/9987
       - "-@examples//ffi/rust_calling_c:matrix_dylib_test"
+    build_flags:
+      - "--config=rustfmt"
   windows:
     build_flags:
       - "--enable_runfiles" # this is not enabled by default on windows and is necessary for the cargo build scripts
+      - "--config=rustfmt"
     windows_targets: &windows_targets
       - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245
       - "..."
@@ -78,6 +89,8 @@
     working_directory: examples
     test_targets:
       - //...
+    build_flags:
+      - "--config=rustfmt"
   docs_linux:
     name: Docs
     platform: ubuntu1804
@@ -100,15 +113,6 @@
     platform: ubuntu1804
     shell_commands:
       - ./test/clippy/clippy_failure_test.sh
-  rustfmt_examples:
-    name: Rustfmt on Examples
-    platform: ubuntu2004
-    working_directory: examples
-    build_flags:
-      - "--aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect"
-      - "--output_groups=rustfmt_checks"
-    build_targets:
-      - //...
   rustfmt_failure:
     name: Negative Rustfmt Tests
     platform: ubuntu2004
@@ -143,6 +147,8 @@
       - "//..."
     test_targets:
       - "//..."
+    build_flags:
+      - "--config=rustfmt"
   crate_universe_examples_macos:
     name: Crate Universe Examples
     platform: macos
@@ -153,6 +159,8 @@
       - "//..."
     test_targets:
       - "//..."
+    build_flags:
+      - "--config=rustfmt"
   crate_universe_examples_windows:
     name: Crate Universe Examples
     platform: windows
@@ -161,6 +169,7 @@
     working_directory: examples/crate_universe
     build_flags:
       - "--enable_runfiles" # this is not enabled by default on windows and is necessary for the cargo build scripts
+      - "--config=rustfmt"
     crate_universe_windows_targets: &crate_universe_windows_targets
       - "//..."
       # TODO: There are windows specific build issues in the generated
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..db9695b
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,6 @@
+# `.bazelrc` is a Bazel configuration file.
+# https://docs.bazel.build/versions/master/best-practices.html#using-the-bazelrc-file
+
+# Enable rustfmt for all targets in the workspace
+build:rustfmt --aspects=//rust:defs.bzl%rustfmt_aspect
+build:rustfmt --output_groups=+rustfmt_checks
diff --git a/cargo/cargo_build_script_runner/BUILD.bazel b/cargo/cargo_build_script_runner/BUILD.bazel
index 15ad96c..b24008d 100644
--- a/cargo/cargo_build_script_runner/BUILD.bazel
+++ b/cargo/cargo_build_script_runner/BUILD.bazel
@@ -1,4 +1,4 @@
-load("//rust:rust.bzl", "rust_binary", "rust_library", "rust_test")
+load("//rust:defs.bzl", "rust_binary", "rust_library", "rust_test")
 
 rust_library(
     name = "cargo_build_script_output_parser",
diff --git a/examples/.bazelrc b/examples/.bazelrc
new file mode 100644
index 0000000..a61cbe3
--- /dev/null
+++ b/examples/.bazelrc
@@ -0,0 +1,6 @@
+# `.bazelrc` is a Bazel configuration file.
+# https://docs.bazel.build/versions/master/best-practices.html#using-the-bazelrc-file
+
+# Enable rustfmt for all targets in the workspace
+build:rustfmt --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
+build:rustfmt --output_groups=+rustfmt_checks
diff --git a/examples/crate_universe/.bazelrc b/examples/crate_universe/.bazelrc
new file mode 100644
index 0000000..a61cbe3
--- /dev/null
+++ b/examples/crate_universe/.bazelrc
@@ -0,0 +1,6 @@
+# `.bazelrc` is a Bazel configuration file.
+# https://docs.bazel.build/versions/master/best-practices.html#using-the-bazelrc-file
+
+# Enable rustfmt for all targets in the workspace
+build:rustfmt --aspects=@rules_rust//rust:defs.bzl%rustfmt_aspect
+build:rustfmt --output_groups=+rustfmt_checks
diff --git a/rust/private/rustfmt.bzl b/rust/private/rustfmt.bzl
index d38c2a8..9c59f48 100644
--- a/rust/private/rustfmt.bzl
+++ b/rust/private/rustfmt.bzl
@@ -16,6 +16,10 @@
     if rust_common.crate_info not in target:
         return []
 
+    # Ignore external targets
+    if target.label.workspace_root.startswith("external"):
+        return []
+
     # Targets annotated with `norustfmt` will not be formatted
     if aspect_ctx and "norustfmt" in aspect_ctx.rule.attr.tags:
         return []
diff --git a/test/rustfmt/BUILD.bazel b/test/rustfmt/BUILD.bazel
index 5ab4876..37920f0 100644
--- a/test/rustfmt/BUILD.bazel
+++ b/test/rustfmt/BUILD.bazel
@@ -19,6 +19,7 @@
     name = "unformatted_2018",
     srcs = ["srcs/2018/unformatted.rs"],
     edition = "2018",
+    tags = ["norustfmt"],
 )
 
 rustfmt_test(
@@ -42,6 +43,7 @@
     name = "unformatted_2015",
     srcs = ["srcs/2015/unformatted.rs"],
     edition = "2015",
+    tags = ["norustfmt"],
 )
 
 rustfmt_test(
diff --git a/test/rustfmt/rustfmt_failure_test.sh b/test/rustfmt/rustfmt_failure_test.sh
index 0a658e8..7fc56da 100755
--- a/test/rustfmt/rustfmt_failure_test.sh
+++ b/test/rustfmt/rustfmt_failure_test.sh
@@ -33,17 +33,7 @@
   fi
 }
 
-function test_all() {
-  local -r TEST_OK=0
-  local -r TEST_FAILED=3
-
-  check_build_result $TEST_FAILED test_unformatted_2015
-  check_build_result $TEST_FAILED test_unformatted_2018
-  check_build_result $TEST_OK test_formatted_2015
-  check_build_result $TEST_OK test_formatted_2018
-}
-
-function test_apply() {
+function test_all_and_apply() {
   local -r TEST_OK=0
   local -r TEST_FAILED=3
 
@@ -62,8 +52,21 @@
 rust_repositories()
 EOF
 
+  # Drop the 'norustfmt' tags
+  if [ "$(uname)" == "Darwin" ]; then
+    SEDOPTS=(-i '' -e)
+  else
+    SEDOPTS=(-i)
+  fi
+  sed ${SEDOPTS[@]} 's/"norustfmt"//' "${new_workspace}/test/rustfmt/BUILD.bazel"
+
   pushd "${new_workspace}"
 
+  check_build_result $TEST_FAILED test_unformatted_2015
+  check_build_result $TEST_FAILED test_unformatted_2018
+  check_build_result $TEST_OK test_formatted_2015
+  check_build_result $TEST_OK test_formatted_2018
+
   # Format a specific target
   bazel run @rules_rust//tools/rustfmt -- //test/rustfmt:unformatted_2018
 
@@ -85,5 +88,4 @@
   rm -rf "${temp_dir}"
 }
 
-test_all
-test_apply
+test_all_and_apply
diff --git a/test/unit/use_libtest_harness/mytest.rs b/test/unit/use_libtest_harness/mytest.rs
index e69de29..8b13789 100644
--- a/test/unit/use_libtest_harness/mytest.rs
+++ b/test/unit/use_libtest_harness/mytest.rs
@@ -0,0 +1 @@
+
diff --git a/test/unit/use_libtest_harness/mytest_noharness.rs b/test/unit/use_libtest_harness/mytest_noharness.rs
index e71fdf5..f328e4d 100644
--- a/test/unit/use_libtest_harness/mytest_noharness.rs
+++ b/test/unit/use_libtest_harness/mytest_noharness.rs
@@ -1 +1 @@
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/tools/runfiles/BUILD.bazel b/tools/runfiles/BUILD.bazel
index 38dff9c..b78074f 100644
--- a/tools/runfiles/BUILD.bazel
+++ b/tools/runfiles/BUILD.bazel
@@ -1,5 +1,5 @@
 load(
-    "//rust:rust.bzl",
+    "//rust:defs.bzl",
     "rust_doc_test",
     "rust_library",
     "rust_test",
diff --git a/tools/rust_analyzer/main.rs b/tools/rust_analyzer/main.rs
index 4b1e733..a519d08 100644
--- a/tools/rust_analyzer/main.rs
+++ b/tools/rust_analyzer/main.rs
@@ -33,7 +33,9 @@
     let mut generated_rust_project = bazel_bin.clone();
 
     if let Some(repository_name) = label.repository_name {
-        generated_rust_project = generated_rust_project.join("external").join(repository_name);
+        generated_rust_project = generated_rust_project
+            .join("external")
+            .join(repository_name);
     }
 
     for package in label.packages() {