Is every single file compiled in Objective-C? - objective-c

I would like to know, which code is compiled when i build the project in Objective-C - every single line of code in my project, or only those, that are called from the main.c and then from the ones that are called from them?
I mean, does the compiler separate the project to the simply connected domains and compiles the one that is linked to the main, or it just compiles it all?
Thank you, guys!

The compiler does not perform semantical analysis on your code. It compiles exactly what you tell it to compile -- Xcode generally invokes the compiler in a way that it compiles every file into your application. However, it's unnecessary to compile/link the files from which no classes/functions are used; although not compiling files from which you use classes/functions results in a linkage error (that is, the compiler won't be able to find some symbols in the binary file while putting together the object code for the final executable).

All files in your project get compiled, except for the header files that are not included from any of the .m files, or headers the inclusion of which is suppressed conditionally.

A Xcode project consists of one or more targets.
For each target you can define, what *.m-files get compiled
if you add a new file to the project, you can specify to what target it will be added. (actually this is a place, where I often see, that the main target is not selected — beware)

Related

Where is the implementation of a framework or library added to an Xcode project?

When I add a framework to a project, using Cocoapods or manually, they contain only header files. From Xcode, using "Jump to definition" there is no definition (that means that there are no .m files).
When a function in a library is called, how does the compiler get its implementation if the .m file is not in the project?
To put it in a somewhat simplistic way, building an executable usually goes through at least these two stages:
compiling, which turns source code into binary code;
linking, which "glues" chunks of binary code into an executable.
Frameworks may include implementations in binary form, already compiled. These are then linked with your compiled sources. The compiler does not touch them in any way, and only needs the .h files that describe them. It's the linker's job to stitch them together with your code.
If you'd like to know more on the subject, the answers to the following questions contain more detailed information:
How does the compilation/linking process work? (The question is about C++, but C and Objective C go through mostly the same process)
What is compiler, linker, loader?

How to add .c and .h files to Atmel Studio 6?

I know there are a lot of questions on this topic, and I've looked through a fair number of them. However I am still having problems.
I started writing a test program for a prototype PCB, and now that it's grown to nearly 1000 lines I'm trying to break it up into libraries that I can use for particular functions.
I thought this would be very simple. Make .c and .h files for each library that I need. I.e. I would have OLED.h and OLED.c for functions that control an OLED display. Copy the appropriate functions/definitions into each file. Then copy these files into the solution in Atmel Studio. I put them into the src folder under the project name.
However, this doesn't work! I get an exceedingly long list of errors. All of the things that are defined in the .h file are apparently undefined as far as the compiler is concerned. I also get many error messages of the type "unknown type name int16_t/uint16_t/uint8_t/etc..." That part is really baffling to me. Why should it matter that functions are in an external library, now the compiler doesn't understand what those data types mean?
So, this is probably a stupid problem to have. I don't want Atmel Studio to control my libraries by wrapping them up in some "library project" or somethig, I want to put them in a folder of my choosing and add them when I need them. I've searched for answers to this problem and I find long tutorials about changing the compiler settings for the project, the linker settings, etc... I tried this tutorial and still no dice: http://www.engblaze.com/tutorial-using-avr-studio-5-with-arduino-projects/#setup
I also can't find a way to add something by right clicking the project and clicking "Add." It wants me to find .a files. The "Add Library" dialog box in Atmel Studio is awful, it seems.
Surely it can't be that convoluted to just add a library to an existing project and have it function normally?! I've used PICs in the past and coming to Atmel I've found horrible documentation and a weird super-slick super-fly whizz bang interface that can't leave well enough alone and obfuscates simple function. What can I do to add these libraries?
UPDATE: Seemed to answer my own question. Turns out I needed to include all of the libraries to recognize data types and whatnot into the .c file. I somehow assumed this only had to be done in the main file but obviously I was mistaken. Adding asf.h seems to work well as it includes all of the MCU specific port definitions/names and all of that. All good for now!
Adding library files to a solution should be simple. Go to the Solution Explorer, right-click on your solution, and go to "Add->Existing Item". If you want to add a pre-existing library and keep it in a separate folder from your solution, click the arrow next to "Add" and choose "Add as link". That saves many headaches due to having a duplicate copy of your library in your solution folder, and files not staying up-to-date.
You are right in saying that you need to include the necessary header files in the .c files where they are used.
The compiler compiles each C file separately, and then links them together at the end, so you got the error unknown typename int_* because the compiler had not seen the relevant header in the context of compiling that C file.
You also seem to be in some confusion as to the difference between definition and declaration.
A function is:
Declared in the header file. This means there is a function prototype, e.g. int some_func(char some_var); which tells the compiler that the function exists, but does not tell it what it is. This is necessary because the compiler only looks at one C file at a time, so needs to be told that other functions exist.
Defined in the C file.This is the actual function body, i.e. int some_func(char some_var) { do_stuff(some_var); }. After compilation of each individual C file in isolation, the linker is called to put all the pieces together and give you your final binary, which you flash to the device.
A function can be (and must be) defined only once, but may be declared many times - even in the same file, so long as the declarations are not conflicting.

