firebase/firebase-cpp-sdk

iOS: How to build universal libs

frankosterfeld opened this issue · 5 comments

The release builds available at https://firebase.google.com/download/cpp contain universal builds for iOS, supporting both arm64 and x86_64, among others.

For easier debugging of a firebase-based app in the iOS simulator, I'd like to do an x86_64 or even better "universal" debug build of firebase-cpp-sdk. The iOS instructions in the README are using a CMake toolchain file that only builds for arm64. Trying to replace "arm64" by "x86_64" in the toolchain file already fails when building flatbuffers.

Could you please document how to compile firebase-cpp-sdk for iOS/x86_64?
Ideally I would like to be able to reproduce the iOS part of the official .zip, just with -DCMAKE_BUILD_TYPE=Debug

Hi @frankosterfeld

What is the problem you are seeing when you replace x86_64? With the CMAKE_XCODE_EFFECTIVE_PLATFORMS taking in -iphonesimulator, it should be fine using that.

Unfortunately, building the universal libraries is a bit tricky. Internally we build for all the different platforms, and use the lipo command line tool to combine them together into a universal library. We do want to eventually include a script that reproduces the same layout and libraries as the release build, but because of the number of targets and platforms involved, it might be a while until it is available.

The modified toolchain file I used:

diff --git a/cmake/ios.cmake b/cmake/ios.cmake
index 7c89dcc..0e11dcd 100644
--- a/cmake/ios.cmake
+++ b/cmake/ios.cmake
@@ -13,8 +13,8 @@
 # limitations under the License.
 
 set(CMAKE_OSX_SYSROOT iphoneos)
-set(CMAKE_OSX_ARCHITECTURES "arm64")
-set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator")
+set(CMAKE_OSX_ARCHITECTURES "x86_64")
+set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
 set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO")
 set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES")
 
@@ -23,4 +23,4 @@ set(CMAKE_CXX_COMPILER_WORKS TRUE)
 set(CMAKE_C_COMPILER_WORKS TRUE)
 
 # force MAC_BUNDLE for executable
-#set(CMAKE_MACOSX_BUNDLE YES)
\ No newline at end of file
+#set(CMAKE_MACOSX_BUNDLE YES)

Then:

mkdir build_ios
cd build_ios
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_BUILD_TYPE=Debug ..
# with the iPhoneOS build, running cmake twice somehow made errors go away...
cmake --build . --target firebase_app

It gets the cocoapods, clones flatbuffers, starts compiling flatbuffers, builds flatbuffers once (for iPhoneOS??), then starts again to build flatbuffers but fails:

[  4%] Building CXX object external/src/flatbuffers-build/CMakeFiles/flatbuffers.dir/src/code_generators.cpp.o
In file included from /Users/frank/source/firebase-cpp-sdk/build_ios/external/src/flatbuffers/src/code_generators.cpp:17:
In file included from /Users/frank/source/firebase-cpp-sdk/build_ios/external/src/flatbuffers/include/flatbuffers/code_generators.h:20:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/map:455:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__tree:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:416:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iosfwd:90:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/wchar.h:119:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/usr/include/wchar.h:70:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/usr/include/_types.h:27:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/usr/include/sys/_types.h:32:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/usr/include/sys/cdefs.h:784:2: error: Unsupported architecture
#error Unsupported architecture

From the include, it looks like it includes iOS headers, not simulator headers.

This is Xcode 10.2.1, CMake 3.14.5

With VERBOSE=1 the call is:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++   -I/Users/frank/source/firebase-cpp-sdk/build_ios/external/src/flatbuffers/include -I/Users/frank/source/firebase-cpp-sdk/build_ios/external/src/flatbuffers/grpc  -g -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk   -std=gnu++11 -o CMakeFiles/flatbuffers.dir/src/code_generators.cpp.o -c /Users/frank/source/firebase-cpp-sdk/build_ios/external/src/flatbuffers/src/code_generators.cpp

Hi @frankosterfeld at the moment with the existing cmake build, all you can do is build for each architecture then combine the libraries using lipo. It may be possible to plumb in something like https://github.com/leetal/ios-cmake in your environment but I literally landed on the page via Google search, no additional effort has gone into evaluating that project.

We will be adding support for packaging open source C++ SDK builds similar to what we do internally, including the symbol mangling we do for 3rd party libraries. We'll update this issue when we have something.

@frankosterfeld the compile error you're running into is because you're including a file from the iPhoneSDK directory, which only supports iPhone build archs. You should be including the header from iPhoneSimulator.platform, whose path is something like this:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/...

As Stewart mentioned, the only way to create a universal framework for Apple platforms is to build each architecture individually and then lipo the result.