Importing a configuration file gives mach-o-linker - objective-c

Its very strange, i have a .h file with many const and variables .
I have tWo classes that use him, hence import him:
classA , and classB with : ( #import "configurations.h" )
Now another new class that i have added, C , came in , and when i am trying to do the same with him, import the configuration file - i get a mach-o-linker error .
Check this out : even if the new class C is empty(!) i cant add that configuration file and get the same error . i have tried also with new classes , and its the same .
I could only add it then , to A B and now, no more importing !
EDIT
Ok, i now get it , first its not happen in class A and B because: A.m and B.mm hence i can import them both with that .h file .
Than the problem is probably because i dont use extern with my consts in the .h file ?
(i have tried extern and still got errors) , i create somehow 2 copies of consts from .h :
How i define them in .h file ? just like that :
const int wordSize=8;
const int numOfWords=8;
Whay am i missing here ?
(there is some other class D ,that import A B C if its matter )

.h file is for declarations
.m file is for definitions
It means no "=" signs in .h, no method implementations. If you have constant:
configurations.h
extern const int wordSize;
extern NSString * const someStringConst;
configurations.m
const int wordSize = 8;
NSString * const someStringConst = #"someStringConst";
If you import your
configurations.h
const int wordSize = 8;
from multiple files, compiler generates _wordSize symbol for every file that imported configurations.h
Linker for sure cannot resolve these duplicated symbols - so the best approach is to get rid of definitions in your .h file using extern declaration like i've shown above.

Related

how to use HOST_VM_INFO_COUNT in swift file

I trying to use HOST_VM_INFO_COUNT in my swift file. In objective C it is working.
I have tried by importing
#import <mach/host_info.h>
using bridging header but its not working.
<mach/host_info.h> defines HOST_VM_INFO_COUNT as
#define HOST_VM_INFO_COUNT ((mach_msg_type_number_t) \
(sizeof(vm_statistics_data_t)/sizeof(integer_t)))
and “non-trivial” macro definitions are not imported into Swift.
Therefore you have to define it yourself:
let HOST_VM_INFO_COUNT = MemoryLayout<vm_statistics_data_t>.stride/MemoryLayout<integer_t>.stride
An alternative is to add
#import <mach/host_info.h>
static const mach_msg_type_number_t HostVMInfoCount = HOST_VM_INFO_COUNT;
to the bridging header file and then use HostVMInfoCount in
the Swift code.

Generate random identifier in C Preprocessor to avoid duplicate linker symbols

I'm trying to solve Can Xcode tell me if I forget to include a category implementation in my target?, and I came up with the following solution:
NSObject+Foo.h
extern int volatile canary;
void canaryCage() {
canary = 0;
}
NSObject+Foo.m
int canary = 0;
Now, if I #import "NSObject+Foo.h" in a source file, I'll get a linker error if that NSObject+Foo.m wasn't also included in my target.
However, every time I #import "NSObject+Foo.h" I generate a duplicate _canaryCage symbol. I can't use __COUNTER__ because I only #import "NSObject+Foo.h" in implementation files. I need canaryCage to be unique across my whole symbol table.
I need something like:
#define CONCAT(x, y) x##y
#define CONCAT2(x, y) CONCAT(x, y)
extern int volatile canary;
void CONCAT2(canaryCage, __RANDOM__)() {
canary = 0;
}
This way, if I have source files like:
Bar.m
#import "NSObject+Foo.h"
Baz.m
#import "NSObject+Foo.h"
I'll get symbols like _canaryCage9572098740753234521 and _canaryCage549569815492345, which won't conflict. I also don't want to enable --allow-multiple-definition in ld because I want other duplicate symbol definitions to cause an error. I don't want to use canaryCage for anything but a marker that I forgot to link a source file whose header I #imported.
If you make it static, each translation unit will get its own copy, and everything else should work the way you want it to - no preprocessor gymnastics required.
static void canaryCage()
{
canary = 0;
}
This answer was close, but it resulted in canaryCage being optimized away because it was dead code.
Solution:
NSObject+Foo.h
extern int canary;
__attribute__((constructor)) static void canaryCage() {
canary = 0;
}
NSObject+Foo.m
int canary = 0;
Unfortunately, this adds some overhead every time the category is imported, but the overhead is very minimal. If anyone knows a way to prevent canaryCage from being stripped, I'll happily mark their answer as correct.

Importing header file multiple times with C function in Objective-C

