Complicated conditional macro: force OR evaluation without latter definition existance - objective-c

My service is included in 2 different platforms source files (iOS and watchOS), but I only want it to be compiled for watchOS platform only when a specified flag is set
Under main platform (iOS): alway include content
Under extension. Only include content when BUILD_FLAG(watch_feature) is 1
BUILD_FLAG is defined in config.h. config.h is always available under watchOS, but sometime not available under iOS platform.
TARGET_OS_IOS is always available to detect which platform the file is included
What I want is something like
#include "config.h"
#if TARGET_OS_IOS || BUILD_FLAG(watch_feature)
<content>
#endif
And sometime compiler complains config.h does not exist when compiling for iOS platform.
Here is my solution, but it is long. If anyone has better ideal, always welcome
Solution 1:
#if TARGET_OS_IOS
#if !defined(BUILD_FLAG)
#define MARKER
#define BUILD_FLAG(_) 1
#endif
#else
#include "config.h"
#endif
#if TARGET_OS_IOS || BUILD_FLAG(watch_feature)
#if defined(MARKER)
#undef MARKER
#undef BUILD_FLAG
#endif
<file content>
#endif

Related

Swift's canImport analogue in Objective-C

Swift 4.2 has a special condition canImport that helps developers to check whether a module can be imported in project. It was introduced in Swift 4.1.
Now I am working on iOS project written in Objective-C. I use modules, and for each target these modules are different. That's why I want to use something like that:
#if canImport(SomeModule)
#import SomeModule;
#endif
How can I solve this problem? Now I use different "Other C Flags" for each target, but I want to find more flexible solution.
This is a little late as an answer, but i came across this issue while working on a similar case.
I used the __has_include(<SomeModule/SomeModule.h>)
Importing your framework:
#if __has_include(<SomeModule/SomeModule.h>)
#import <SomeModule/SomeModule.h>
#define __HAS_SOME_MODULE_FRAMEWORK__
#endif
Later in your code :
- (void)doSomething {
#ifdef __HAS_SOME_MODULE_FRAMEWORK__
// with SomeModule framework
#else
// without SomeModule framework
#endif
}

Error message "could not build module 'Foundation'"

I searched for this question and could not find much help.
Error:
could not build module 'Foundation'
#import <Foundation/Foundation.h>
What is the problem?
I was able to solve this using the solution provided in this Apple Support Communities thread:
The real problem here is at Build Settings in the session: Apple LLVM 5.0 - Language - Modules, we should set Enable Modules (C and Objective C) to NO
The suggested fix to set Enable Modules (C and Objective-C) did not solve this issue for me.
What did is renaming my someFile.c files to someFile.m. Even though those files contain just C functions (that do use Foundation types), naming them .c produces this error.
I found that if you use some external C / C++ code in your project, you have to remove all the #import in the prefix. That's quite a headache, but it's a true problem.
Cmd + Option + Shift + K and then Cmd + Option + K solved above error for me.
In my case I had a Precompiled Header where I had includes that included <Foundation/Foundation.h> The solution for me was to wrap the include in a
#ifdef __OBJC__
#include SomeIncludeWithFoundation.h
#endif
You may also see in your .pch files something like:
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
Be sure your modules are included in the right place in your Precompiled Header
None of the given solutions worked for me.
I have a project with mixed source codes (C and Objective-C) and the problem was given by a .c which included a shared .h which in turn included the Foundation header:
#import <Foundation/Foundation.h>
In order to solve the problem I had to perform the following steps:
In the .c that was causing the problem add as first include/import statement: #import <Foundation/Foundation.h> You can keep the same import statement in the shared header if you need.
In the project settings select the entry under Targets then click
on Build Phases -> Compile Sources. In the Compiler Flags
add -x objective-c. This will force the compilation of the C source code as Objective-C to allow the linking with the Foundation framework and since Objective-C can embed C source code this is perfectly legal.
In the project settings select the entry under Targets then click on Build Phases -> Link Binary With Libraries. Add the Foundation.framework library in the list.
You can try this:
In your .pch file, write like this:
#ifndef PureStandard_PrefixHeader_pch
#define PureStandard_PrefixHeader_pch
#ifdef __OBJC__
#import "A.h"
#import "B.h"
#endif
#endif
I have resolved by change Build System to Legacy Build System
Open the ios/PROJECT_NAME.workspace file
Then in the top menu, select File → Workspace Settings
Then change Build System to Legacy Build System
From this answer:
Set Allow Non-modular Includes in Framework Modules to YES in target's Build Settings
I was seeing the issue on this line in a .m file that is being built as part of an extension:
#import <Foundation/Foundation.h>
So I had the same problem, but the errors would for some reason not cause the build to fail, so they were like fake errors, and I made them go away by quitting Xcode, and deleting ~/Library/Developer/Xcode/DerivedData/ProjectName
Just rename your Objective-C++ file from *.c to *.mm.
The errors are gone that way. It handles all the imports just fine this way.
Use the following:
Cmd + Alt + Shift + K and then Cmd + Alt + K
Menu File → Workspace Settings → Legacy Build System
Cmd + B
It works for me.

