1#!/bin/bash -eu 2# Invoked by the Xcode projects to build the protos needed for the unittests. 3 4readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos" 5 6# ----------------------------------------------------------------------------- 7# Helper for bailing. 8die() { 9 echo "Error: $1" 10 exit 2 11} 12 13# ----------------------------------------------------------------------------- 14# What to do. 15case "${ACTION}" in 16 "") 17 # Build, fall thru 18 ;; 19 "clean") 20 rm -rf "${OUTPUT_DIR}" 21 exit 0 22 ;; 23 *) 24 die "Unknown action requested: ${ACTION}" 25 ;; 26esac 27 28# ----------------------------------------------------------------------------- 29# Reusing a bunch of the protos from the protocolbuffers/protobuf tree, this 30# can include some extras as there is no harm in ensuring work for C++ 31# generation. 32 33CORE_PROTO_FILES=( 34 src/google/protobuf/any_test.proto 35 src/google/protobuf/unittest_arena.proto 36 src/google/protobuf/unittest_custom_options.proto 37 src/google/protobuf/unittest_enormous_descriptor.proto 38 src/google/protobuf/unittest_embed_optimize_for.proto 39 src/google/protobuf/unittest_empty.proto 40 src/google/protobuf/unittest_import.proto 41 src/google/protobuf/unittest_import_lite.proto 42 src/google/protobuf/unittest_lite.proto 43 src/google/protobuf/unittest_mset.proto 44 src/google/protobuf/unittest_mset_wire_format.proto 45 src/google/protobuf/unittest_no_generic_services.proto 46 src/google/protobuf/unittest_optimize_for.proto 47 src/google/protobuf/unittest.proto 48 src/google/protobuf/unittest_import_public.proto 49 src/google/protobuf/unittest_import_public_lite.proto 50 src/google/protobuf/unittest_drop_unknown_fields.proto 51 src/google/protobuf/unittest_preserve_unknown_enum.proto 52 src/google/protobuf/map_lite_unittest.proto 53 src/google/protobuf/map_proto2_unittest.proto 54 src/google/protobuf/map_unittest.proto 55 # The unittest_custom_options.proto extends the messages in descriptor.proto 56 # so we build it in to test extending in general. The library doesn't provide 57 # a descriptor as it doesn't use the classes/enums. 58 src/google/protobuf/descriptor.proto 59) 60 61# ----------------------------------------------------------------------------- 62# The objc unittest specific proto files. 63 64OBJC_TEST_PROTO_FILES=( 65 objectivec/Tests/unittest_cycle.proto 66 objectivec/Tests/unittest_deprecated.proto 67 objectivec/Tests/unittest_deprecated_file.proto 68 objectivec/Tests/unittest_extension_chain_a.proto 69 objectivec/Tests/unittest_extension_chain_b.proto 70 objectivec/Tests/unittest_extension_chain_c.proto 71 objectivec/Tests/unittest_extension_chain_d.proto 72 objectivec/Tests/unittest_extension_chain_e.proto 73 objectivec/Tests/unittest_extension_chain_f.proto 74 objectivec/Tests/unittest_extension_chain_g.proto 75 objectivec/Tests/unittest_objc.proto 76 objectivec/Tests/unittest_objc_startup.proto 77 objectivec/Tests/unittest_objc_options.proto 78 objectivec/Tests/unittest_runtime_proto2.proto 79 objectivec/Tests/unittest_runtime_proto3.proto 80) 81 82OBJC_EXTENSIONS=( .pbobjc.h .pbobjc.m ) 83 84# ----------------------------------------------------------------------------- 85# Ensure the output dir exists 86mkdir -p "${OUTPUT_DIR}/google/protobuf" 87 88# ----------------------------------------------------------------------------- 89# Move to the top of the protobuf directories and ensure there is a protoc 90# binary to use. 91cd "${SRCROOT}/.." 92[[ -x src/protoc ]] || \ 93 die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)." 94 95# ----------------------------------------------------------------------------- 96RUN_PROTOC=no 97 98# Check to if all the output files exist (incase a new one got added). 99 100for PROTO_FILE in "${CORE_PROTO_FILES[@]}" "${OBJC_TEST_PROTO_FILES[@]}"; do 101 DIR=${PROTO_FILE%/*} 102 BASE_NAME=${PROTO_FILE##*/} 103 # Drop the extension 104 BASE_NAME=${BASE_NAME%.*} 105 OBJC_NAME=$(echo "${BASE_NAME}" | awk -F _ '{for(i=1; i<=NF; i++) printf "%s", toupper(substr($i,1,1)) substr($i,2);}') 106 107 for EXT in "${OBJC_EXTENSIONS[@]}"; do 108 if [[ ! -f "${OUTPUT_DIR}/google/protobuf/${OBJC_NAME}${EXT}" ]]; then 109 RUN_PROTOC=yes 110 fi 111 done 112done 113 114# If we haven't decided to run protoc because of a missing file, check to see if 115# an input has changed. 116if [[ "${RUN_PROTOC}" != "yes" ]] ; then 117 # Find the newest input file (protos, compiler, and this script). 118 # (these patterns catch some extra stuff, but better to over sample than 119 # under) 120 readonly NewestInput=$(find \ 121 src/google/protobuf/*.proto \ 122 objectivec/Tests/*.proto \ 123 src/.libs src/*.la src/protoc \ 124 objectivec/DevTools/compile_testing_protos.sh \ 125 -type f -print0 \ 126 | xargs -0 stat -f "%m %N" \ 127 | sort -n | tail -n1 | cut -f2- -d" ") 128 # Find the oldest output file. 129 readonly OldestOutput=$(find \ 130 "${OUTPUT_DIR}" \ 131 -type f -name "*.pbobjc.[hm]" -print0 \ 132 | xargs -0 stat -f "%m %N" \ 133 | sort -n -r | tail -n1 | cut -f2- -d" ") 134 # If the newest input is newer than the oldest output, regenerate. 135 if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then 136 RUN_PROTOC=yes 137 fi 138fi 139 140if [[ "${RUN_PROTOC}" != "yes" ]] ; then 141 # Up to date. 142 exit 0 143fi 144 145# ----------------------------------------------------------------------------- 146# Prune out all the files from previous generations to ensure we only have 147# current ones. 148find "${OUTPUT_DIR}" \ 149 -type f -name "*.pbobjc.[hm]" -print0 \ 150 | xargs -0 rm -rf 151 152# ----------------------------------------------------------------------------- 153# Helper to invoke protoc 154compile_protos() { 155 src/protoc \ 156 --objc_out="${OUTPUT_DIR}/google/protobuf" \ 157 --proto_path=src/google/protobuf/ \ 158 --proto_path=src \ 159 --experimental_allow_proto3_optional \ 160 "$@" 161} 162 163# ----------------------------------------------------------------------------- 164# Generate most of the proto files that exist in the C++ src tree. 165 166# Note: there is overlap in package.Message names between some of the test 167# files, so they can't be generated all at once. This works because the overlap 168# isn't linked into a single binary. 169for a_proto in "${CORE_PROTO_FILES[@]}" ; do 170 compile_protos "${a_proto}" 171done 172 173# ----------------------------------------------------------------------------- 174# Generate the Objective C specific testing protos. 175compile_protos \ 176 --proto_path="objectivec/Tests" \ 177 "${OBJC_TEST_PROTO_FILES[@]}" 178