swift-version.sh 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #!/usr/bin/env bash
  2. : "${REALM_XCODE_VERSION:=}"
  3. : "${REALM_SWIFT_VERSION:=}"
  4. : "${DEVELOPER_DIR:=}"
  5. get_swift_version() {
  6. "$1" --version 2>/dev/null | sed -ne 's/^Apple Swift version \([^\b ]*\).*/\1/p'
  7. }
  8. get_xcode_version() {
  9. "$1" -version 2>/dev/null | sed -ne 's/^Xcode \([^\b ]*\).*/\1/p'
  10. }
  11. is_xcode_version() {
  12. test "$(get_xcode_version "$1")" = "$2"
  13. }
  14. find_xcode_with_version() {
  15. local path required_version
  16. if [ -z "$1" ]; then
  17. echo "find_xcode_with_version requires an Xcode version" >&2
  18. exit 1
  19. fi
  20. required_version=$1
  21. # First check if the currently active one is fine, unless we are in a CI run
  22. if [ -z "$JENKINS_HOME" ] && is_xcode_version xcodebuild "$required_version"; then
  23. DEVELOPER_DIR=$(xcode-select -p)
  24. return 0
  25. fi
  26. # Check the spot where we install it on CI machines
  27. path="/Applications/Xcode-${required_version}.app/Contents/Developer"
  28. if [ -d "$path" ]; then
  29. if is_xcode_version "$path/usr/bin/xcodebuild" "$required_version"; then
  30. DEVELOPER_DIR=$path
  31. return 0
  32. fi
  33. fi
  34. # Check all of the items in /Applications that look promising per #4534
  35. for path in /Applications/Xcode*.app/Contents/Developer; do
  36. if is_xcode_version "$path/usr/bin/xcodebuild" "$required_version"; then
  37. DEVELOPER_DIR=$path
  38. return 0
  39. fi
  40. done
  41. # Use Spotlight to see if we can find others installed copies of Xcode
  42. for path in $(/usr/bin/mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'" 2>/dev/null); do
  43. path="$path/Contents/Developer"
  44. if [ ! -d "$path" ]; then
  45. continue
  46. fi
  47. if is_xcode_version "$path/usr/bin/xcodebuild" "$required_version"; then
  48. DEVELOPER_DIR=$path
  49. return 0
  50. fi
  51. done
  52. echo "No Xcode found with version $required_version" >&2
  53. exit 1
  54. }
  55. test_xcode_for_swift_version() {
  56. if [ -z "$1" ] || [ -z "$2" ]; then
  57. echo "test_xcode_for_swift_version called with empty parameter(s): '$1' or '$2'" >&2
  58. exit 1
  59. fi
  60. local path=$1
  61. local required_version=$2
  62. for swift in "$path"/Toolchains/*.xctoolchain/usr/bin/swift; do
  63. if [ "$(get_swift_version "$swift")" = "$required_version" ]; then
  64. return 0
  65. fi
  66. done
  67. return 1
  68. }
  69. find_xcode_for_swift() {
  70. local path required_version
  71. if [ -z "$1" ]; then
  72. echo "find_xcode_for_swift requires a Swift version" >&2
  73. exit 1
  74. fi
  75. required_version=$1
  76. # First check if the currently active one is fine, unless we are in a CI run
  77. if [ -z "$JENKINS_HOME" ] && test_xcode_for_swift_version "$(xcode-select -p)" "$required_version"; then
  78. DEVELOPER_DIR=$(xcode-select -p)
  79. return 0
  80. fi
  81. # Check all of the items in /Applications that look promising per #4534
  82. for path in /Applications/Xcode*.app/Contents/Developer; do
  83. if test_xcode_for_swift_version "$path" "$required_version"; then
  84. DEVELOPER_DIR=$path
  85. return 0
  86. fi
  87. done
  88. # Use Spotlight to see if we can find others installed copies of Xcode
  89. for path in $(/usr/bin/mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'" 2>/dev/null); do
  90. path="$path/Contents/Developer"
  91. if [ ! -d "$path" ]; then
  92. continue
  93. fi
  94. if test_xcode_for_swift_version "$path" "$required_version"; then
  95. DEVELOPER_DIR=$path
  96. return 0
  97. fi
  98. done
  99. echo "No version of Xcode found that supports Swift $required_version" >&2
  100. exit 1
  101. }
  102. find_default_xcode_version() {
  103. DEVELOPER_DIR="$(xcode-select -p)"
  104. # Verify that DEVELOPER_DIR points to an Xcode installation, rather than the Xcode command-line tools.
  105. if [ -x "$DEVELOPER_DIR/usr/bin/xcodebuild" ]; then
  106. # It's an Xcode installation so we're good to go.
  107. return 0
  108. fi
  109. echo "WARNING: The active Xcode command line tools, as returned by 'xcode-select -p', are not from Xcode."
  110. echo " The newest version of Xcode will be used instead."
  111. # Find the newest version of Xcode available on the system, based on CFBundleVersion.
  112. local xcode_version newest_xcode_version newest_xcode_path
  113. newest_xcode_version=0
  114. for path in $(/usr/bin/mdfind "kMDItemCFBundleIdentifier == 'com.apple.dt.Xcode'" 2>/dev/null); do
  115. xcode_version=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$path/Contents/Info.plist")
  116. if echo "$xcode_version" "$newest_xcode_version" | awk '{exit !( $1 > $2)}'; then
  117. newest_xcode_version="$xcode_version"
  118. newest_xcode_path="$path"
  119. fi
  120. done
  121. if [ -z "$newest_xcode_path" ]; then
  122. echo "No version of Xcode could be found" >&2
  123. exit 1
  124. fi
  125. DEVELOPER_DIR="$newest_xcode_path/Contents/Developer"
  126. }
  127. set_xcode_and_swift_versions() {
  128. if [ -n "$REALM_XCODE_VERSION" ]; then
  129. find_xcode_with_version "$REALM_XCODE_VERSION"
  130. if [ -n "$REALM_SWIFT_VERSION" ] && ! test_xcode_for_swift_version "$DEVELOPER_DIR" "$REALM_SWIFT_VERSION"; then
  131. echo "The version of Xcode specified ($REALM_XCODE_VERSION) does not support the Swift version required: $REALM_SWIFT_VERSION"
  132. exit 1
  133. fi
  134. elif [ -n "$REALM_SWIFT_VERSION" ]; then
  135. find_xcode_for_swift "$REALM_SWIFT_VERSION"
  136. elif [ -z "$DEVELOPER_DIR" ]; then
  137. find_default_xcode_version
  138. fi
  139. export DEVELOPER_DIR
  140. REALM_XCODE_VERSION="$(get_xcode_version "$DEVELOPER_DIR/usr/bin/xcodebuild")"
  141. export REALM_XCODE_VERSION
  142. if [ -z "$REALM_SWIFT_VERSION" ]; then
  143. REALM_SWIFT_VERSION=$(get_swift_version "$(xcrun -f swift)")
  144. fi
  145. export REALM_SWIFT_VERSION
  146. }
  147. return 2>/dev/null || { # only run if called directly
  148. set_xcode_and_swift_versions
  149. echo "Found Swift version $REALM_SWIFT_VERSION in Xcode $REALM_XCODE_VERSION at $DEVELOPER_DIR"
  150. }