Skip to content

Instantly share code, notes, and snippets.

@eyeplum
Last active September 27, 2021 03:56
Show Gist options
  • Save eyeplum/ff0b76f70ca5b8d192cac0b52496433d to your computer and use it in GitHub Desktop.
Save eyeplum/ff0b76f70ca5b8d192cac0b52496433d to your computer and use it in GitHub Desktop.
Build Google Protobuf C++ Runtime for iOS
#!/bin/bash
## Environments
# Exit the build pass if any command returns a non-zero value
#set -o errexit
# Echo commands
set -x
# 13.4.0 - Mavericks
# 14.0.0 - Yosemite
# 15.0.0 - El Capitan
# 16.0.0 - Sierra
DARWIN=darwin`uname -r`
MIN_SDK_VERSION=8.0
IPHONEOS_SYSROOT=`xcrun --sdk iphoneos --show-sdk-path`
IPHONESIMULATOR_SYSROOT=`xcrun --sdk iphonesimulator --show-sdk-path`
# Verbose clang output
#CLANG_VERBOSE="--verbose"
CC=clang
CXX=clang
SILENCED_WARNINGS="-Wno-unused-local-typedef -Wno-unused-function"
# NOTE: Google Protobuf does not currently build if you specify 'libstdc++'
# instead of `libc++` here.
STDLIB=libc++
CFLAGS="${CLANG_VERBOSE} ${SILENCED_WARNINGS} -DNDEBUG -g -O0 -pipe -fPIC -fcxx-exceptions"
CXXFLAGS="${CFLAGS} -std=c++11 -stdlib=${STDLIB}"
LDFLAGS="-stdlib=${STDLIB}"
LIBS="-lc++ -lc++abi"
PROTOC=`which protoc`
PROTOBUF_SOURCE_DIR=protobuf
PREFIX=`pwd`/../output/protobuf
if [ -d ${PREFIX} ]
then
rm -rf "${PREFIX}"
fi
mkdir -p "${PREFIX}/platform"
## Functions
build-arch() {
HOST=$1
ARCH=$2
PLATFORM_NAME=${ARCH}
SYSROOT=${IPHONEOS_SYSROOT}
make distclean
./configure \
--build=x86_64-apple-${DARWIN} \
--host=${HOST} \
--with-protoc=${PROTOC} \
--disable-shared \
--prefix=${PREFIX} \
--exec-prefix=${PREFIX}/platform/${PLATFORM_NAME} \
"CC=${CC}" \
"CFLAGS=${CFLAGS} -miphoneos-version-min=${MIN_SDK_VERSION} -arch ${ARCH} -isysroot ${SYSROOT}" \
"CXX=${CXX}" \
"CXXFLAGS=${CXXFLAGS} -miphoneos-version-min=${MIN_SDK_VERSION} -arch ${ARCH} -isysroot ${SYSROOT}" \
LDFLAGS="-arch ${ARCH} -miphoneos-version-min=${MIN_SDK_VERSION} ${LDFLAGS}" \
"LIBS=${LIBS}"
make -j8
make install
}
build-i386-simulator() {
ARCH=i386
HOST=${ARCH}-apple-${DARWIN}
PLATFORM_NAME=${ARCH}-simulator
SYSROOT=${IPHONESIMULATOR_SYSROOT}
make distclean
./configure \
--build=x86_64-apple-${DARWIN} \
--host=${HOST} \
--with-protoc=${PROTOC} \
--disable-shared \
--prefix=${PREFIX} \
--exec-prefix=${PREFIX}/platform/${PLATFORM_NAME} \
"CC=${CC}" \
"CFLAGS=${CFLAGS} -mios-simulator-version-min=${MIN_SDK_VERSION} -arch ${ARCH} -isysroot ${SYSROOT}" \
"CXX=${CXX}" \
"CXXFLAGS=${CXXFLAGS} -mios-simulator-version-min=${MIN_SDK_VERSION} -arch ${ARCH} -isysroot ${SYSROOT}" \
LDFLAGS="-arch ${ARCH} -mios-simulator-version-min=${MIN_SDK_VERSION} ${LDFLAGS}" \
"LIBS=${LIBS}"
make -j8
make install
}
build-x86_64-simulator() {
ARCH=x86_64
PLATFORM_NAME=${ARCH}-simulator
SYSROOT=${IPHONESIMULATOR_SYSROOT}
make distclean
./configure --prefix=${PREFIX} \
--exec-prefix=${PREFIX}/platform/${PLATFORM_NAME} \
--with-sysroot=${SYSROOT} \
--with-protoc=`which protoc` \
--enable-static \
--disable-shared
make -j8
make install
}
build-fat-lib() {
OUT=${PREFIX}/universal
mkdir -p ${OUT}
PLATFORM_ROOT=${PREFIX}/platform
LIPO=lipo
LIB=libprotobuf.a
${LIPO} ${PLATFORM_ROOT}/arm64/lib/${LIB} \
${PLATFORM_ROOT}/armv7/lib/${LIB} \
${PLATFORM_ROOT}/x86_64-simulator/lib/${LIB} \
${PLATFORM_ROOT}/i386-simulator/lib/${LIB} \
-create \
-output ${OUT}/${LIB}
LIB_LITE=libprotobuf-lite.a
${LIPO} ${PLATFORM_ROOT}/arm64/lib/${LIB_LITE} \
${PLATFORM_ROOT}/armv7/lib/${LIB_LITE} \
${PLATFORM_ROOT}/x86_64-simulator/lib/${LIB_LITE} \
${PLATFORM_ROOT}/i386-simulator/lib/${LIB_LITE} \
-create \
-output ${OUT}/${LIB_LITE}
}
## Build pass
cd ${PROTOBUF_SOURCE_DIR}
./autogen.sh
build-x86_64-simulator
build-i386-simulator
build-arch arm arm64
build-arch armv7-apple-${DARWIN} armv7
build-fat-lib
echo DONE!
@fzyzcjy
Copy link