Glew not compiling in Xcode

I tried using the Glew Library for shading and was trying to compile a simple program using the NSOpenGLView Class in Xcode 5. The program fails at the following code in glew.h
#if defined(__gltypes_h_)
#error gltypes.h included before glew.h
#endif
It says that Gltypes.h is included before glew.h.
My implementation file for OpenGLView has headers included in following fashion:
#include <glew.h>
#import "OpenGLView.h" // Includes Cocoa.h
#include "LoadShaders.h" // Includes <OpenGL/gl.h>
So, if glew.h is included in the beginning, why is the error coming here. None of the other headers are included before the inclusion of glew.h, so tests for them(like gl.h) are passing in glew.h. I am not able to find out here as to who is including Gltypes.h in this file.
Hope anyone has a clue to it here.
The precompiled header file (.pch) pulls Cocoa in. Edit it to include glew.h before Cocoa.h and you are good to go.

Cocoa preprocessor exit file

I've seen some compilers that lets you stop reading the file where ever in the file you want
and I want to know if obj-c has such thing here's an example, so you can understand:
#ifndef __OBJC__ // or #if !defined(__OBJC__)
#exit // do not continue compiling this file!
#endif
No, you can't simply stop compilation in the middle of the file. You'd have to structure it this way:
#if __OBJC__
// the rest of the file
#endif

How do I declare a debug only statement

In C# I can use the following code to have code which only executes during debug build, how can I do the same in Xcode?
#if DEBUG
{
// etc etc
}
#endif
You can use
#ifdef DEBUG
....
#endif
You'll need to add DEBUG=1 to the project's preprocessor symbol definitions in the Debug configuration's settings as that's not done for you automatically by Xcode.
I personally prefer doing DEBUG=1 over checking for NDEBUG=0, since the latter implies that the default build configuration is with debug information which you then have to explicitly turn off, whereas 'DEBUG=1' implies turning on debug only code.
The NDEBUG symbol should be defined for you already in release mode builds
#ifndef NDEBUG
/* Debug only code */
#endif
By using NDEBUG you just avoid having to specify a -D DEBUG argument to the compiler yourself for the debug builds
DEBUG is now defined in "debug mode" by default under Project/Preprocessor Macros. So testing it always works unless you have a very old project.
However I hate the fact that it messes up the code indentation and not particularly compact. That is why I use another macro which makes life easier.
#ifdef DEBUG
#define DEBUGMODE YES
#else
#define DEBUGMODE NO
#endif
So testing the DEBUGMODE value is much more compact:
if (DEBUGMODE) {
//do this
} else {
//do that
}
My favourite:
NSTimeInterval updateInterval = DEBUGMODE?60:3600;
There is a very useful debugging technote: Technical Note TN2124 Mac OS X Debugging Magic
http://developer.apple.com/technotes/tn2004/tn2124.html#SECENV which contains lots of useful stuff for debugging your apps.
Tony