I came across this unusual code in a tutorial I was using.
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
return CGFloat(sqrtf(Float(a)))
}
#endif
It looks nothing like the code I've been learning so far. I know it's a square root function but the hashtag? Something about my computer architecture?
Please explain it to me in simple terms.
#if condition
// Code in here
#endif
This is a conditional compilation directive - it is used to hide blocks of code from the compiler. The code in the block is only compiled if the condition is true.
It's supported in many languages, notably C and C++. It is often used to account for processor architecture and operating system differences - allowing one code-base to compile on many different platforms.
It can also be used to remove debugging/tracing code in a release build.
The condition is evaluated once at compile time, normally in an initial pass over the source code before the main compiler.
You can set those kind of conditional compilation directive for various purpose.
For example you might have an environnement for DEBUG and one for RELEASE, depending on which you wan't to compile your might not use the same functions / values.
In you case, #if !(arch(x86_64) || arch(arm64)) is to determine the architecture of your device (or simulator).
Indeed, some iDevice run 32bits and others 64bits (5S and newer). Float aren't represented the same way.
As #Martin wrote, you might not have to use this code anymore :)
Related
In Objective-C I had a bunch of compiler flags set in Build Settings -> Other C Flags that were being used in the code. For instance:
Flag => -DPortNumber = 1
And in code I was able to access it by #(PortNumber)
This doesn't work in Swift, and I'm not able to find an answer.
The -D flag to C compilers defines a preprocessor macro. There are no preprocessor macros in Swift. So if you're looking to do something like:
// compile with -DPORT_NUMBER 31337
var port = PORT_NUMBER // error
... you can't. Swift is designed for source code to be syntactically complete before compilation. If you could switch out blocks of it at build time, you'd break the ability of the toolchain to help verify that your code is correct. (Partly this is because preprocessor macros in C are textual replacement: you can use them to rewrite any part of the language, not just fill in values for variables.)
The Swift compiler does have a -D flag, but its use is more limited: you can use it for build configurations only. So, if you wanted to do something like the following, you'd be cool:
// compile with -DUSE_STAGING_SERVER
#if USE_STAGING_SERVER
var port = 31337
#else
var port = 80
#endif
Note that unlike C, everything inside an #if block needs to be syntactically complete. (For example, you can't put just the declaration line of a func in an #if block and leave the function body outside the conditional.)
Of course, this doesn't help you if you want to have a configuration value set at compile time be used in your code. For that, I'd recommend alternate approaches. Xcode can still do textual substitution in resource files, like property lists. (Note that the Info.plist that comes with your app is full of things like $(TARGET_NAME), for example.) So, you could include a bundle resource with your app whose contents are populated at compile time according to your project settings, then read your port number from that.
is is possible to use macros in config files? I want to achieve something like:
if iPad
set variable to 1
else
set variable to 0
Is that possible? I would rather not use scripts for this.
You generally should check this at runtime rather than compile time. See iOS - conditional compilation (xcode).
If you don't do it that way, I typically recommend using different targets as hinted at by #Robert Vojta.
That said, I can imagine cases where this would be useful in some piece of shared code. So...
There is an xcconfig variable you can use called TARGETED_DEVICE_FAMILY. It returns 1 for iPhone and iPod Touch, and 2 for iPad. This can be used to create a kind of macro. I don't highly recommend this approach, but here's how you do it. Let's say you were trying to set some value called SETTINGS:
// Family 1 is iPhone/iPod Touch. Family 2 is iPad
SettingsForFamily1 = ...
SettingsForFamily2 = ...
SETTINGS = $(SettingsForFamily$(TARGETED_DEVICE_FAMILY))
I've done this a few times in my projects (for other problems, not for iPad detection). Every time I've done it, a little more thought has allowed me to remove it and do it a simpler way (usually finding another way to structure my project to remove the need). But this is a technique for creating conditionals in xcconfig.
AFAIK it's not possible. But if you want to solve simple task - lot of common settings and just few variables have different values, you can do this:
generic.xcconfig:
settings for both configs
ipad.xcconfig:
#include "generic.xcconfig"
ipad-specific-settings
iphone.xcconfig
#include "generic.xcconfig"
iphone-specific-settings
This can solve your condition need. I do use this schema frequently.
That's not possible. Configuration files are not preprocessed (and compiled). What are you trying to do?
I have added some debugging code to my app which I want to call only when needed. I remember there is some kind of IFDEF that can be used to conditionally include code into a source file.
For example I might have something like this:
IFDEF kDebugEnabled == YES {
// some debugging code here
}
And then this piece of code is only compiled into the binary if that kDebugEnabled is YES.
How can I do something like this?
Please note: I don't want to use the project compiler flag settings. I just want to define a BOOL (or something that serves the purpose just as well) which is true or false and then just easily set it in my App Delegate for example. I find it hard to navigate to the project compiler settings, searching for a flag and then setting it. I know there is a Debug flag which might be of use.
What you are looking for is:
#ifdef __YOURSYMBOL__
<conditional code>
#endif
You can programmatically define __YOURSYMBOL__ like this:
#define __YOURSYMBOL__
__YOURSYMBOL__ can be any string that makes sense to you to remember why you are including/excluding that code snippet.
The DEBUG constant is a special preprocessor constant that the compiler defines specifically for you when the code is built for debugging, so you can simply use it:
#ifdef DEBUG
<conditional code>
#endif
Take into account that this is the C-preprocessor, not C, nor Objective-C that you are using, so a test like kDebugEnabled == YES (where kDebugEnabled is an Objective-C variable) is simply not possible. You can define integer values for your constants, like this:
#define __LOG_LEVEL__ 3
and then test for it:
#if __LOG_LEVEL__ == 3
...
Endif
As far as I know, you can't have code in your classes that is not compiled into the final product without using compiler flags. However, using the DEBUG flag is a lot easier than you think. If you are using Xcode 4, it's set up for you by default.
#ifdef DEBUG
// Your debug-only code goes here
#endif // DEBUG
Xcode has, by default, two configurations, Debug and Release. When you use the debug build configuration, among other things, it sets the DEBUG compiler flag, which you can then use to conditionally compile code. No need to mess with compilation settings at all.
I have a workspace built using MS-Visual Studio 2005 with all C code.In that i see many functions which are not called but they are still compiled(they are not under any compile time macro to disable them from compiling).
I set following optimization settings for the MS-VS2005 project to remove that unused code:-
Optimization level - /Ox
Enable whole program optimization - /GL
I tried both Favor speed /Ot and Favor Size /Os
Inspite of all these options, when i see the linker generated map file, I see the symbols(unsed functions) names present in the map file.
Am I missing something? I want to completely remove the unused code.
How do I do this?
The compiler compiles C files one-at-a-time. Therefore, while compiling a C-file that does contains an unused function, the compiler cannot be sure that it will not be called from another file and hence it will compile that function too. However, if that function were declared as static (file-scope), then the compiler would know it is not used and hence remove it.
Even with whole program optimization, I think it would still not be done since the compilation could be for a library.
Linkers do something similar to what you are looking for. If your code links against a library containing multiple objects, then any objects that do not contain functions used by your code (directly or indirectly) would not be included in the final executable.
One option would be to separate your code into individual libraries and object files.
PS - This is just my guess. The behavior of the compiler (with whole program optimization) or linker essentially depends on the design choices of that particular compiler or linker
On our projects we have a flag set under the project properties\Linker\Refrences. We set it to Eliminate Unreferenced Data (/OPT:REF), according to the description this is supposed to remove function calls or data that are never used. I am just going by the description, I have never tested this or worked with it. But I just happened to see it within the last hour and figured it might be something you could try.
os i figured out how to use the -mthumb and -mno-thumb compiler flag and more or less understand what it's doing.
But what is the -mthumb-interlinking flag doing? when is it needed, and is it set for the whole project if i set 'compile for thumb' in my project settings?
thanks for the info!
Open a terminal and type man gcc
Do you mean -mthumb-interwork ?
-mthumb-interwork
Generate code which supports calling between the ARM and Thumb
instruction sets. Without this option the two instruction sets
cannot be reliably used inside one program. The default is
-mno-thumb-interwork, since slightly larger code is generated when
-mthumb-interwork is specified.
If this is related to a build configuration, you should be able to set it separately for each configuration "such as Release or Debug".
Why do you want to change these settings? I know using thumb instructions save some memory but will it save enough to matter in this case?
my application uses both, thumb and vfp code but i never specifically
set -thumb-interwork flag.. how is that possible?
According to man page, without that flag the two instructions sets
cannot be reliably used inside one program.
It says "reliably"; so without that option, it seems they still can be mixed within a single program but it might be "unreliably". I think normally mixing both instructions sets works, the compiler is smart enough to figure out when it has to switch from one set to another one. However, there might be border cases the compiler just doesn't understand correctly and it might fail to see that it should switch instruction sets here, causing the application to fail (most likely it will crash). This option generates special code, so that no matter what your code does, the switching always happens correctly and reliably; the downside is that this extra code is needed for every global visible function and thus increases the binary side (I have no idea if it also might slow down function calls a little bit, I personally would expect that).
Please also note the following two settings:
-mcallee-super-interworking
Gives all externally visible functions in the file being
compiled an ARM instruction set header
which switches to Thumb mode before executing the rest of
the function. This allows these
functions to be called from non-interworking code.
-mcaller-super-interworking
Allows calls via function pointers (including virtual
functions) to execute correctly regardless
of whether the target code has been compiled for
interworking or not. There is a small overhead
in the cost of executing a function pointer if this option
is enabled.
Though I think you only need those, when building libraries to be used with other projects; but I don't know for sure. The GCC thumb handling is definitely "underdocumented".