How to reuse Fortran modules without copying source or creating libraries

I'm having trouble understanding if/how to share code among several Fortran projects without building libraries or duplicating source code.
I am using Eclipse/Photran with the Intel compiler (ifort) on a linux system, but I believe I'm having a bigger conceptual problem with modules than with the specific tools.
Here's a simple example: In ~/workspace/cow I have a source directory (src) containing cow.f90 (the PROGRAM) and two modules m_graze and m_moo in m_graze.f90 and m_moo.f90, respectively. This project builds and links properly to create the executable 'cow'. The executable and modules (m_graze.mod and m_moo.mod) are stored in ~/workspace/cow/Debug and object files are stored under ~/workspace/cow/Debug/src
Later, I create ~/workplace/sheep and have src/sheep.f90 as the program and src/m_baa.f90 as the module m_baa. I want to 'use m_graze, only: ruminate' in sheep.f90 to get access to the ruminate() subroutine. I could just copy m_graze.f90 but that could lead to code getting out of sync and doesn't take into account any dependencies m_graze might have. For these reasons, I'd rather leave m_graze in the cow project and compile and link sheep.f90 against it.
If I try to compile the sheep project, I'll get an error like:
error #7002: Error in opening the compiled module file. Check INCLUDE paths. [M_GRAZE]
Under Properties:Project References for sheep, I can select the cow project. Under Properties:Fortran Build:Settings:Intel Compiler:Preprocessor I can add ~/workspace/cow/Debug (location of the module files) to the list of include directories so the compiler now finds the cow modules and compiles sheep.f90. However the linker dies with something like:
Building target: sheep
Invoking: Intel(R) Fortran Linker
ifort -L/home/me/workspace/cow/Debug -o "sheep" ./src/sheep.o
./src/sheep.o: In function `sheep':
/home/me/workspace/sheep/src/sheep.f90:11: undefined reference to `m_graze_mp_ruminate_'
This would normally be solved by adding libraries and library paths to the linker settings except there are no appropriate libraries to link to (this is Fortran, not C.)
The cow project was perfectly capable of compiling and linking together cow.f90, m_graze.f90 and m_moo.f90 into an executable. Yet while the sheep project can compile sheep.f90 and m_baa.f90 and can find the module m_graze.mod, it can't seem to find the symbols for m_graze even though all the requisite information is present on the system for it to do so.
It would seem to be an easy matter of configuration to get the linker portion of ifort to find the missing pieces and put them together but I have no idea what magic words need to be entered where in the Photran UI to make this happen.
I confess an utter lack of interest and competence in C and the C build process and I'd rather avoid the diversion of creating libraries (.a or .so) unless that's the only way to make this work.
Ultimately, I'm looking for a pure Fortran solution to this problem so I can keep a single copy of the source code and don't have to manually maintain a pile of custom Makefiles.
So can this be done?
Apologies if this has already been documented somewhere; Google is only showing me simple build examples, how to create modules, and how to link with existing libraries. There don't seem to be (m)any examples of code reuse with modules that don't involve duplicating source code.
Edit
As respondents have pointed out, the .mod files are necessary but not sufficient; either object code (in the form of m_graze.o) or static or shared libraries must be specified during the linking phase. The .mod files describe the interface to the object code/library but both are necessary to build the final executable.
For an oversimplified toy problem such as this, that's sufficient to answer the question as posed.
In a larger project with more complex dependencies (in my case, 80+KLOC of F90 linking to the MKL version of LAPACK95), the IDE or toolchain may lack sufficient automatic or user-interface facilities to make sharing a single canonical set of source files a viable strategy. The choice seems to be between risking duplicate source files getting out of sync, giving up many of the benefits of an IDE (i.e. avoiding manual creation of make/CMake/SCons files), or, in all likelihood, both. While a revision control system and good code organization can help, it's clear that sharing a single canonical set of source files among projects is far from easy given the current state of Eclipse.
Some background which I suspect you already know: Typically (including ifort) compiling the source code for a Fortran module results in two outputs - a "mod" file that contains a description of the Fortran entities that the module defines that the compiler needs to find whenever it sees a USE statement for the module, and object code for the linker that implements the procedures and variable storage, etc., that the module defines.
Your first error (the one you solved) is because the compiler couldn't find the mod file.
The second error is because the linker hasn't been told about the object code that implements the stuff that was in the source file with the module. I'm not an Eclipse user by any means, but a brute force way of specifying that is just to add the object file (xxxxx/Debug/m_graze.o) as an additional linker option (Fortran Build > Settings, under Intel Fortran Linker > Command Line). (Other tool chains have explicit "additional object file" properties for their link stage - there may well be a better way of doing this for the Intel chain.)
For more involved examples you would typically create a library out of the shared code. That's not really C specific, the only Fortran aspect is that the libraries archive of object code needs to be provided alongside the mod files that the Fortran compiler generates.
Yes the object code must be provided. E.g., when you install libnetcdf-dev in Debian (apt-get install libnetcdf-dev), there is a /usr/include/netcdf.mod file that is included.
You can now use all netcdf routines in your Fortran code. E.g.,
program main
use netcdf
...
end
but you'll have link to the netcdf shared (or static) library, i.e.,
gfortran -I/usr/include/ main.f90 -lnetcdff
However, as user MSB mentioned the mod file can only be used by gfortran that comes with the distribution (apt-get install gfortran). If you want to use any other compiler (even a different version that you may have installed yourself) then you'll have to build netcdf yourself using that particular compiler.
So creating a library is not a bad solution.

