Brian Silverman | 9c614bc | 2016-02-15 20:20:02 -0500 | [diff] [blame^] | 1 | #!/bin/bash |
| 2 | # |
| 3 | # Helper to do build so you don't have to remember all the steps/args. |
| 4 | |
| 5 | |
| 6 | set -eu |
| 7 | |
| 8 | # Some base locations. |
| 9 | readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") |
| 10 | readonly ProtoRootDir="${ScriptDir}/../.." |
| 11 | |
| 12 | printUsage() { |
| 13 | NAME=$(basename "${0}") |
| 14 | cat << EOF |
| 15 | usage: ${NAME} [OPTIONS] |
| 16 | |
| 17 | This script does the common build steps needed. |
| 18 | |
| 19 | OPTIONS: |
| 20 | |
| 21 | General: |
| 22 | |
| 23 | -h, --help |
| 24 | Show this message |
| 25 | -c, --clean |
| 26 | Issue a clean before the normal build. |
| 27 | -a, --autogen |
| 28 | Start by rerunning autogen & configure. |
| 29 | -r, --regenerate-cpp-descriptors |
| 30 | The descriptor.proto is checked in generated, cause it to regenerate. |
| 31 | -j #, --jobs # |
| 32 | Force the number of parallel jobs (useful for debugging build issues). |
| 33 | --core-only |
| 34 | Skip some of the core protobuf build/checks to shorten the build time. |
| 35 | --skip-xcode |
| 36 | Skip the invoke of Xcode to test the runtime on both iOS and OS X. |
| 37 | --skip-xcode-ios |
| 38 | Skip the invoke of Xcode to test the runtime on iOS. |
| 39 | --skip-xcode-osx |
| 40 | Skip the invoke of Xcode to test the runtime on OS X. |
| 41 | --skip-objc-conformance |
| 42 | Skip the Objective C conformance tests (run on OS X). |
| 43 | |
| 44 | EOF |
| 45 | } |
| 46 | |
| 47 | header() { |
| 48 | echo "" |
| 49 | echo "========================================================================" |
| 50 | echo " ${@}" |
| 51 | echo "========================================================================" |
| 52 | } |
| 53 | |
| 54 | # Thanks to libtool, builds can fail in odd ways and since it eats some output |
| 55 | # it can be hard to spot, so force error output if make exits with a non zero. |
| 56 | wrapped_make() { |
| 57 | set +e # Don't stop if the command fails. |
| 58 | make $* |
| 59 | MAKE_EXIT_STATUS=$? |
| 60 | if [ ${MAKE_EXIT_STATUS} -ne 0 ]; then |
| 61 | echo "Error: 'make $*' exited with status ${MAKE_EXIT_STATUS}" |
| 62 | exit ${MAKE_EXIT_STATUS} |
| 63 | fi |
| 64 | set -e |
| 65 | } |
| 66 | |
| 67 | NUM_MAKE_JOBS=$(/usr/sbin/sysctl -n hw.ncpu) |
| 68 | if [[ "${NUM_MAKE_JOBS}" -lt 4 ]] ; then |
| 69 | NUM_MAKE_JOBS=4 |
| 70 | fi |
| 71 | |
| 72 | DO_AUTOGEN=no |
| 73 | DO_CLEAN=no |
| 74 | REGEN_CPP_DESCRIPTORS=no |
| 75 | CORE_ONLY=no |
| 76 | DO_XCODE_IOS_TESTS=yes |
| 77 | DO_XCODE_OSX_TESTS=yes |
| 78 | DO_OBJC_CONFORMANCE_TESTS=yes |
| 79 | while [[ $# != 0 ]]; do |
| 80 | case "${1}" in |
| 81 | -h | --help ) |
| 82 | printUsage |
| 83 | exit 0 |
| 84 | ;; |
| 85 | -c | --clean ) |
| 86 | DO_CLEAN=yes |
| 87 | ;; |
| 88 | -a | --autogen ) |
| 89 | DO_AUTOGEN=yes |
| 90 | ;; |
| 91 | -r | --regenerate-cpp-descriptors ) |
| 92 | REGEN_CPP_DESCRIPTORS=yes |
| 93 | ;; |
| 94 | -j | --jobs ) |
| 95 | shift |
| 96 | NUM_MAKE_JOBS="${1}" |
| 97 | ;; |
| 98 | --core-only ) |
| 99 | CORE_ONLY=yes |
| 100 | ;; |
| 101 | --skip-xcode ) |
| 102 | DO_XCODE_IOS_TESTS=no |
| 103 | DO_XCODE_OSX_TESTS=no |
| 104 | ;; |
| 105 | --skip-xcode-ios ) |
| 106 | DO_XCODE_IOS_TESTS=no |
| 107 | ;; |
| 108 | --skip-xcode-osx ) |
| 109 | DO_XCODE_OSX_TESTS=no |
| 110 | ;; |
| 111 | --skip-objc-conformance ) |
| 112 | DO_OBJC_CONFORMANCE_TESTS=no |
| 113 | ;; |
| 114 | -*) |
| 115 | echo "ERROR: Unknown option: ${1}" 1>&2 |
| 116 | printUsage |
| 117 | exit 1 |
| 118 | ;; |
| 119 | *) |
| 120 | echo "ERROR: Unknown argument: ${1}" 1>&2 |
| 121 | printUsage |
| 122 | exit 1 |
| 123 | ;; |
| 124 | esac |
| 125 | shift |
| 126 | done |
| 127 | |
| 128 | # Into the proto dir. |
| 129 | cd "${ProtoRootDir}" |
| 130 | |
| 131 | # if no Makefile, force the autogen. |
| 132 | if [[ ! -f Makefile ]] ; then |
| 133 | DO_AUTOGEN=yes |
| 134 | fi |
| 135 | |
| 136 | if [[ "${DO_AUTOGEN}" == "yes" ]] ; then |
| 137 | header "Running autogen & configure" |
| 138 | ./autogen.sh |
| 139 | ./configure \ |
| 140 | CPPFLAGS="-mmacosx-version-min=10.9 -Wunused-const-variable -Wunused-function" \ |
| 141 | CXXFLAGS="-Wnon-virtual-dtor -Woverloaded-virtual" |
| 142 | fi |
| 143 | |
| 144 | if [[ "${DO_CLEAN}" == "yes" ]] ; then |
| 145 | header "Cleaning" |
| 146 | wrapped_make clean |
| 147 | if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then |
| 148 | XCODEBUILD_CLEAN_BASE_IOS=( |
| 149 | xcodebuild |
| 150 | -project objectivec/ProtocolBuffers_iOS.xcodeproj |
| 151 | -scheme ProtocolBuffers |
| 152 | ) |
| 153 | "${XCODEBUILD_CLEAN_BASE_IOS[@]}" -configuration Debug clean |
| 154 | "${XCODEBUILD_CLEAN_BASE_IOS[@]}" -configuration Release clean |
| 155 | fi |
| 156 | if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then |
| 157 | XCODEBUILD_CLEAN_BASE_OSX=( |
| 158 | xcodebuild |
| 159 | -project objectivec/ProtocolBuffers_OSX.xcodeproj |
| 160 | -scheme ProtocolBuffers |
| 161 | ) |
| 162 | "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Debug clean |
| 163 | "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Release clean |
| 164 | fi |
| 165 | fi |
| 166 | |
| 167 | if [[ "${REGEN_CPP_DESCRIPTORS}" == "yes" ]] ; then |
| 168 | header "Regenerating the C++ descriptor sources." |
| 169 | ./generate_descriptor_proto.sh -j "${NUM_MAKE_JOBS}" |
| 170 | fi |
| 171 | |
| 172 | if [[ "${CORE_ONLY}" == "yes" ]] ; then |
| 173 | header "Building core Only" |
| 174 | wrapped_make -j "${NUM_MAKE_JOBS}" |
| 175 | else |
| 176 | header "Building" |
| 177 | # Can't issue these together, when fully parallel, something sometimes chokes |
| 178 | # at random. |
| 179 | wrapped_make -j "${NUM_MAKE_JOBS}" all |
| 180 | wrapped_make -j "${NUM_MAKE_JOBS}" check |
| 181 | # Fire off the conformance tests also. |
| 182 | cd conformance |
| 183 | wrapped_make -j "${NUM_MAKE_JOBS}" test_cpp |
| 184 | cd .. |
| 185 | fi |
| 186 | |
| 187 | header "Ensuring the ObjC descriptors are current." |
| 188 | # Find the newest input file (protos, compiler, and the generator script). |
| 189 | # (these patterns catch some extra stuff, but better to over sample than under) |
| 190 | readonly NewestInput=$(find \ |
| 191 | src/google/protobuf/*.proto \ |
| 192 | src/.libs src/*.la src/protoc \ |
| 193 | objectivec/generate_descriptors_proto.sh \ |
| 194 | -type f -print0 \ |
| 195 | | xargs -0 stat -f "%m %N" \ |
| 196 | | sort -n | tail -n1 | cut -f2- -d" ") |
| 197 | # Find the oldest output file. |
| 198 | readonly OldestOutput=$(find \ |
| 199 | "${ProtoRootDir}/objectivec/google" \ |
| 200 | -type f -print0 \ |
| 201 | | xargs -0 stat -f "%m %N" \ |
| 202 | | sort -n -r | tail -n1 | cut -f2- -d" ") |
| 203 | # If the newest input is newer than the oldest output, regenerate. |
| 204 | if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then |
| 205 | echo ">> Newest input is newer than oldest output, regenerating." |
| 206 | objectivec/generate_descriptors_proto.sh -j "${NUM_MAKE_JOBS}" |
| 207 | else |
| 208 | echo ">> Newest input is older than oldest output, no need to regenerating." |
| 209 | fi |
| 210 | |
| 211 | header "Checking on the ObjC Runtime Code" |
| 212 | objectivec/DevTools/pddm_tests.py |
| 213 | if ! objectivec/DevTools/pddm.py --dry-run objectivec/*.[hm] objectivec/Tests/*.[hm] ; then |
| 214 | echo "" |
| 215 | echo "Update by running:" |
| 216 | echo " objectivec/DevTools/pddm.py objectivec/*.[hm] objectivec/Tests/*.[hm]" |
| 217 | exit 1 |
| 218 | fi |
| 219 | |
| 220 | if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then |
| 221 | XCODEBUILD_TEST_BASE_IOS=( |
| 222 | xcodebuild |
| 223 | -project objectivec/ProtocolBuffers_iOS.xcodeproj |
| 224 | -scheme ProtocolBuffers |
| 225 | ) |
| 226 | # Don't need to worry about form factors or retina/non retina; |
| 227 | # just pick a mix of OS Versions and 32/64 bit. |
| 228 | # NOTE: Different Xcode have different simulated hardware/os support. |
| 229 | readonly XCODE_VERSION_LINE="$(xcodebuild -version | grep Xcode\ )" |
| 230 | readonly XCODE_VERSION="${XCODE_VERSION_LINE/Xcode /}" # drop the prefix. |
| 231 | IOS_SIMULATOR_NAME="Simulator" |
| 232 | case "${XCODE_VERSION}" in |
| 233 | 6.* ) |
| 234 | echo "ERROR: Xcode 6.3/6.4 no longer supported for building, please use 7.0 or higher." 1>&2 |
| 235 | exit 10 |
| 236 | ;; |
| 237 | 7.* ) |
| 238 | XCODEBUILD_TEST_BASE_IOS+=( |
| 239 | -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit |
| 240 | -destination "platform=iOS Simulator,name=iPhone 6,OS=9.0" # 64bit |
| 241 | -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit |
| 242 | -destination "platform=iOS Simulator,name=iPad Air,OS=9.0" # 64bit |
| 243 | ) |
| 244 | ;; |
| 245 | * ) |
| 246 | echo "Time to update the simulator targets for Xcode ${XCODE_VERSION}" |
| 247 | exit 2 |
| 248 | ;; |
| 249 | esac |
| 250 | header "Doing Xcode iOS build/tests - Debug" |
| 251 | "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Debug test |
| 252 | header "Doing Xcode iOS build/tests - Release" |
| 253 | "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Release test |
| 254 | # Don't leave the simulator in the developer's face. |
| 255 | killall "${IOS_SIMULATOR_NAME}" |
| 256 | fi |
| 257 | if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then |
| 258 | XCODEBUILD_TEST_BASE_OSX=( |
| 259 | xcodebuild |
| 260 | -project objectivec/ProtocolBuffers_OSX.xcodeproj |
| 261 | -scheme ProtocolBuffers |
| 262 | # Since the ObjC 2.0 Runtime is required, 32bit OS X isn't supported. |
| 263 | -destination "platform=OS X,arch=x86_64" # 64bit |
| 264 | ) |
| 265 | header "Doing Xcode OS X build/tests - Debug" |
| 266 | "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Debug test |
| 267 | header "Doing Xcode OS X build/tests - Release" |
| 268 | "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Release test |
| 269 | fi |
| 270 | |
| 271 | if [[ "${DO_OBJC_CONFORMANCE_TESTS}" == "yes" ]] ; then |
| 272 | cd conformance |
| 273 | wrapped_make -j "${NUM_MAKE_JOBS}" test_objc |
| 274 | cd .. |
| 275 | fi |