Architecture-Specific Build Settings in Xcode 13 - ios

I'm trying to use architecture-specific build settings in my Xcode Framework so that I can handle the case of the Apple Silicon Mac and the Intel Mac separately. I need to use this build setting as a macro in Metal to check whether the half data type is supported on the CPU (it's supported on Apple Silicon but not supported on Intel).
My current implementation uses an xcconfig file with the following line:
IS_X86_64[arch=x86_64] = 1
Then, in my build settings I have the following user-defined condition (from the xcconfig):
I then create the macro IS_INTEL so it can be used in Metal:
Here's The Problem
In theory I feel like this should work. However, running my Metal app on my Intel mac yields 0 for IS_X86_64. The first thing I did was check whether I set up my build setting correctly and replaced
IS_X86_64[arch=x86_64] = 1
with
IS_X86_64[arch=*] = 1
This worked so I knew that the problem had to be that my current architecture wasn't being represented correctly. Diving further into why this was happening, it turns out that the value for CURRENT_ARCH (which should hold the value for the current device architecture that the project is being run on) is undefined_arch.
In their Xcode 10 release notes, apple mentioned something about undefined_arch saying:
The new build system passes undefined_arch as the value for the ARCH environment variable when running shell script build phases. The value was previously not well defined. Any shell scripts depending on this value must behave correctly for all defined architectures being built, available via the ARCHS environment variable.
However, I'm not building my project on the shell and I don't have any shell scripts.
Does anyone know how I can fix this so that architecture-specific build settings behave as they should?

You can check the architecture via built-in macros. You can see how they are used in usr/include/TargetConditionals.h:
#if __is_target_arch(x86_64)
...
#endif
More macros:
__is_target_arch(arm64)
__is_target_arch(arm64e)
__is_target_os(ios)
__is_target_environment(macabi)
__is_target_environment(simulator)

Related

Is there a way to fix an xcframework so it works on M1 and Intel simulators?

Edit: Selecting Xcode in Finder, getting info, and ticking the box for Open using Rosetta makes things work, but surely there is a better way…
I have an iOS project with a static framework containing three variants in it; ios-armv7_armv7s_arm64, ios-i386_x86_64-simulator, and ios-x86_64-maccatalyst. I do not have any access to the source code for this framework and asking for a new build of the framework is not a practical option. As a result I need to work with the xcframework that I have in hand.
The framework works just fine on my colleagues machines as they are using Intel based Macs. As a new addition to the team I have been given an M1 machine. While I can build to a physical device, building to the simulator fails with missing symbols. This makes complete sense given that the simulator variant doesn't have arm64 in it.
Simply adding a new definition to the info.plist to cover the M1 chip doesn't work as that means there are two simulator definitions. (There are also other issues with this route)
If I duplicate the ios-armv7_armv7s_arm64 folder, add -simulator to the copies name, and replace the existing definition for the simulator framework with info from the ios-armv7_armv7s_arm64 definition I get an error about building for the simulator but linking in a file built for iOS. This means that no matter what I can't simply copy the existing M1 framework to get things going.
The only things I can think of both involve the need to somehow edit the M1 copy of the compiled framework so that it will work on the simulator, and I rather doubt there is a way to do that. If it is possible to do though I would then need to either come up with some nested framework trick that allowed me to have two definitions for the simulator but for two different architectures; or I would need to write a script that used uname -m to decide how to edit the framework's info.plist file (This feels very hacky, but would be the simplest way of making the project 'just work' on both Intel and M1 machines without the need to make manual adjustments and remember not to commit them.
Anyone have any brilliant ideas on how to get this framework working in the simulator without having a new copy built? (I haven't even found a clear method for how it would need to be built to work on both architectures.)
Xcode: 13.3.1

Codename One iOS build error: Implicit declaration of function 'java_lang_NullPointerException___INIT___' is invalid in C99

I'm trying to build the iOS source code generated by the CodeName One build server. I specifically upgraded to the Basic account to have this feature.
I'm experiencing build errors on XCode 5.1.1 which are similar to this one:
/build/xcode/src/app/java_lang_NoSuchFieldError.m:227:5: Implicit
declaration of function 'java_lang_NullPointerException___INIT___' is invalid in C99
This is what I did:
Take a functioning CodenameOne app (mine didn't work so I also tried with KitchenSink with similar results)
I followed the steps from the guide in the how-do-i section
load the xcode project from dist
added everything from res
added selectively from btres: *.xib, *.a, *.res, *.strings
Additionally I had to change the architecture in: build settings / architectures / standard architectures
After that I hit the error above. The obvious solution is to declare functions before use, per the restrictions of the C99 language standard, but after including the required headers a few times I gave up.
The way I see it, this could happen because something else needs to be adjusted in the xcode project (I'm not too familiar with iOS development). Also it could be a code generation bug.
Any thoughts?
Use xcode 5.0 and not 5.1 which only works with the new VM. You can download older versions from Apples developer site.

Compiling and running the metal examples

It has been a while since I have used XCode, but since Apple revieled XCode 6 and the new Metal API I had to check it out.
They have released examples, e.g. a converted version of their Basic3D example. I am having problems making them compile and run, though. I had to add paths the Quatz and Metal frameworks for compilation and linking to work - thought that should have worked out of the box with build-in libraries?
Also the metal shader compilation step fails, it can not find the metal compiler. Where in XCode is that path setup?
If I ignore the shader compilation step I get an error that the application will not run on any of the simulators. Can metal based 3D applications only run on actual hardware and not in simulator mode?
According to a staff on Apple dev forums, Metal does not run in the simulator.
See: https://devforums.apple.com/message/971605#971605
If you look at other samples/app templates there is no need to explicitly link any framework, indeed everything runs out of the box.
You can't run metal on simulator but you can use this workaround so that it will still compile as long as you have a fallback for the code.
http://medium.com/#jscampbell/bare-metal-working-with-metal-and-the-simulator-70e085e3a45
I started with the hello triangle example they give you to download. It contains all the platform #if's you need to know about. I recommend you get that project and take a look.
https://developer.apple.com/documentation/metal/hello_triangle
#if TARGET_OS_SIMULATOR
#error No simulator support for Metal API. Must build for a device
#endif

(In iOS/OS X SDK's) Where are __i386__ and __x86_64__ defined?

In iOS and OS X SDK's, where are those architecture values defined?
The reason I am interested is because I used to conditionally compile code for the iOS Simulator as follows:
#ifdef __i386__
// Simulator-only code
#endif
And just noticed that I haven't updated it for the new 64-bit iOS Simulator by also checking for __x86_64__, and I'm also curious about other defines as there doesn't seem to be an official Apple documentation file for this.
Those values are defined by CLANG at compilation time depending on the target you happen to be building for, but were formalized by the GNU C spec for use in GCC.

Script for checking Build Mode in Xcode

I am creating a iOS Static Library in Xcode. I will be distributing two separate binaries, one for running in simulators(x86 architecture) & other for devices(ARM architecture).
I am aware of aggregate target, but I want to know whether it is possible to write a script to check whether the code is running in Debug or Release mode, i.e in Simulator(debug) or Device(Release) in ideal scenario.
Depending on this, I can put some check in my respective binary to compile or not.
Devices do not run in debug or release. The user chooses to build their target in debug or release. You can supply a debug version of your library, if you'd like, though. That is something I have seen other vendors do, and is greatly appreciated by developers.

Resources