I have several drivers using a resource in my code, of which only one can be defined.
eg if I have the following defines: USB_HID, USB_SERIAL, USB_STORAGE.
and I want to test that only one is defined, is there a simple way to do this?
Currently I am doing it this way:
#ifdef USB_HID
#ifdef USB_INUSE
#error "Can only have one USB device"
#else
#define USB_INUSE
#endif
#endif
#ifdef USB_SERIAL
#ifdef USB_INUSE
#error "Can only have one USB device"
#else
#define USB_INUSE
#endif
#endif
...
with one of these blocks for each USB_XXX driver.
Is there more elegant way of doing this?
#if defined(USB_HID) + defined(USB_SERIAL) + defined(USB_STORAGE) != 1
#error Define exactly one of USB_HID, USB_SERIAL, USB_STORAGE
#endif
Yes, use the define operator such as:
#if defined (USB_HID) && defined (USB_INUSE)
Why not #elif ?
#if defined(USB_HID)
#define USB_INUSE
#elif defined(USB_SERIAL)
#define USB_INUSE
#endif
Related
I have an application having two target, I want to define a macro having different value for different target.how can i do that? both are release version
Each target has it's own "Build settings" in Xcode, there you have the "Preprocessing"-category (Look for where 'DEBUG=1' is defined) where you can set custom macros that will be unique for the target.
Do it this way
#define CONSOLE_DEBUG 1 // Comment this line to undefine
#ifdef CONSOLE_DEBUG
#define SMLog(format, ...) NSLog((#"%s (%d) " format), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define SMLog(format, ...)
#endif
When you'll define CONSOLE_DEBUG then SMLOG will print log with Pretty function. else if you comment above line then it'll just print a simple NSLOG.
You can simple check for target Macros instead of CONSOLE_DEBUG.
EDIT:
In one of my apps I needed to give diffent URLs so Idid it with diffrent targets as follows
#ifdef APP_LIVE
#define strDefaultURL <Some URL String>
#define strIndexPlistURL <Some URL String>
#elif APP_DEV
#define strDefaultURL <Some URL String>
#define strIndexPlistURL <Some URL String>
#else
#define strDefaultURL <Some URL String>
#define strIndexPlistURL <Some URL String>
#endif
Where APP_LIVE and APP_DEV were defined in respective targets.
I got a bunch of NSLog statements in my code. Is there anyway I can suppress them from executing in production, but execute when I'm developing? I want to not comment them out, and them put them back in when developing, as it's a hassle.
DEBUG is a macro that is only defined (xcode default) when you are doing a debug/development build of your project. This will cause any code between the #ifdef DEBUG and #endif lines to not be included when doing a release build but they will be compiled and included with a debug/dev/test build.
Example:
#ifdef DEBUG
NSLog(#"Hello World!");
#endif
This is what I use in my Project-Prefix.pch file (called with DEBUGLOG(#"abc %#", someStr);):
#ifdef DEBUG
extern void DBGQuietLog(NSString *format, ...);
#define DEBUGLOG(fmt, ...) DBGQuietLog((#"[Line: %d] %s: " fmt), __LINE__, __FUNCTION__, ##__VA_ARGS__);
#else
#define DEBUGLOG(fmt, ...)
#endif
#ifdef DEBUG
void DBGQuietLog(NSString *format, ...) {
if (format == nil) {
printf("nil\n");
return;
}
va_list argList;
va_start(argList, format);
NSString *s = [[NSString alloc] initWithFormat:format arguments:argList];
printf("%s\n", [[s stringByReplacingOccurrencesOfString:#"%%" withString:#"%%%%"] UTF8String]);
[s release];
va_end(argList);
}
#endif
This prints console lines (only when debugging) with line number, class name, and method name like so:
[Line: 36] -[iPhoneAppDelegate application:didFinishLaunchingWithOptions:]: Hello World!
You could make a proxy and define it as a preprocessor macro:
#ifdef DEBUG
#define MyLog(str, ...) NSLog(str, ##__VA_ARGS__)
#else
#define MyLog(str, ...)
#endif
Then you'd use MyLog() instead of NSLog() in your code and when not compiling in debug mode the NSLog would be replaced with a no-op.
As an extension to CajunLuke's answer, I can only advise you to use this: http://kdl.nobugware.com/post/2009/03/11/better-nslog/
Wrap them with a macro. It's unfortunate that Apple doesn't do this already, with a "canned" solution, but many folks do it, and there are a number of examples on the web.
Something like:
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog(#"<%#:(%d)> %#", [NSString stringWithUTF8String __PRETTY_FUNCTION__], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
(Hopefully got that right -- copied by hand from another screen)
Made a new window application. Right-clicked Frameworks > Add Existing Frameworks. Selected Frameworks folder, then AudioToolbox.framework.
Build, and 11 crashes.
#elif defined __ppc__ || __ppc64__
#define _IntSaturate(x) ((int) (x))
#else
#error "Unknown architecture."
// To use unoptimized standard C code, remove above line.
#define _IntSaturate(x) ((x) <= -0x1p31f ? (int) -0x80000000 : \
0x1p31f <= (x) ? (int) 0x7fffffff : (int) (x))
#endif
Tried commenting that line, then MachineExceptions still crashes:
typedef CALLBACK_API_C( OSStatus , ExceptionHandlerProcPtr )(ExceptionInformation * theException);
error: expected ")" before '*' token
..what the hell happened? I'm 99.9% sure I've never modified the AudioToolbox or any other framework.
Just scrapped the project, copied main classes and everything working smoothly again.
I have a few lines of assembler arm code in an .s file. Just a few routines i need to call. It works fine when building for the device, however when i switch to iPhone Simulator i get "no such instruction" errors. I tried to compile parts of the .s file conditionally with what i know:
#if !TARGET_IPHONE_SIMULATOR
But the assembler doesn't recognize these preprocessor directives (of course) and none of the conditional compilation techniques for assembler that i could remember or find worked, so i'm scratching my head now on how to avoid compilation of that assembler code when building for the Simulator. I also don't see a project option in Xcode that would allow me to compile the file or not depending on the target platform.
SOLVED:
All i was missing was the proper #import in the assembler file. I did not think of adding it because Xcode syntax highlighted any preprocessor directive in green (comment) which made me assume that these commands are not recognized when in fact they work just fine.
This works:
#import "TargetConditionals.h"
#if !TARGET_IPHONE_SIMULATOR
... asm code here ...
#endif
You do do it with a pre-processor macro. They are defined in TargetConditionals.h TARGET_IPHONE_SIMULATOR should be there! (You do need to #include it however.)
Here is code I use to detect ARM vs Thumb vs Simulator:
#include "TargetConditionals.h"
#if defined(__arm__)
# if defined(__thumb__)
# define COMPILE_ARM_THUMB_ASM 1
# else
# define COMPILE_ARM_ASM 1
# endif
#endif
#if TARGET_IPHONE_SIMULATOR
// Simulator defines
#else
// ARM or Thumb mode defines
#endif
// And here is how you might use it
uint32_t
test_compare_shifted_operand(uint32_t w1) {
uint32_t local;
#if defined(COMPILE_ARM_ASM)
const uint32_t shifted = (1 << 8);
__asm__ __volatile__ (
"mov %[w2], #1\n\t"
"cmp %[w2], %[w1], lsr #8\n\t"
"moveq %[w2], #10\n\t"
"movne %[w2], #11\n\t"
: \
[w1] "+l" (w1),
[w2] "+l" (local)
: \
[shifted] "l" (shifted)
);
#else // COMPILE_ARM_ASM
if ((w1 >> 8) == 1) {
local = 10;
} else {
local = 11;
}
#endif // COMPILE_ARM_ASM
return local;
}
I'm writing a bunch of related preprocessor macros, one of which generates labels which the other one jumps to. I use them in this fashion:
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL();
MAKE_LABEL();
)
I need some way to generate unique labels, one for each inner MAKE_LABEL call, with the preprocessor. I've tried using __LINE__, but since I call MAKE_LABEL inside another macro, they all have the same line and the labels collide.
What I'd like this to expand to is something like:
MAKE_FUNNY_JUMPING_LOOP(
my_cool_label_1: // from first inner macro
...
my_cool_label_2: // from second inner macro
...
)
Is there a way to generate hashes or auto-incrementing integers with the preprocessor?
If you're using GCC or MSVC, there is __COUNTER__.
Other than that, you could do something vomit-worthy, like:
#ifndef USED_1
#define USED_1
1
#else
#ifndef USED_2
#define USED_2
2
/* many many more */
#endif
#endif
I use this:
#define MERGE_(a,b) a##b
#define LABEL_(a) MERGE_(unique_name_, a)
#define UNIQUE_NAME LABEL_(__LINE__)
int main()
{
int UNIQUE_NAME = 1;
return 0;
}
... and get the following:
int main()
{
int unique_name_8 = 1;
return 0;
}
As others noted, __COUNTER__ is the easy but nonstandard way of doing this.
If you need extra portability, or for other cool preprocessor tricks, the Boost Preprocessor library (which works for C as well as C++) will work. For example, the following header file will output a unique label wherever it's included.
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/slot/slot.hpp>
#if !defined(UNIQUE_LABEL)
#define UNIQUE_LABEL
#define BOOST_PP_VALUE 1
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#else
#define BOOST_PP_VALUE BOOST_PP_INC(BOOST_PP_SLOT(1))
#include BOOST_PP_ASSIGN_SLOT(1)
#undef BOOST_PP_VALUE
#endif
BOOST_PP_CAT(my_cool_label_, BOOST_PP_SLOT(1)):
Sample:
int main(int argc, char *argv[]) {
#include "unique_label.h"
printf("%x\n", 1234);
#include "unique_label.h"
printf("%x\n", 1234);
#include "unique_label.h"
return 0;
}
preprocesses to
int main(int argc, char *argv[]) {
my_cool_label_1:
printf("%x\n", 1234);
my_cool_label_2:
printf("%x\n", 1234);
my_cool_label_3:
return 0;
}
I can't think of a way to automatically generate them but you could pass a parameter to MAKE_LABEL:
#define MAKE_LABEL(n) my_cool_label_##n:
Then...
MAKE_FUNNY_JUMPING_LOOP(
MAKE_LABEL(0);
MAKE_LABEL(1);
)
You could do this:
#define MAKE_LABEL() \
do { \
my_cool_label: \
/* some stuff */; \
goto my_cool_label; \
/* other stuff */; \
} while (0)
This keeps the scope of the label local, allowing any number of them inside the primary macro.
If you want the labels to be accessed more globally, it's not clear how your macro "MAKE_FUNNY_JUMPING_LOOP" references these labels. Can you explain?
It doesn't seem possible with a standard preprocessor, although you could fake it out by putting parameters within MAKE_LABEL or MAKE_FUNNY_JUMPING_LOOP, and use token pasting to create the label.
There's nothing preventing you from making your own preprocessing script that does the automatic increment for you. However, it won't be a standard C/C++ file in that case.
A list of commands available: http://www.cppreference.com/wiki/preprocessor/start