fzyzcjy commented Sep 26, 2021

Hi I see the following error, could you please give some hints, thanks!

...
  CXX      google/protobuf/compiler/csharp/csharp_source_generator_base.lo
  CXX      google/protobuf/compiler/csharp/csharp_wrapper_field.lo
  CXXLD    libprotobuf-lite.la
  CXXLD    libprotobuf.la
ar: `u' modifier ignored since `D' is the default (see `U')
ar: `u' modifier ignored since `D' is the default (see `U')
In file included from google/protobuf/compiler/csharp/csharp_source_generator_base.cc:39:
./google/protobuf/compiler/csharp/csharp_source_generator_base.h:62:25: warning: private field 'descriptor_' is not used [-Wunused-private-field]
  const FileDescriptor* descriptor_;
                        ^
1 warning generated.
  CXXLD    libprotoc.la
ar: `u' modifier ignored since `D' is the default (see `U')
  CXXLD    protoc
ld: warning: ignoring file ./.libs/libprotobuf.a, building for iOS-armv7 but attempting to link with file built for iOS-armv7
ld: warning: ignoring file /Users/tom/RefCode/protobuf/src/.libs/libprotobuf.a, building for iOS-armv7 but attempting to link with file built for iOS-armv7
ld: warning: ignoring file ./.libs/libprotoc.a, building for iOS-armv7 but attempting to link with file built for unknown-unsupported file format ( 0x21 0x3C 0x61 0x72 0x63 0x68 0x3E 0x0A 0x2F 0x20 0x20 0x20 0x20 0x20 0x20 0x20 )
Undefined symbols for architecture armv7:
  "google::protobuf::compiler::objectivec::ObjectiveCGenerator::ObjectiveCGenerator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::objectivec::ObjectiveCGenerator::~ObjectiveCGenerator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::CodeGenerator::~CodeGenerator()", referenced from:
      google::protobuf::compiler::js::Generator::~Generator() in main.o
      google::protobuf::compiler::ruby::Generator::~Generator() in main.o
      google::protobuf::compiler::php::Generator::~Generator() in main.o
  "google::protobuf::compiler::CommandLineInterface::AllowPlugins(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::CommandLineInterface::RegisterGenerator(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::compiler::CodeGenerator*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::CommandLineInterface::Run(int, char const* const*)", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::CommandLineInterface::CommandLineInterface()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::CommandLineInterface::~CommandLineInterface()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::cpp::CppGenerator::CppGenerator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::cpp::CppGenerator::~CppGenerator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::java::JavaGenerator::JavaGenerator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::java::JavaGenerator::~JavaGenerator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::csharp::Generator::Generator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::csharp::Generator::~Generator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::python::Generator::Generator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "google::protobuf::compiler::python::Generator::~Generator()", referenced from:
      google::protobuf::compiler::ProtobufMain(int, char**) in main.o
  "vtable for google::protobuf::compiler::CodeGenerator", referenced from:
      google::protobuf::compiler::CodeGenerator::CodeGenerator() in main.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for google::protobuf::compiler::js::Generator", referenced from:
      google::protobuf::compiler::js::Generator::Generator() in main.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for google::protobuf::compiler::php::Generator", referenced from:
      google::protobuf::compiler::php::Generator::Generator() in main.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for google::protobuf::compiler::ruby::Generator", referenced from:
      google::protobuf::compiler::ruby::Generator::Generator() in main.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [protoc] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

@eyeplum
Copy link
Author

eyeplum commented Sep 27, 2021

Hey @fzyzcjy, sorry this gist is pretty outdated and I haven't tried building Profobuf for iOS for a long time.

By the look of the errors it looks like a bunch of symbols can't be found for armv7. Not really sure what's going on there. Just one thought though, will it work if you build for arm64? Since I believe armv7 is a really old architecture for the iOS devices (dates back to 32-bit Apple CPUs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment