while developing in Xcode it is common to switch between Debug and Release mode and using some parts of code in Debug mode only while not using some in Release mode.
I often throw out NSLog
code by some #define
rule that lets the Pre-compiler parse out those commands that are not needed in a Release. Doing so because some final testing needs proof everything works as expected and errors are still handled properly without messing some NSLog i possibly forgot. This is in example of importance in audio development where logging in general is contra productive but needed while debugging. Wrapping everything in #ifdef DEBUG
is kinda cumbersome and makes code lock wild, so my #defines are working well to keep code simple and readable without worrying about NSLog
left in releases while still Logging on purpose if needed. This praxis works really well for me to have a proper test scenario with pure Release code.
But this leads to compiler warnings that some variables are not used at all. Which is not much of a problem but i want to go one step ahead and try to get rid of those warnings also. Now i could turn those warnings off in Xcode but i try to find a way to keep those and just getting rid of them for my NSLog overruled #defines
So instead of logging against dev>null
i throw out (nullify) all code that is wrapped by NSLog(
… )
and use some extra defined rule called ALLWAYSLog()
that keeps NSLog in Releases on purpose and also changes NSLog to fprintf to avoid app origin and time prints.
Here my rules..
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr, "%s n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String])
#else
#define NSLog(FORMAT, ...) {;}
#endif
#define ALLWAYSLog(FORMAT, ...) fprintf(stderr, "%s n", [[[NSString alloc] initWithFormat:FORMAT, ##__VA_ARGS__] UTF8String])
To get rid of those unused variable warnings we often use
#pragma unused(variablename)
to inform the precompiler we did that on purpose..
Question:
Is it possible to write some #define
rule that makes use of #pragma unused(x)
?
Or how to integrate this mentioned way of __unused
attribute
2
Answers
after testing and still not believing there is no "official way" of doing this i ended up reading my header files again. (
usr/include/sys/cdefs.h
)where
__unused
is declared as__attribute__((__unused__))
.This seems the officially way of telling the Apple Clang (GCC) compiler a specific variable will be not used intentionally by placing a
__unused
directive at the right place in code. In example in front of a variables declaration or after a function declaration and more.. see stackoverflow discussion starting 2013 ongoing@dbush 's answer was and is nice because it suppresses the unused variable warning by making use of the passed arguments and introducing nullify logic that will do no harm - but will still be executed to find "Expression result unused". That was pretty close to my goal and is possibly still the most simple solution.
in example:
While this will not print anything, the compiler knows the expression is unused then.
But this left me with the question how unused marking is done properly. Trying a reciprocal approach distinguish Debug and Release to make use of
__unused
again in combination with my first approach like so...In Debug it will not silence the unused variable warning by parsing out the directive itself and in Release it will exchange
IN_RELEASE__unused
to__unused
according to the macro and silence it. This is a little extra work but could help to see which parts are unused on purpose.Means i can type like below..
This keeps NSLog in place (in code), marks the unused variables to silence the warning properly and NSLog gets parsed out completely in Release. And i can still force prints for both modes with the introduced ALLWAYSLog.
Conclusion: dbush's solution is still more straight forward.
In the
#else
case, you can put the function call on the right side of the&&
operator with 0 on the left side. That will ensure that variables are "used" while also ensuring that the function doesn’t actually get called and that the parameters are not evaluated.