I am trying to create an iOS
plugin for Godot Game Engine
. Now my plugin requires integration with FirebaseAuth
so I created a Podfile and added those dependencies. Here is the complete source code
This is my SConstruct
file
#!/usr/bin/env python
import os
import sys
import subprocess
if sys.version_info < (3,):
def decode_utf8(x):
return x
else:
import codecs
def decode_utf8(x):
return codecs.utf_8_decode(x)[0]
# Most of the settings are taken from https://github.com/BastiaanOlij/gdnative_cpp_example
opts = Variables([], ARGUMENTS)
# Gets the standard flags CC, CCX, etc.
env = DefaultEnvironment()
# Define our options
opts.Add(EnumVariable('target', "Compilation target", 'debug', ['debug', 'release', "release_debug"]))
opts.Add(EnumVariable('arch', "Compilation Architecture", '', ['', 'arm64', 'armv7', 'x86_64']))
opts.Add(BoolVariable('simulator', "Compilation platform", 'no'))
opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no'))
opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'bin/'))
opts.Add(EnumVariable('plugin', 'Plugin to build', '', ['', 'arithematic']))
opts.Add(EnumVariable('version', 'Godot version to target', '', ['', '3.x', '4.0']))
# Updates the environment with the option variables.
opts.Update(env)
# Process some arguments
if env['use_llvm']:
env['CC'] = 'clang'
env['CXX'] = 'clang++'
if env['arch'] == '':
print("No valid arch selected.")
quit();
if env['plugin'] == '':
print("No valid plugin selected.")
quit();
if env['version'] == '':
print("No valid Godot version selected.")
quit();
# For the reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags
# Enable Obj-C modules
env.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])
if env['simulator']:
sdk_name = 'iphonesimulator'
env.Append(CCFLAGS=['-mios-simulator-version-min=10.0'])
env.Append(LINKFLAGS=["-mios-simulator-version-min=10.0"])
else:
sdk_name = 'iphoneos'
env.Append(CCFLAGS=['-miphoneos-version-min=10.0'])
env.Append(LINKFLAGS=["-miphoneos-version-min=10.0"])
try:
sdk_path = decode_utf8(subprocess.check_output(['xcrun', '--sdk', sdk_name, '--show-sdk-path']).strip())
except (subprocess.CalledProcessError, OSError):
raise ValueError("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
env.Append(CCFLAGS=[
'-fobjc-arc',
'-fmessage-length=0', '-fno-strict-aliasing', '-fdiagnostics-print-source-range-info',
'-fdiagnostics-show-category=id', '-fdiagnostics-parseable-fixits', '-fpascal-strings',
'-fblocks', '-fvisibility=hidden', '-MMD', '-MT', 'dependencies', '-fno-exceptions',
'-Wno-ambiguous-macro',
'-Wall', '-Werror=return-type',
# '-Wextra',
])
env.Append(CCFLAGS=['-arch', env['arch'], "-isysroot", "$IOS_SDK_PATH", "-stdlib=libc++", '-isysroot', sdk_path])
env.Append(CCFLAGS=['-DPTRCALL_ENABLED'])
env.Prepend(CXXFLAGS=[
'-DNEED_LONG_INT', '-DLIBYUV_DISABLE_NEON',
'-DIOS_ENABLED', '-DUNIX_ENABLED', '-DCOREAUDIO_ENABLED'
])
env.Append(LINKFLAGS=["-arch", env['arch'], '-isysroot', sdk_path, '-F' + sdk_path])
if env['arch'] == 'armv7':
env.Prepend(CXXFLAGS=['-fno-aligned-allocation'])
if env['version'] == '3.x':
env.Append(CCFLAGS=["$IPHONESDK"])
env.Prepend(CXXFLAGS=['-DIPHONE_ENABLED'])
env.Prepend(CXXFLAGS=['-DVERSION_3_X'])
env.Prepend(CFLAGS=['-std=gnu11'])
env.Prepend(CXXFLAGS=['-DGLES_ENABLED', '-std=gnu++14'])
if env['target'] == 'debug':
env.Prepend(CXXFLAGS=[
'-gdwarf-2', '-O0',
'-DDEBUG_MEMORY_ALLOC', '-DDISABLE_FORCED_INLINE',
'-D_DEBUG', '-DDEBUG=1', '-DDEBUG_ENABLED',
'-DPTRCALL_ENABLED',
])
elif env['target'] == 'release_debug':
env.Prepend(CXXFLAGS=['-O2', '-ftree-vectorize',
'-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1', '-DDEBUG_ENABLED',
'-DPTRCALL_ENABLED',
])
if env['arch'] != 'armv7':
env.Prepend(CXXFLAGS=['-fomit-frame-pointer'])
else:
env.Prepend(CXXFLAGS=[
'-O2', '-ftree-vectorize',
'-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1',
'-DPTRCALL_ENABLED',
])
if env['arch'] != 'armv7':
env.Prepend(CXXFLAGS=['-fomit-frame-pointer'])
elif env['version'] == '4.0':
env.Append(CCFLAGS=["$IOS_SDK_PATH"])
env.Prepend(CXXFLAGS=['-DIOS_ENABLED'])
env.Prepend(CXXFLAGS=['-DVERSION_4_0'])
env.Prepend(CFLAGS=['-std=gnu11'])
env.Prepend(CXXFLAGS=['-DVULKAN_ENABLED', '-std=gnu++17'])
if env['target'] == 'debug':
env.Prepend(CXXFLAGS=[
'-gdwarf-2', '-O0',
'-DDEBUG_MEMORY_ALLOC', '-DDISABLE_FORCED_INLINE',
'-D_DEBUG', '-DDEBUG=1', '-DDEBUG_ENABLED',
])
elif env['target'] == 'release_debug':
env.Prepend(CXXFLAGS=[
'-O2', '-ftree-vectorize',
'-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1', '-DDEBUG_ENABLED',
])
if env['arch'] != 'armv7':
env.Prepend(CXXFLAGS=['-fomit-frame-pointer'])
else:
env.Prepend(CXXFLAGS=[
'-O2', '-ftree-vectorize',
'-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1',
])
if env['arch'] != 'armv7':
env.Prepend(CXXFLAGS=['-fomit-frame-pointer'])
else:
print("No valid version to set flags for.")
quit();
# Adding header files
if env['version'] == '3.x':
env.Append(CPPPATH=[
'.',
'godot',
'godot/platform/iphone',
])
else:
env.Append(CPPPATH=[
'.',
'godot',
'godot/platform/ios',
])
sources = Glob('arithematic/*.cpp')
sources.append(Glob('arithematic/*.mm'))
sources.append(Glob('arithematic/*.m'))
library_platform = env["arch"] + "-" + ("simulator" if env["simulator"] else "iphone")
library_name = env['plugin'] + "." + library_platform + "." + env["target"] + ".a"
library = env.StaticLibrary(target=env['target_path'] + library_name, source=sources)
If I run scons target=release_debug arch=arm64 plugin=arithematic version=4.0
I get error saying
In file included from arithematic/arithematic.mm:16:
arithematic/arithematic.h:19:9:{19:9-19:38}: fatal error: 'FirebaseCore/FirebaseCore.h' file not found [1]
#import <FirebaseCore/FirebaseCore.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
scons: *** [arithematic/arithematic.o] Error 1
scons: building terminated because of errors.
Default(library)
# Generates help for the -h scons option.
Help(opts.GenerateHelpText(env))
then I added
sources.append(Glob('Pods/FirebaseCore/FirebaseCore/Sources/*.m'))
sources.append(Glob('Pods/FirebaseAuth/FirebaseAuth/Sources/*.m'))
and ran the command again but now I get
Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m:17:9:{17:9-17:59}: fatal error: 'FirebaseCore/Sources/FIRAnalyticsConfiguration.h' file not found [1]
#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
scons: *** [Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.o] Error 1
scons: building terminated because of errors.
Is there a way to include the entire Pods
folder as there are multiple sub directories within directories
Also I tried
def collect_sources(directory, extensions):
sources = []
for root, _, files in os.walk(directory):
for file in files:
if file.endswith(extensions):
sources.append(os.path.join(root, file))
return sources
pod_sources = collect_sources('Pods', ('.m', '.mm', '.cpp', '.h'))
sources.extend(pod_sources)
but it gives error saying
Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m:17:9:{17:9-17:59}: fatal error: 'FirebaseCore/Sources/FIRAnalyticsConfiguration.h' file not found [1]
#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
scons: *** [Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.o] Error 1
scons: building terminated because of errors.
EDIT:
Compile CommandLine:
Command: gcc -o Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.o -c -std=gnu11 -fmodules -fcxx-modules -miphoneos-version-min=10.0 -fobjc-arc -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -fno-exceptions -Wno-ambiguous-macro -Wall -Werror=return-type -arch arm64 -isysroot -stdlib=libc++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk -DPTRCALL_ENABLED -I. -Igodot -Igodot/platform/ios Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m
Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m:17:9:{17:9-17:59}: fatal error: 'FirebaseCore/Sources/FIRAnalyticsConfiguration.h' file not found [1]
EDIT 2:
Include FirebaseCore
in include paths
So I added below code to SConstruct
def find_include_dirs(root_dir):
include_dirs = []
for dirpath, dirnames, filenames in os.walk(root_dir):
if any(filename.endswith('.h') for filename in filenames):
include_dirs.append(dirpath)
return include_dirs
include_dirs = find_include_dirs('Pods')
env.Append(CPPPATH=include_dirs)
Here is the command line
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
gcc -o Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.o -c -std=gnu11 -fmodules -fcxx-modules -miphoneos-version-min=16.0 -fobjc-arc -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -fno-exceptions -Wno-ambiguous-macro -Wall -Werror=return-type -arch arm64 -isysroot -stdlib=libc++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk -DPTRCALL_ENABLED -I. -Igodot -Igodot/platform/ios -IPods/FirebaseCore/FirebaseCore/Extension -IPods/FirebaseCore/FirebaseCore/Sources -IPods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore -IPods/RecaptchaInterop/RecaptchaEnterprise/RecaptchaInterop/Public/RecaptchaInterop -IPods/PromisesObjC/Sources/FBLPromises/include "-IPods/Target Support Files/FirebaseCore" "-IPods/Target Support Files/RecaptchaInterop" "-IPods/Target Support Files/PromisesObjC" "-IPods/Target Support Files/FirebaseAuth" "-IPods/Target Support Files/FirebaseAppCheckInterop" "-IPods/Target Support Files/GTMSessionFetcher" "-IPods/Target Support Files/FirebaseCoreInternal" "-IPods/Target Support Files/Pods-arithematic" "-IPods/Target Support Files/GoogleUtilities" -IPods/FirebaseAuth/FirebaseCore/Extension -IPods/FirebaseAuth/FirebaseAuth/Interop -IPods/FirebaseAuth/FirebaseAuth/Sources/Auth -IPods/FirebaseAuth/FirebaseAuth/Sources/SystemService -IPods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor -IPods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/Phone -IPods/FirebaseAuth/FirebaseAuth/Sources/MultiFactor/TOTP -IPods/FirebaseAuth/FirebaseAuth/Sources/User -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/Phone -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/Proto/TOTP -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Enroll -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/SignIn -IPods/FirebaseAuth/FirebaseAuth/Sources/Backend/RPC/MultiFactor/Unenroll -IPods/FirebaseAuth/FirebaseAuth/Sources/Storage -IPods/FirebaseAuth/FirebaseAuth/Sources/Utilities -IPods/FirebaseAuth/FirebaseAuth/Sources/Public/FirebaseAuth -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GameCenter -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Twitter -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/OAuth -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Google -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/GitHub -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Facebook -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Phone -IPods/FirebaseAuth/FirebaseAuth/Sources/AuthProvider/Email -IPods/FirebaseAppCheckInterop/FirebaseAppCheck/Interop/Public/FirebaseAppCheckInterop -IPods/GTMSessionFetcher/Sources/Core -IPods/GTMSessionFetcher/Sources/Core/Public/GTMSessionFetcher -IPods/GoogleUtilities/third_party/IsAppEncrypted/Public -IPods/GoogleUtilities/GoogleUtilities/Logger/Public/GoogleUtilities -IPods/GoogleUtilities/GoogleUtilities/Network -IPods/GoogleUtilities/GoogleUtilities/Network/Public/GoogleUtilities -IPods/GoogleUtilities/GoogleUtilities/Common -IPods/GoogleUtilities/GoogleUtilities/Reachability -IPods/GoogleUtilities/GoogleUtilities/Reachability/Public/GoogleUtilities -IPods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal -IPods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Public/GoogleUtilities -IPods/GoogleUtilities/GoogleUtilities/Environment/Public/GoogleUtilities -IPods/GoogleUtilities/GoogleUtilities/NSData+zlib/Public/GoogleUtilities Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m
Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m:17:9:{17:9-17:59}: fatal error: 'FirebaseCore/Sources/FIRAnalyticsConfiguration.h' file not found [1]
#import "FirebaseCore/Sources/FIRAnalyticsConfiguration.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
scons: *** [Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.o] Error 1
scons: building terminated because of errors.
Looks like you want to compile FirebaseCore/FirebaseAuth from the sources pulled by Cocoapods. Cocoapods is meant to be integrated by Xcode, and if you want to compile your static library from the source codes of Firebase, It's possible, but I guess we should learn the podspec of Firebase. It is just too complicated.
It is better to link against the compiled xcframeworks from Firebase:
Then I downloaded the compiled xcframeworks, removed the cocoapods, the xcworkspace project and other unnecessary files. Made some changes to your Sconstruct file:
if env['simulator']:
env.Append(LIBPATH=['Firebase/FirebaseAuth.xcframework/ios-arm64_x86_64-simulator'])
env.Append(CPPPATH=['Firebase/FirebaseAuth.xcframework/ios-arm64_x86_64-simulator/FirebaseAuth.framework/Headers'])
env.Append(LIBPATH=['Firebase/FirebaseCore.xcframework/ios-arm64_x86_64-simulator/FirebaseCore.framework'])
env.Append(CPPPATH=['Firebase/FirebaseCore.xcframework/ios-arm64_x86_64-simulator/FirebaseCore.framework/Headers'])
else:
env.Append(LIBPATH=['Firebase/FirebaseAuth.xcframework/ios-arm64'])
env.Append(CPPPATH=['Firebase/FirebaseAuth.xcframework/ios-arm64/FirebaseAuth.framework/Headers'])
env.Append(LIBPATH=['Firebase/FirebaseCore.xcframework/ios-arm64/FirebaseCore.framework'])
env.Append(CPPPATH=['Firebase/FirebaseCore.xcframework/ios-arm64/FirebaseCore.framework/Headers'])
You will also need to change angled imports to quoted include:
// #import <FirebaseCore/FirebaseCore.h>
// #import <FirebaseAuth/FirebaseAuth.h>
#include "FirebaseCore.h"
#include "FirebaseAuth.h"
After these modifications you can compile the project.
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o arithematic/arithematic.o -c -fomit-frame-pointer -O2 -ftree-vectorize -DNDEBUG -DNS_BLOCK_ASSERTIONS=1 -DDEBUG_ENABLED -DVULKAN_ENABLED -std=gnu++17 -DVERSION_4_0 -DIOS_ENABLED -DNEED_LONG_INT -DLIBYUV_DISABLE_NEON -DIOS_ENABLED -DUNIX_ENABLED -DCOREAUDIO_ENABLED -fmodules -fcxx-modules -miphoneos-version-min=10.0 -fobjc-arc -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -fvisibility=hidden -MMD -MT dependencies -fno-exceptions -Wno-ambiguous-macro -Wall -Werror=return-type -arch arm64 -isysroot -stdlib=libc++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk -DPTRCALL_ENABLED -I. -Igodot -Igodot/platform/ios -IFirebase/FirebaseAuth.xcframework/ios-arm64/FirebaseAuth.framework/Headers -IFirebase/FirebaseCore.xcframework/ios-arm64/FirebaseCore.framework/Headers arithematic/arithematic.mm
scons: `bin/libarithematic.arm64-iphone.release_debug.a' is up to date.
scons: done building targets.
BTW, above workaround is in this github Repo