In my Xcode project I made a standalone header file with the following C utility function:
#ifndef FOO
#define FOO
CGFloat DistanceBetweenTwoPoints(CGPoint p1, CGPoint p2)
{
CGFloat dx = p2.x - p1.x;
CGFloat dy = p2.y - p1.y;
return sqrt(dx*dx + dy*dy);
};
#endif
Even with the preprocessor directives, if I try to import or include that header file in multiple locations, I receive the following error complaining about duplicate symbols:
linker command failed with exit code 1
Is there a different way I can achieve this effect? This question is out of curiosity more than anything else.
Thanks
Put your function body in a .c file and the function declaration (aka prototype) in the .h with those #ifndef, etc. Then use include to import the header file where you need the function.
Remember to check the target membership of the .c file, otherwise it won't be compiled.
For a small function like that you can declare it inline and just use the header file:
inline CGFloat DistanceBetweenTwoPoints(CGPoint p1, CGPoint p2)
{
// code as is
}
The compiler will replace your function calls with the function code without actually building and linking a new object file. No more duplicated symbols.
Since the function's definition is in the header, you get one definition of the function in each file (actually, each translation unit) where it is included.
Move the function body into a ".c" file, leaving a declaration in the header, or declare it inline.

Objective-C: how to group a series of string constants?

I defined a series of string constants like below, in macro way,
#define EXT_RESULT_APPID #"appid"
#define EXT_RESULT_ERROR_CODE #"errorcode"
#define EXT_RESULT_PROGRESS #"progress"
...
All these constants are supposed to be used in same context, so I'd like to constraint them in a same namespace, and I don't want to make them global, just like what this post said.
In the other hand, I could put all numeric constants in an enum but it doesn't work for strings.
Then how could I group these related string constants?
Here's one approach:
MONExtResult.h
// add __unsafe_unretained if compiling for ARC
struct MONExtResultStruct {
NSString * const AppID;
NSString * const ErrorCode;
NSString * const Progress;
};
extern const struct MONExtResultStruct MONExtResult;
MONExtResult.m
const struct MONExtResultStruct MONExtResult = {
.AppID = #"appid",
.ErrorCode = #"errorcode",
.Progress = #"progress"
};
In use:
NSString * str = MONExtResult.AppID;
Create a header file where you declare your strings and import it when needed
You may create a header file name "Constants.h". Then you need to import this header file where you want to use these constants like:
#import "Constants.h"
Create a header file say Constants.h
Add all constants in this file. These can be constants that you would like to use in deferent classes of your project.
#define EXT_RESULT_APPID #"appid"
#define EXT_RESULT_ERROR_CODE #"errorcode"
#define EXT_RESULT_PROGRESS #"progress"
Now, instead of importing this Constants.h in every class, goto <project name>-Prefix.pch file and import the File here.
#import "SCConstants.h"
now you can use the Constants in any class of the project to your ease.

Error and warnings in Xcode when declaring Array of NSString* as a global extern

I am declaring an array of NSString* in a header file of a class.
PolygonShape.h
NSString* POLYGON_NAMES[] = {#"Invalid Polygon", #"Monogon", ...};
Now I am using this in PolyginShape.m as follows:
- (NSString*) name {
return (POLYGON_NAMES [self.numberOfSides]);
}
numberOfSides is an iVar which will indicate the index at which the polygon name is stored
So far so good ... it was compiling without any errors
Then I added PolygonShape.h in my file that implements main method (note: these does not have any class definition and call functions C-Style rather than obj-c Style)
#import "PolygonShape.h"
Now when I compile, I am getting a build (linking) error
ld: duplicate symbol _POLYGON_NAMES in /Users/../Projects/CS193P/1B/What_A_Tool/build/What_A_Tool.build/Debug/What_A_Tool.build/Objects-normal/i386/PolygonShape.o and /Users/../Projects/CS193P/1B/What_A_Tool/build/What_A_Tool.build/Debug/What_A_Tool.build/Objects-normal/i386/What_A_Tool.o
collect2: ld returned 1 exit status
So I went thru stack overflow and other forums and mostly the advice was to make the global variable extern and so I did ...
extern NSString* POLYGON_NAMES[] = {#"Invalid Polygon", #"Monogon" .. };
However I am still getting the linking error and also getting 2 warnings now that says
warning: 'POLYGON_NAMES' initialized and declared 'extern'
at both the places where i am importing PolygonShape.h
What am I missing here?
Thanks.
In your header file declare the array as:
extern const NSString* POLYGON_NAMES[];
In your source file, define the array and initialize the contents:
const NSString* POLYGON_NAMES[] = {#"Invalid Polygon", #"Monogon" };