I'm currently having some linker problems when trying to compile an Objective-C program and think that the reason why I can't figure out the issue may be due to ignorance as to the compiler process.
Would it be possible for somebody to give me an overview of the steps taken during compilation?
This is as I currently understand the process:
The compiler copies the contents of any included .h files into the file that it was defined in. The compiler does not keep track of whether a .h file has already been included, so it may be included within a project multiple times.
Any .m files are compiled to C equivalent code (which are in turn compiled to object code).
The linker produces links between the declarations made in the .h files and the appropriate functions within the object code. The appropriate functions are determined by looking for them in a .m file of the same name.
The object files are connected together to form the executable, making sure that the main function is situated at the entry point of the executable. Any declarations are then presumably deleted to save space?
Assuming this is correct (which it may not be), this would presumably mean that you should never #include .m files because you will likely end up with multiple method definitions which will cause the linker problems.
Thanks for any illumination anybody can bring to this :).
Cheers,
Danny
You get the idea more or less correctly. A few corrections:
#include doesn't check whether it's already included or not, but #import does check.
.m is not first converted to C and then to object code. It was done that way 20 years ago, but it's no longer the case. It's just directly compiled down to object code.
The linker doesn't care how the file was named. You can use different file names for .h and .m. You can split implementations of functions declared in a .h file into multiple .m files, for example.
Whether unused implementations are deleted or not depends on the compiler and the compiler options.
In any case, your conclusion is correct: you should never include/import an implementation file to another implementation file. You will run into a double-implementation error.
Related
the more i study and research, the less i understand now.. very frustrating..
But, still try to figure it out i hope anyone who knows in detail, please help me out :)
What i know is when i use "#import(include) (file1)", it does nothing but putting file1 in current source file so that i can.... use the name of file...(I'm not so sure..)
And,
The Question is then when i inherit file1.h, every definition included in file1.m can be inherited..?
What about the "include" case..? it also include file1.m behind the scene..? or my program just knows declaration in file1.h and can refer to real definition at runtime..?
Sorry if my question is a bit not organised cuz even my brain is not organised as well Y.Y
The Question is then when i inherit file1.h, every definition included
in file1.m can be inherited..?
You don't inherit a file, you #include or #import it. Actually the thing is easier than you think.
In any source code file, you use functions and objects. For example you can use NSString or a custom object MyClass. But the compiler and the linker needs to know WHERE is the definition of those objects and functions, so that it can verify the syntax and link with the appropriate libraries.
Say you use MyClass in some source file.
MyClass myclass = [[MyClass alloc] init];
The compiler doesn't know what MyClass is, so you write this
#include "MyClass.h"
This tells the compiler that it should look into that header file when looking up objects. So what about MyClass.m? Well, at the point where you're object is being compiled the contents of MyClass.m don't matter, because that will be resolved later, by the linker.
In objectiveC you will use "import"
In C you will use "include"
In Xcode you can right in c and ObjectiveC.
Basically what is dose, is take the file that you imported and place is before the file that you imported it from, before the program compiles.
For Example if i use "import myViewController.h", in the class "mainViewController.m"
The class that i imported it to("mainViewController.m"), can use all the properties that are at the "#interface" at the "import myViewController.h" file.
Hope my answer is clear enough..
The implications to the visibility of symbols should be exactly the same.
If you are dealing with somelib.h, and in my module.c you #import somelib;
it should give you the same symbols in that compilation unit as if you did #import <somelib.h>
but you wouldn't have to add the framework in your linking phase.
Where do #import my headers and implementations?
Are there rules regarding what I should do?
Is there a way to import everything in a single header file?
Given "General guidelines for using #import in very large projects.".
Well, Objective-C is much like C and C++ in this regard. Stuffing all your #includes/#imports into your headers will introduce a lot of unnecessary dependency, which adds a lot of time to your build. So further information may also be sought in topics on C and C++ dependencies.
Where do #import my headers and implementations?
Typically, you should write #import only where physical dependency exists. Since every objc object is reference counted and your properties/ivars do not typically need to exist in the header, #imports are far lower than C++.
Robin van Dijke outlined the common cases of physical dependence in his answer (+1).
Are there rules regarding what I should do?
Is there a way to import everything in a single header file?
Well, it depends on the size of your project. Some people add all frameworks they use to the PCH (Pre-Compiled Header). Some people put the most frequent ones in the PCH, and some people don't use PCH files at all. The longer the build times and more complex the project, the less the PCH should include.
If you are working on "Very Large" projects, you should probably not add more than Foundation to your PCH.
Another common mistake is that some people will use the PCH so they need to type less (pretty much). The problem with that is their project's common includes/headers change, and when that happens, the target must be entirely rebuilt.
Also, if you can avoid #importing frameworks/libraries in your headers, you can save a lot of build time.
Adding #imports to headers increases causes dependencies to spread even further. It's easy for tons of unrelated code/frameworks which only need to be visible to a few source files to be actually visible to a high percentage of your source files.
Finally, you should really try to keep headers which change often out of other headers.
The big takeaway is that you should:
separate your programs based on features
favor forward declarations over #import. the compiler must know names, but the import is often needed only when you create/message the object.
try to keep your dependency-heavy implementations in the *.m file.
Every once in a while, it can help to review the preprocessed output of some of your source files -- to see what is actually #imported -- the results can be quite surprising.
Notes:
The PCH must be generated for every language in your project.
Compile sources based on their needs; e.g. If you have C programs, don't compile them as ObjC.
As your project's complexity increases, the gains to be made by dividing by targets (e.g. static libraries, modules, dividing your tests logically...) will increase. Structuring dependent targets correctly with low dependency is a large topic in itself. It can really help you build and test at higher frequencies when structured correctly (also important if you use continuous integration or have several developers). Like header dependencies, if you don't consider this from the start, old problems can take a lot of man-hours to correct (after it's already grown to be unbearably slow).
The following conventions can be used:
Use #import in your header file when
- You subclass the imported class
- You use a protocol from the imported header file
- You use other C datastructures (enum, struct) from the imported header file
Example:
#import "SuperClass.h"
#import "Protocol.h"
#class SomeOtherClass
#interface Subclass : SuperClass <Protocol>
SomeOtherClass _instanceVariableToOtherClass
#end
Otherwise use #class in the header file
For all other cases, use #import in the .m file.
Note: #import "class.h" is in fact the following:
#pragma once
#include "class.h"
So it takes care that every class is only imported once to prevent include cycles/loops.
First read this official site That may be helpful for you.
It is similar like , #include Statement In the C language,
Basically #import statement has two Defination,
1) #import "headerFile.h" // This statement is use for Import any header file in current file (UIController)
2) #import<FramWorkName> // This statement basically use for add any framework in current file (UIController)
For use any file any where in your Project then add your file (#import "fileName.h") in .pch file. It is Prefix headers are compiled and stored in a cache, and then automatically included in every file during compilation. This can speed up compilation, and lets you include a file without adding an import statement to every file using it. They are not required, and actually slow compilation whenever you change them. This file is available in your project with .pch file extension.
Such Like:
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "MyFile_Name.h"
Your can also use PROTOCOL for to define methods that are to be implemented by other classes.
For More information about, How to create POTOCOL, here is Best example with detail.
Just for kicks - I'm going to add a few "basic tenets" - that although are not as detailed as what has been said already - can sometimes help understand the overall "process".
Implementation.m files are never (as far as I know) #import'ed - that is what the compiler "is doing" when it "compiles".
Any header you want ALL compiled (.m) files to "know about" can go in the .pch file. I usually also stick directives shared across all classes, i.e. #import <Cocoa/Cocoa.h>, etc in there - so I don't have to look at them in every file.
If you are going to reference a previously undeclared class in a header file, i.e. AppDelegate.h
#property (nonatomic, strong) HTTPServer *http;
you can #import "HTTPServer.h" at the top of that file (or even in the.pch`)... but it is usually better to reference the "forward class" as follows...
#class HTTPServer;
#interface AppDelegate : NSObject ➜ ...
and then #import "HTTPServer.h" in AppDelegate's .m file. The main reason that you need access to the header file... is to call methods and work with properties, etc of an instance of that external class within your own class's "scope". This is why you can "get away with" simply "mentioning" the #class in your header - you're not actually doing anything with it yet.
The only other thing to consider - and this probably isn't the case if you're building a standalone application - but when building a framework, or a bundle, etc… in which YOUR classes will be referenced in an "API-kind-of-way"… You would want to add a "Copy Files" phase to your build process which would allow "others" to "know about" your classes, via your "Public Header" files. In such a case... you can simply expose a header file which imports the forward declarations needed for your class, for other people to #import. This is how you are able to access all the classes in an "Umbrella Framework", such as <Foundation/Foundation.h> with a single #import... It has exposed the headers that it "makes available" in that first `.h' file.. á la...
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
If you ever used compiler before Xcode, the way to think about it is that any header you need to import are the same as an "Include" -I directive on the commandline. Given a header file src/headers/header.h and a source code file source.c which has an #include "header.h" statement.. the compile command would be
gcc -Iheaders/ source.c -o executable
You can learn about what is actually happening when you compile something in Xcode by navigating to the "log navigator" and Xcode and checking out all the steps.
I am working through the "Big Nerds Ranch" Objective-C book and noticed in one of the chapters where they are setting up an observer to listen for time zone changes they create a method in the .m file called zoneChanged however it didn't need to be declared in the .h? How can methods be used without being declared? Is it because it was only going to be triggered by the observer?
I read that if you declare a method in the .m file then it would be private however it doesn't seem to be declared at all in the .m file.
How can methods be used without being declared?
What they are doing is directly providing the definition itself. The problem is if it is not declared in the header file, any other file depending on this file isn't aware that zoneChanged function exist. However you can link it through the keyword extern and that is a different story.
As far as to the compiler, it should know what the function is in the current compilation unit, else the compiler complains. In case if you forward declare the function, you are promising the compiler the definition is else where but may or may not be before the point of call. And if you don't provide definition, linker complains.
By default Xcode creates both an .h and and an .m file when you ask for a new ObjC class.
Everything works fine until you need to refer to any C++ file elsewhere in your project and start #import ing it into either your .h or .m file
At that point, the ObjC compiler gest utterly confused and throws mountains of parsing errors, and you the user (that is to say: me) get even more confused until such time it hits me: of course I should make that file an ObjC++ file instead.
The options are:
tell Xcode that this particular file, even though it is a .m file
really is an ObjC++ file, or
rename that file to .mm.
The first option is not very palatable to me, because that file really is ObjC++ regardless of the what the project thinks it is.
The second option is not good either as it screws up the Git repo which then 'forgets' that there used to be another .m file which really is the history of this 'new' .mm file.
So I have decided from now on to always rename any .m file that Xcode creates for me to .mm first thing after creating it so that I won't loose the history.
It has worked well for me so far, but I have this slight worry in my head, that there might be some corner case where I would really want to have an ObjC file and not an ObjC++ file.
What would those corner cases be? Anyone is aware of any ObjC++ file which happens to NOT contain any C++ reference but would choke the ObjC compiler in some way, just by virtue of being an .mm file?
And if there are no downside, why not just deprecate the use of .m forever and stick to .mm instead?
Parsing C++ is much slower than parsing ObjC, so ObjC++ files have significantly longer compile times. I'm not certain if this overhead will apply to ObjC++ files that contain no C++, but it would make a certain amount of sense that it's harder to parse just because the compiler needs to look for C++ constructs.
Also, the C++ type system has a few slightly different rules from C, that are applied to ObjC/C code in a C++ file as well. I don't recall the details, but it's not going to be harmful; just might require a few extra casts.
There is no downside, although there are two methods created on behalf of you (.cxx_construct and .cxx_destruct), but they are only used for crafting and destroying C++ objects when you create/dealloc an instance. If your class has no C++ members, these functions do nothing and add only an really extremely low overhead. Otherwise, you still have C functions generated for your Objective-C methods, not C++ functions.
Create an Objective-C++ file template so you get a .mm file instead of a .m file when you create a new file. Make a copy of Apple's Objective-C class templates and rename the .m files to .mm. More detailed information on creating Xcode 4 file templates is available in the following article:
Creating Custom Xcode 4 File Templates
Language incompatibilities aside, one reason to avoid an entirely .mm project is that you might end up being tempted to start sections of your methods in c++, which will result in a project written in a (relatively obscure) hybrid of two languages, and will only be understood by people who know both. (I have done this before)
A nice way to avoid cluttering your obj-c headers with c++ is to declare instance variables in your implementation file (which is allowed as of xcode 4.2/clang 3.0, possibly earlier). Eg:
#implementation MyClass {
std::vector<int> myVector;
}
This helps to keep the points of contact between objective-c and c++ minimised.
I use .mm file exclusively for my iOS code and have never had any issues. Yes, my compiles are a little slower in that a clean compile takes 15 seconds vs 10 seconds. At least on a iMac, it's not significant.
I recognize that this is a general type of question but I'd be interested in your opinion on:
why are #interface #protocol and #property definitons seperated into a .h header file and then imported into the implementation file?
Is there anybody out there who just defines everything in a .m file?
BTW> its not that I am planning on not using .h files, just trying to understand the thinking behind it!
Because Objective-C relies on standard C infrastructure in which every compilation unit (.m) is compiled separately and then all of them are linked together.
This means that the static type checking phase of the Objective-C compiler will need just the .h files to know the characteristics of declared classes (eg. signatures of methods) but just to ensure that everything is used as it is supposed to be, and this is why you #import them in other source files that require what you declared inside the header.
if you have A.h/.m and B.h/.m which uses A you can think of the header file like a contract: "if you want to use A, I will link its binary code at the end of the compilation phase, what A is able to provide is described in this header file and this is the only thing you should know"