My project compiles and runs OK in debug mode, but when I switch to release x86_64 compiling, I get compiler errors for attempts to setBounds using NSRect. (The errors read “incompatible type for argument 1 of setBounds”.)
There are lots of posts which I take to be suggesting to add the NS_BUILD_32_LIKE_64 macro definition above the Cocoa (Foundation) import, so that the “if NS_BUILD_32_LIKE_64” language in NSGeometry.h will be true and the necesseary typedefs will be used. So I added the macro definition to the h file of the offending class:
#define NS_BUILD_32_LIKE_64 1
#import <Cocoa/Cocoa.h>
And I still get the same compile errors.
I also tried converting explicitly from NSRect to CGRect, so that instead of this . . .
// rectIncomingSource is an NSRect
calayer.bounds = rectIncomingSource;
. . . I wrote this:
calayer.bounds = CGRectMake(rectIncomingSource.origin.x, rectIncomingSource.origin.y, rectIncomingSource.size.width, rectIncomingSource.size.height);
Same errors.
And why would setting bounds be the only problem? Per Apple docs, NSInteger and NSUInteger are the main conversion problem, and I use them all over the place, but the compiler doesn’t complain about them. So why would it choke on bounds?
I’m probably missing something really simple here — for which I apologize to the wizards. Any help for the blind?
The target info window gave me the clue to figure this out:
I was putting the NS_BUILD_32_LIKE_64 define in a particular class's h file. It should have been in the prefix header file, the one with the pch extension that usually resides in the project's "Other Sources."
#ifdef __OBJC__
#define NS_BUILD_32_LIKE_64 1 // this line added
#import <Cocoa/Cocoa.h>
#endif
Well, yeah, I suppose this was obvious. But maybe some other preprocessor neophyte will find this clarification helpful, so I won't delete the question.
And I still don't understand why setting bounds should have been the only problem. Maybe something to do with core animation?
Related
I am working on a project with the library ADOL-C (for automatic differentiation) using gcc. Right now I am trying to recompile the library to use the parallelization features however the make process does not working apparently due to some preprocessor stuff.
I think the problematic line is :
#define ADOLC_OPENMP_THREAD_NUMBER int ADOLC_threadNumber
However I could not find what it means. Does it make a link between two variables? Also ADOLC_threadNumber has not been declared before...
The preprocessor doesn't even know what a variable is. All that #define does is define a short(long?)hand for declaring a variable. I.e., if you type
ADOLC_OPENMP_THREAD_NUMBER;
It becomes
int ADOLC_threadNumber;
It's just a text substitution. Everywhere in code where ADOLC_OPENMP_THREAD_NUMBER appears, it's substituted by int ADOLC_threadNumber.
As far as I see it, the line with the define itself is not problematic, but maybe the subsequent appearance of ADOLC_OPENMP_THREAD_NUMBER. However, to check this, we need to know more about the context.
#define is a directive used often in .h files,
it creates a macro, which is the association of an identifier or parameterized identifier with a token string.
After the macro is defined, the compiler can substitute the token string for each occurrence of the identifier in the source file.
#define may be associated with #ifndef directive to avoid to delare the identifier more than once :
#ifndef ADOLC_OPENMP_THREAD_NUMBER
#define ADOLC_OPENMP_THREAD_NUMBER int ADOLC_threadNumber
#endif
I'm following a tutorial in a book (iPhone 3D Programming), which uses:
Objective-C header and source files (file extensions .h, .m - respectively),
Objective-C++ header and source files (file extensions .h, .mm - respectively)
C++ header and source files (file extensions .hpp, .mpp - respectively)
A sample Xcode project is included which compiles successfully.
Before I found the sample project, I had manually typed out the code from the book but I was getting the following compilation errors for the files detailed below:
Unknown type name 'virtual'
Expected member name or ';' after declaration specifiers
IRenderingEngine.hpp (Xcode File Inspector - File Type = "Default - C++ Header")
...
struct IRenderingEngine {
virtual void Initialize(int width, int height) = 0; //2 errors as marked above
virtual void Render() const = 0; //2 errors as marked above
virtual void UpdateAnimation(float timeStep) = 0; //2 errors as marked above
virtual void OnRotate(DeviceOrientation newOrientation) = 0; //2 errors as marked above
virtual ~IRenderingEngine() {} //2 errors as marked above
};
...
Must use 'struct' tag to refer to type 'IRenderingEngine'
GLView.h (Xcode File Inspector - File Type = "Default - C Header")
#import "IRenderingEngine.hpp"
#import <QuartzCore/QuartzCore.h>
#interface GLView : UIView {
#private
EAGLContext* m_context;
IRenderingEngine* m_renderingEngine; //1 error marked above
float m_timestamp;
}
- (void) drawView:(CADisplayLink*)displayLink;
- (void) didRotate:(NSNotification*)notification;
#end
The file types for all the other files also defaulted to their expected file types in the Xcode File Inspector and as such should have worked correctly with the Build Setting - Apple LLVM compiler 4.2 - Language - "Compile Sources As = According to File Type" - which is identical to the Build Setting in the sample project that compiles successfully.
For some odd reason changing the Build Setting to "Compile Sources As = Objective-C++" in my manually created project removed the compilation errors and the application ran as expected.
Can anyone offer a reason as to why this setting is not consistent between seemingly identical (source-code-wise) projects?
Header files are not compiled. Header files are used by the preprocessor — anywhere you have a #include or a #import the actual text of the original is treated as though you'd copied and pasted it into the original.
Hence it doesn't matter if your file is called .hpp, .h or anything else. If a .m file imports a .h file that includes a .hpp file then the .hpp code will be compiled as part of the .m file, i.e. as Objective-C.
I am therefore going to guess that you've got GLView.m. If that's going to import a .hpp file, whether directly or indirectly, it needs to be compiled as Objective-C++. One way to do it is to rename it .mm, the other is to tell the project not to try to guess language types by file extension.
Tommy and HotLicks gave you the right answer to your immediate problem -- you need to make sure that all source files that include GLView.h are Objective-C files, by naming them .mm.
However, I want to add another side to this. Blindly making all files Objective-C++ is a bad solution. It should lead you to ask yourself: why do all these files need to be Objective-C++, if they are not using C++ features? The answer is that they import GLView.h, and the GLView class contains an instance variable whose type is a pointer to a struct that contains C++ features. Why do these other files care about that? They shouldn't.
There are various things you can do about it.
IRenderingEngine can be forward-declared in GLView.h. It is unnecessary to import IRenderingEngine.hpp, since the header doesn't care about the internal structure of IRenderingEngine; it only needs to know that it's some type in order to have a pointer to it. A forward declaration suffices for this. (However it would be necessary to write struct IRenderingEngine* m_renderingEngine; to be compatible with C.)
Furthermore, the instance variables for the GLView class do not need to be declared in the header in the first place. Instance variables can instead be declared in the implementation (.m) file either in the "class extension" (i.e. #interface GLView () { ... }), or, in newer versions of Xcode, directly in the class implementation (#implementation GLView { ... })
I would like to create a define based on the status of iTunes File Sharing boolean status on the Info.plist file. So, I have created this:
#define itunesFileSharingEnabled [[[NSBundle mainBundle] \
objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]
#if itunesFileSharingEnabled
#define something
#endif
but the if fails with the error invalid token at start of preprocessor expression.
if I substitute #define itunesFileSharingEnabled with
#define itunesFileSharingEnabled YES
than the if compiles perfectly. So the error is on the previous line. Xcode is not liking the #define line.
What I want is to define some directive to be true if itunes file sharing is YES and NO if it is not.
How do I declare that?
thanks.
edit:
the problem is that I cannot use regular if to check for iTunes file sharing at run time because I want to make the compiler fail using #error or #warning directive...
for example, later in my code I want to use this
#if iTunesFileSharingEnabled
#error TURN OFF FILE SHARING
#endif
I want the compiler to fail if file sharing is turned on.
Preprocessor directives are evaluated at compile time.
after the first run of the preprocessor
#define itunesFileSharingEnabled [[[NSBundle mainBundle] \
objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]
#if itunesFileSharingEnabled
#define something
#endif
becomes
#if [[[NSBundle mainBundle] objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]
#define something
#endif
During the second run the preprocess tries to validate [[[NSBundle mainBundle] objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]. Which won't work because this can't be evaluated at compile time. This is a statement that can only be evaluated at run-time.
I don't know if the stuff you want to do is possible at all. (I don't know much about the preprocessor).
I guess you know already that you can do those checks at runtime
if ([[[NSBundle mainBundle] \
objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]) {
[self foo];
}
else {
[self bar];
}
Another option would be to enforce a manually entered precompiler macro
This goes into your code, somewhere were it is only called once. Probably in the init of your library:
#if HAS_ITUNES_FILESHARING
if (![[[NSBundle mainBundle] objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]) {
[NSException raise:#"MBFileSharingNotActiveButDeclaredException" format:#"File sharing is not active but \"HAS_ITUNES_FILESHARING\" is set to 1"];
}
#else
if ([[[NSBundle mainBundle] objectForInfoDictionaryKey:#"UIFileSharingEnabled"] boolValue]) {
[NSException raise:#"MBFileSharingActiveButNotDeclaredException" format:#"File sharing is active but you did not declare it as preprocessor macro. Please set \"HAS_ITUNES_FILESHARING\" to 1"];
}
#endif
This has to be entered in the Build Settings as Preprocessor Macro:
HAS_ITUNES_FILESHARING=1
If HAS_ITUNES_FILESHARING=1 is not declared in the preprocessor macro section, but File Sharing is active the code will throw an exception.
If HAS_ITUNES_FILESHARING=1 is declared, but File Sharing is not active, the code will raise an exception too.
This way you can always tell that the preprocessor macro matches the configuration. If you only call this once (in +(void)initialize there should be no performance impact at all.
Even though you can only check for it (in code) at runtime, iTunes File Sharing is something that an app developer sets in development. If you don't want file sharing, don't turn it on.
Presumably you're not actually having trouble with your own left and right hands working at cross purposes, though -- more likely you're in a situation where you're writing code (which wants iTunes File Sharing off) to be used by someone else (who might have it turned on)?
In that case, your best recourse is documentation (or licensing). Communicate to the user of your library that it should be used only in projects without iTunes File Sharing. To put it another way: if you're giving your source code to another programmer, you've surrendered control over what they do with it, but you can still give them recommendations as to how it's best used. (Or have your lawyer get them to agree to only use your software in ways that you specify, but that's no longer a programming question and this isn't a legal advice forum.)
(Aside: you could also consider doing something interesting with the build system: e.g. a shell script build phase that reads the project's main Info.plist. However, if your library is a dependency of the app, it'll need to be built first, which means that plist won't be there for it to read. Again, communication is your best bet.)
I have been trying to enable syntax highlighting and see call hierarchy for code which is embedded in #ifdedfine block but I am not able to find the option for it. Could anyone please point me at how to do it? It works well for other code/files it's just the code in #ifdef block (e.g. #ifdef CPP_UNIT....#endif). Thanks.
Code in #ifdef blocks IS syntax-highlighted IF THE CODE IS ACTIVE (e.g. if you have a #ifdef Q_OS_WIN and somewhere in your included headers Q_OS_WIN is defined, the code will be highlighted. Otherwise, it will be grayed-out.)
As a test, try temporarily replacing #ifdef ... with #if 1. If the latter works, then you know that ... is undefined by that file or any included files.
Assume that you have a label in a legacy Visual C++ 2010 project, defined like so:
[foo.rc]
LTEXT "Foo",IDC_STATIC,42,42,42,42
In a resource (.rc) file.
Now, you want to generate the text based on constants you define in a header file, like so:
[foo.rc]
LTEXT FOO_TEXT,IDC_STATIC,42,42,42,42
Where FOO_TEXT was previously defined in some other way, for instance:
[bar.h]
#define FROBNICATE "F"
#define OO "o"
#define ICANTTHINKOFMETASYNTACTICVARIABLESBEGINNINGWITHO "o"
#define FOO_TEXT (FROBNICATE OO ICANTTHINKOFMETASYNTACTICVARIABLESBEGINNINGWITHO)
Only that that doesn't work, because .rc files are not header files, and the RC compiler complains, telling you:
[Build output]
1>foo.rc(42): error RC2116: expecting number for ID
1>
1>
1>foo.rc(42): error RC2108: expected numerical dialog constant
What would you do?
To clarify, yes, the entire string in question is known at compile-time, but it also needs to be constructed from smaller strings (in this case, version information and release category (development, release, and another one)). Of course, I could also write C++ code that does that, but that seems very inelegant to me.
So, is there a nicer way?
I don't think you will be able to achive what you want without C++ code. See the comment to this msdn article:
Don't use parens in #define
The resource compiler is very limited in its understanding of directives. So, for example, this:
#define RESTYPE_FILE (256)
will silently get ignored, while this:
#define RESTYPE_FILE 256
will work. Obviously, trying to use expressions or anything complicated like that will silently fail, leaving you wondering why you can't load that resource.