How to check if constant is used in project - objective-c

I have a big project with many Objective C and Swift files.
There's a Constants.h file which contains many constants with #define. It looks like this:
#define kConstant1 #"constant1"
#define kConstant2 #"constant2"
#define kConstant3 #"constant3"
#define kConstant4 #"constant4"
...
In the project there are many files (Swift and Objective C) which use these constants. Unfortunately there are also constants which aren't used by any file in the code, so they are unused variables. I want to find out which constants are used and which are not, to delete the constants which aren't used. There are about 3000 constants in this file so it would take too long to search through the code manually for each constant.
Is there any other way to find out which #define variable is used by the code?

Three suggestions:
Download JetBrains AppCode and try running your code through its diagnostics. AppCode tools might find the unused constants.
Write a script to go through each file and look check for the presence of the constants. If a constant is found, mark it as found. When all the files are checked, whatever isn't marked can be deleted. You can write this script in anything you want -- bash, ruby, python, swift, etc -- and you can either hard code the constants in or extract them from the Constants.h file.
Comment or remove each constant one by one and build the project. The compiler will throw an error if one of the constants you removed is used in the project.
Unfortunately, there is no magic bullet here. This is fundamentally a time-consuming process. :(

Related

Is it possible to prevent POSIX symbol name pollution in Objective-C?

I've run into a somewhat unexpected behavior in Xcode/Objective-C. I know it's probably not advised, but if I want to make my own struct in_addr in a .m file, it seems I can't. This implies something rather strange about namespaces and symbol pollution in Objective-C. The same seems to apply for many other networking types and perhaps other POSIX-y things as well.
I came up with a very basic example that demonstrates this behavior. Note that this snippet is the entire contents of the .m file.
#define _SYS_SOCKET_H_
#define _NETINET_IN_H_
#include <stdint.h>
struct in_addr {
uint32_t foo;
};
which yields the build error Redefinition of 'in_addr'.
This implies some fairly strange things about Objective-C. For starters, I wouldn't expect <stdint.h> to bring in any networking types. But even allowing that it might, defining _NETINET_IN_H_ first should prevent the definition of struct in_addr. And yet even still, this code refuses to build.
Is it possible to somehow forgo this forced symbol visibility? Is there a list of symbols that are included, no matter what? Is there a good reason for this behavior?
edit: Stranger still, if i remove <stdint.h> and change the uint32_t to int, this actually does compile.
If you go into the Report navigator and read the full error emitted by the clang tool, you'll see a big hint:
In module 'Darwin' imported from /Users/csrstka/Desktop/asdfasdf/asdfasdf/main.m:1:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/netinet/in.h:302:12: note: field has name 's_addr' here
in_addr_t s_addr;
As you can see, the existing in_addr is coming from the Darwin module, which is implicitly imported due to your #include of stdint.h, which is part of the Darwin module. You can see this if you go to Product > Perform Action > Preprocess in Xcode—instead of copying in all the headers you've imported, there's just one line about importing Darwin.C.stdint.
Basically, there are a few purposes for modules; they improve compile times by cutting down on redundant compilation tasks, and they prevent people from messing with library headers via #defines like you're trying to do. ;-) For more on Objective-C modules, how they work, and the rationale behind them, see this link:
https://clang.llvm.org/docs/Modules.html#introduction
Of particular interest to your question are the following excerpts:
The primary user-level feature of modules is the import operation, which provides access to the API of software libraries. However, today’s programs make extensive use of #include, and it is unrealistic to assume that all of this code will change overnight. Instead, modules automatically translate #include directives into the corresponding module import. For example, the include directive
#include <stdio.h>
will be automatically mapped to an import of the module std.io. Even with specific import syntax in the language, this particular feature is important for both adoption and backward compatibility: automatic translation of #include to import allows an application to get the benefits of modules (for all modules-enabled libraries) without any changes to the application itself. Thus, users can easily use modules with one compiler while falling back to the preprocessor-inclusion mechanism with other compilers.
And later on:
If any submodule of a module is imported into any part of a program, the entire top-level module is considered to be part of the program. As a consequence of this, Clang may diagnose conflicts between an entity declared in an unimported submodule and an entity declared in the current translation unit, and Clang may inline or devirtualize based on knowledge from unimported submodules.
Or, if you'd prefer to turn them off and get more traditional C-like behavior, you can simply set Enable Modules (C and Objective-C) to No in Xcode's Build Settings, or compile without the -fmodules flag if you're using the command line.

dllexport in headers confusion

I'm confused as to why __declspec(dllexport) or equivalent needs to go in the header file. Say I'm writing a library. Surely the users don't need to know or worry about whether symbols are exported or not, all they care about is that the function declarations are there and will presumably be linked against the shared or static library itself. So why can't all this boilerplate go into source files, for use only at build time?
The only use case I think of is a situation where someone is writing a wrapper of my library and needs to export all of my functions as well, but in general that is not the case - is it really worth the hassle of having all the export stuff inside public headers? Is there something I'm missing, is this a technical limitation of linkers..?
I'm asking because I like my headers and build system to be clean, and as dllexport stuff is generally set/not set based on whether we are building the library as a shared or static library, I find it strange that it should end up inside public headers since it's (to my understanding) fundamentally a build time concept. So can someone please enlighten me on what I am missing?
I'm not really sure I can provide a great answer. My impression is that it serves several purposes:
It speeds the loading of DLLs, particularly when lots of DLLs are used (because there are fewer exported symbols to search through)
It reduces the possibility of symbols colliding at run-time (because there are fewer exported symbols)
It allows the linker to complain about undefined symbols (instead of just assuming it might find them at run time.
I'm sure there are other reasons. I generally wrap my APIs in something like this:
#if defined(MY_LIB_CREATION)
#define MY_LIB_API __declspec(dllexport)
#else
#define MY_LIB_API __declspec(dllimport)
#endif
And then all of my API functions & classes are defined as MY_LIB_API:
class MY_LIB_API Foo {};
MY_LIB_API void bar();
And then in the project file defined MY_LIB_CREATION for the project implementing your library.

Why can't I define plain C functions in header file?

I always get a build error when I try to define a C function in the header file just above the interface of the class.
but when I do the same in the implementation file and give a declaration in the header. Things work out.
I wanted to know, why is it so becuase I have defined enums, structs , constant NSStrings in the header-file , so why not C functions ?
This is to do with the way that the C linker (or link editor) works. When the C compiler comes across a function definition, it prepares the assembler code that implements that function and marks it with a symbol that says to the linker "this is where the function with this name starts". The symbol is usually named with an underscore followed by the function name, e.g. _printf.
If you define the function in a header file, then every .c or .m file that imports this header will compile the function, and will cause the compiler to emit the same symbol. The linker expects to only find one instance of each symbol, so this is an error.
This is unrelated to the existence of #include guards, or to using #import instead of #include. The C compiler works on individual translation units - by which it means individual source files. Preprocessor strategies stop you including the same header file twice into a single source file, but do nothing to coordinate activities across multiple files. That means that it's valid to include the same headers in different source files: it also means that when you compile different files, they can (legitimately) contain the same symbol.
It's the job of the link editor to put these files together, resolving any references to symbols that were unknown at compilation time. If you try to link objects (the name of compiled and assembled translation units) that have the same symbol into the same archive, shared library or executable, then you'll get the error you're seeing here.
Solutions:
Don't define the function in the header, just declare it there and define it in an implementation file; as you've already found this works.
Define the function in the header, but only include that header in one place in your code. This is often unacceptable for design reasons.
Define the function in the header with the modifier inline. Inline functions are just copied by the compiler into the function where they're called, so a linker symbol is never emitted for them. This has its own trade-offs that you may wish to read more about.

Temporarily #undef macros when using #import directive for importing COM typelib

I'm trying to use a COM library in C++. I've got a #import "TheLibrary.dll" and it creates the tlh and tli files with the classes in the library.
Now, my problem is that the COM object exposes a few enums with the values of some lists of constants that are also in the Windows SDK headers. I presume this is so that Visual Basic developers have named variants of these constants, rather than having to use their numeric values.
But this poses a problem for me, as these headers are included before my typelib is #import'ed; so now the enum member declarations are being replaced with the numeric constants in the windows header files, causing my compilation to fail.
Example:
windows header file:
#define RES_AND ((ULONG) 0x00000000)
generated tlh:
enum __declspec(uuid(-some guid-))
RestrictionKind
{
RES_AND = 0,
.. etc
So the problem is obvious; the enum in the tlh is expanded, and the result is an attempt to assign a constant to a number.
Now I see several solutions, all of them unattractive:
do a 'rename' on each item, at the time of the #import. There are hundreds of these constants, not looking forward to that.
leave out the enums all together. That would cripple my access to the COM object seriously (I haven't tried this out yet, maybe the whole library will even become unusable).
do a #undef of all these constants before the #import. Again, there are hundreds of them, and on top of that I wouldn't be able to use them afterward - unless I do a #define again...
So I'm kind of at a loss here. I'm hoping for a way to do mass renames of enum values, but the documentation on the #import directive isn't giving me much hope.
Any ideas amongst the few remaining COM programmers out there? Thanks.
Well, you have three options.
Option 1. If you can change that component interface - do that, rename the enum values so that they don't conflict with Windows SDK.
Option 2. Use #import with rename. Although you have hundreds of those elements you can build a nice table splitting the list with use of backslashes.
Option 3. Try to isolate the #import into a separate .h file so that either isn't included with all the Windows SDK or at least is imported with a much smaller number of files. This will eliminate or reduce conflicts and then you can use rename for the remaining conflicts.

Mixing Objective-c and C: How to use a C source file that lacks header file?

I wan't to use some C source in my Objective-c proj but the source lacks a header file. I get a "implicit declaration of function" warning when building, however the app launches fine and works fine up until I try to call one of the C functions. Now that it crashes could be cause somethings wrong with the args I pass, I haven't investigated that further yet. But:
Is there a way to get rid of the build warning?
Am I on the right track? Meaning that the C source will be usable even without the header file..
Some background :
I'm trying to use a GPL dynamic C library in my Objective-c project (iPhone). With no C experience the C code itself is a bit to low level for me to be able to effectively use. However the C lib also contains some higher level example programs which I can understand what they are doing and I think (hope) also modify to suit my needs. This example program is just a source file fired from a shell script wrapper. No header file.
First of all, there is no such thing as a C class.
If you mean just calling a C function you can add the function prototypes in your Objective-C code.
Let's say you need to call a function f that returns an int and takes a char parameter that is defined in your .c file.
In your .m file, where you will call the function, add the following line:
int f(char);
You will get rid of the implicit declaration of function.
Alternatively, you can write all function prototypes in a custom made .h file of your own in case you decide you need to use those functions in other compilation units as well.