Running Fortran on Xcode

I am trying to run sample Fortran code on Xcode 4.3 using a 64-bit compiler and it will not build correctly. The main problem is that despite my best efforts, I cannot get the separate .f90 files to interact with each other, thus code like
USE ElementModule, ONLY : ElementType
will not work. Does anybody have any answers regarding how to get the separate .f90 files to read each other. I'm aware you have to include specific modules, but my search hasn't given me any straight answers regarding what those specific modules are.
Normally when F90 code compiles, it generates 2 files: an object file and a mod file. When compiling subsequent modules, the mod files are used for the USE statements.
If you have circular dependency, then you have to build two or more times. Best to avoid circular dependency if you can avoid it.
The mod files are normally picked up by the same directive that tells the compiler where the include files are.

How do I add a call to FORTRAN code to a project in Xcode 4.5?

My company has a bunch of Fortran code. Traditionally, we compiled the code we needed into a .dll and called that .dll when we needed a calculation done. We are now trying to create an iPad app, which unfortunately means we can't just call a .dll anymore.
One of my coworkers have managed to make a simple Command Line Tool project, where we call a Fortran file to write "Hello, World" in the debugger. However, when I try to get it to work on view based iPad app, I get a bunch of linker errors saying the symbols I'm using cannot be found. I know that the Command Line Tool uses a .cpp file to actually run the Fortran, and I've seen many threads concerning calling .cpp files in an app, but all the ones I've seen are outdated, directly contradict each other, and their fixes don't work for me.
My question is, is there a more direct way to call Fortran straight from a .m file? If not, what do I have to do to take the working Command Line Tool and get it into an app?
UPDATE 1: following the tutorials posted in the comments, I have been able to create a .o file from my Fortran code. I can do a File-Add Files to add it in easily enough, but now how do I actually call it?
UPDATE 2: Okay, baby steps. I found out you can make a .a static library (I'll call it "new_library") from .o files ("source_file.o") using the Terminal command ar crv new_library.a source_file.o (you can do it for multiple .o files by just adding source_file2.o source_file3.o for as many .o files as you want - NOTE: make sure you use cd to get to the folder where the .o files are located). I'm pretty sure Xcode will work with .a files, but it seems a .h file is still needed to let the other files in the project (like the view controllers) make calls to what's in the .a file. I know I can make a new .a file from Xcode itself (New Project -> iOS -> Framework & Library -> Cocoa Touch Static Library), but when I've done it that way in the past, I just write normal .m and .h files, and when I build the new library it just mashes all the .m files into 1 .a. When I want to use the code in that .a in another project, I just import the .a and all the .h files into the new project, and I can call the methods in the .a file just as if I had imported all the separate .m files. So the next question is, do I still need a .h when my .a is made with the terminal instead of Xcode? If so, how would I make a Fortran header file? If not, how do I call my Fortran code in the .a?
Let's try to sum up things:
You need a FORTRAN cross compiler that can produce ARM code. GCC is probably a good choice. But you will need to build it yourself from the source downloads.
Compile your FORTRAN code and put it into a static library. This task is perform outside XCode, probably from the command line.
Write C header files for those FORTRAN routines that you wand to call directly from C. You might want to look at Fortran and C/C++ mixed programming or Tutorial: Using C/C++ and Fortran together. These pages explain how to map the C data types to FORTRAN data types and vice versa.
Add the C header files and the static library to the XCode project.
Import the C header files into your Objective-C files (.m) where required and call the FORTRAN routines as if they were C functions.
Build the iOS app with XCode.