How to compile Swift with Scons?

Godot Version

4.2.2

Question

I am trying to create an iOS plugin for Godot Game Engine. For that I need to create a static library. I am trying to call my swift code from objective-c++. Here is the source code

I am trying to call my swift code from arithematic.mm

I have created the Bridging Header for my swift file and included it in arithematic.mm

#import "arithematic-Swift.h"

Now Godot requires scons to build the ‘.a’ file from a static library, to do that we need to run scons target=release_debug arch=arm64 plugin=arithematic version=4.0 but as soon as I run it I get error saying

arithematic/arithematic.mm:10:9:{10:9-10:30}: fatal error: 'arithematic-Swift.h' file not found [1]
 #import "arithematic-Swift.h"
         ^~~~~~~~~~~~~~~~~~~~~
1 error generated.
scons: *** [arithematic/arithematic.o] Error 1
scons: building terminated because of errors. 

Now I also have a SConstruct file which I am guessing is causing the issue

#!/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=16.0'])
    env.Append(LINKFLAGS=["-mios-simulator-version-min=16.0"])
else:
    sdk_name = 'iphoneos'
    env.Append(CCFLAGS=['-miphoneos-version-min=16.0'])
    env.Append(LINKFLAGS=["-miphoneos-version-min=16.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',
    ])

# tweak this if you want to use different folders, or more folders, to store your source code in.
# sources = Glob('plugin/' + env['plugin'] + '/*.mm')
# sources.append(Glob('plugin/' + env['plugin'] + '/*.mm'))
# sources.append(Glob('plugin/' + env['plugin'] + '/*.m'))


sources = Glob('arithematic/*.cpp')
sources.append(Glob('arithematic/*.mm'))
sources.append(Glob('arithematic/*.m'))



# lib<plugin>.<arch>-<simulator|ios>.<release|debug|release_debug>.a
# library_platform = env["arch"] + "-" + ("simulator" if env["simulator"] else ("iphone" if env['version'] == '3.x' else "ios"))
# library_name = env['plugin'] + "." + library_platform + "." + env["target"] + ".a"
# library = env.StaticLibrary(target=env['target_path'] + library_name, source=sources)

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)

Default(library)

# Generates help for the -h scons option.
Help(opts.GenerateHelpText(env))

As you can see above it does not know how to compile the Bridging-Header and swift file

Here is what I tried adding in the above SConstruct file

# 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/*.h'))
sources.append(Glob('arithematic/*.mm'))
sources.append(Glob('arithematic/*.m'))
sources.append(Glob('arithematic/*.swift'))

# ...

env.Append(CCFLAGS=['-swiftc', '-import-objc-header', 'arithematic-Swift.h'])
env.Append(LINKFLAGS=['-swiftc', '-import-objc-header', 'arithematic-Swift.h'])
env['SWIFTCOM'] = 'swiftc'

# ...

It results in even more errors as I don’t have enough experience in scons

I tried adding this path /Users/Desktop/samples/Godot/mytrial/work/plugin/arithematic to CPPPATH in SConstruct but same issue. Also tried /Users/Desktop/samples/Godot/mytrial/work/plugin/arithematic/arithematic-Swift.h and /Users/Desktop/samples/Godot/mytrial/work/plugin/arithematic/arithematic-Bridging-Header.h