check-dev-context-only-utils.sh 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #!/usr/bin/env bash
  2. set -eo pipefail
  3. cd "$(dirname "$0")/.."
  4. source ci/_
  5. # only nightly is used uniformly as we contain good amount of nightly-only code
  6. # (benches, frozen abi...)
  7. source ci/rust-version.sh nightly
  8. # There's a special common feature called `dev-context-only-utils` to
  9. # overcome cargo's issue: https://github.com/rust-lang/cargo/issues/8379
  10. # This feature is like `cfg(test)`, which works between crates.
  11. #
  12. # Unfortunately, this in turn needs some special checks to avoid common
  13. # pitfalls of `dev-context-only-utils` itself.
  14. #
  15. # Firstly, detect any misuse of dev-context-only-utils as normal/build
  16. # dependencies. Also, allow some exceptions for special purpose crates. This
  17. # white-listing mechanism can be used for core-development-oriented crates like
  18. # bench bins.
  19. #
  20. # Put differently, use of dev-context-only-utils is forbidden for non-dev
  21. # dependencies in general. However, allow its use for non-dev dependencies only
  22. # if its use is confined under a dep. subgraph with all nodes being marked as
  23. # dev-context-only-utils.
  24. # Add your troubled package which seems to want to use `dev-context-only-utils`
  25. # as normal (not dev) dependencies, only if you're sure that there's good
  26. # reason to bend dev-context-only-utils's original intention and that listed
  27. # package isn't part of released binaries.
  28. declare tainted_packages=(
  29. solana-accounts-bench
  30. solana-banking-bench
  31. agave-ledger-tool
  32. solana-bench-tps
  33. agave-store-tool
  34. agave-accounts-hash-cache-tool
  35. )
  36. # convert to comma separeted (ref: https://stackoverflow.com/a/53839433)
  37. printf -v allowed '"%s",' "${tainted_packages[@]}"
  38. allowed="${allowed%,}"
  39. mode=${1:-full}
  40. case "$mode" in
  41. tree | check-bins | check-all-targets | full)
  42. ;;
  43. *)
  44. echo "$0: unrecognized mode: $mode";
  45. exit 1
  46. ;;
  47. esac
  48. if [[ $mode = "tree" || $mode = "full" ]]; then
  49. query=$(cat <<EOF
  50. .packages
  51. | map(.name as \$crate
  52. | (.dependencies
  53. | map(select((.kind // "normal") == "normal"))
  54. | map({
  55. "crate" : \$crate,
  56. "dependency" : .name,
  57. "dependencyFeatures" : .features,
  58. })
  59. )
  60. )
  61. | flatten
  62. | map(select(
  63. (.dependencyFeatures
  64. | index("dev-context-only-utils")
  65. ) and (.crate as \$needle
  66. | ([$allowed] | index(\$needle))
  67. | not
  68. )
  69. ))
  70. | map([.crate, .dependency] | join(": "))
  71. | join("\n ")
  72. EOF
  73. )
  74. abusers="$(_ cargo "+${rust_nightly}" metadata --format-version=1 |
  75. jq -r "$query")"
  76. if [[ -n "$abusers" ]]; then
  77. cat <<EOF 1>&2
  78. \`dev-context-only-utils\` must not be used as normal dependencies, but is by \
  79. "([crate]: [dependency])":
  80. $abusers
  81. EOF
  82. exit 1
  83. fi
  84. # Sanity-check that tainted packages has undergone the proper tedious rituals
  85. # to be justified as such.
  86. query=$(cat <<EOF
  87. .packages
  88. | map([.name, (.features | keys)] as [\$this_crate, \$this_feature]
  89. | if .name as \$needle | ([$allowed] | index(\$needle))
  90. then
  91. {
  92. "crate": \$this_crate,
  93. "crateFeatures": \$this_feature,
  94. }
  95. elif .dependencies | any(
  96. .name as \$needle | ([$allowed] | index(\$needle))
  97. )
  98. then
  99. .dependencies
  100. | map({
  101. "crate": \$this_crate,
  102. "crateFeatures": \$this_feature,
  103. })
  104. else
  105. []
  106. end)
  107. | flatten
  108. | map(select(
  109. (.crateFeatures | index("dev-context-only-utils")) | not
  110. ))
  111. | map(.crate)
  112. | join("\n ")
  113. EOF
  114. )
  115. misconfigured_crates=$(
  116. _ cargo "+${rust_nightly}" metadata \
  117. --format-version=1 \
  118. | jq -r "$query"
  119. )
  120. if [[ -n "$misconfigured_crates" ]]; then
  121. cat <<EOF 1>&2
  122. All crates marked \`tainted\`, as well as their dependents, MUST declare the \
  123. \`dev-context-only-utils\`. The following crates are in violation:
  124. $misconfigured_crates
  125. EOF
  126. exit 1
  127. fi
  128. fi
  129. # Detect possible compilation errors of problematic usage of
  130. # `dev-context-only-utils`-gated code without being explicitly declared as such
  131. # in respective workspace member `Cargo.toml`s. This cannot be detected with
  132. # `--workspace --all-targets`, due to unintentional `dev-context-only-utils`
  133. # feature activation by cargo's feature unification mechanism. So, we use
  134. # `cargo hack` to exhaustively build each individual workspace members in
  135. # isolation to work around.
  136. #
  137. # 1. Check implicit usage of `dev-context-only-utils`-gated code in non-dev (=
  138. # production) code by building without dev dependencies (= tests/benches) for
  139. # each crate
  140. # 2. Check implicit usage of `dev-context-only-utils`-gated code in dev (=
  141. # test/benches) code by building in isolation from other crates, which might
  142. # happen to enable `dev-context-only-utils`
  143. # dcou tends to newly trigger `unused_imports` and `dead_code` lints.
  144. # We could selectively deny (= `-D`) them here, however, deny all warnings for
  145. # consistency with other CI steps and for the possibility of new similar lints.
  146. export RUSTFLAGS="-D warnings -Z threads=8 $RUSTFLAGS"
  147. if [[ $mode = "check-bins" || $mode = "full" ]]; then
  148. _ cargo "+${rust_nightly}" hack check --bins
  149. fi
  150. if [[ $mode = "check-all-targets" || $mode = "full" ]]; then
  151. _ cargo "+${rust_nightly}" hack check --all-targets
  152. fi