How to write a Makefile

Assume there are more number of source files to be compiled using a set of commands everytime is a tedious process. So there is a facility to compile everything at a stretch is by the use of a Makefile.

The makefile can be named as either “Makefile” or “makefile”.

Let me define four files for my simple application, create a new directory and store all the files given below

  • main.c  (which contains the main program)

  • sum.c (summing function is defined)

  • hello.c (print hello world)

  • function.h (function prototypes are declared)

You can download all the files here

//function.h

int sum(int,int);
void print_hello();

//hello.c

#include <stdio.h>
#include "function.h"
void print_hello()
{
printf("Hello World \n");
}

//sum.c

#include "function.h"
int sum(int a, int b)
{
int c;
c=a+b;
return c;
}

//main.c

#include <stdio.h>
#include "function.h"
int main()
{
int a=10,b=20,c;
print_hello();
c=sum(a,b);
printf("The sum of two numbers is %d ",c);
return 0;
}

There are different methods of compiling this file

Method 1: (gcc command based)

gcc main.c sum.c hello.c –o pradeep

once you execute the above command, an executable named pradeep is created and you can see the output by typing ./pradeep

Method 2: using Makefile

The basic makefile is composed of:

This syntax applied to example would look like:

target: dependencies

[tab] system command

all:

gcc main.c sum.c hello.c –o pradeep
to run this make file(the file name should be Makefile or makefile), execute the command


make


Method 3: using Makefile with dependencies

There may be a chance of using different targets in your makefile, this is because if you modify a single file in your project, you don't have to recompile everything, only what you modified.
Here is an example

all: pradeep

hello: main.o sum.o hello.o
gcc main.o sum.o hello.o -o hello


main.o: main.c
gcc –c main.c


sum.o: sum.c
gcc –c sum.c


hello.o: hello.c
gcc –c hello.c




Method 4: using variables

CC=gcc
CFLAGS=-c -Wall


all: hello

hello: main.o sum.o hello.o
$(CC) main.o sum.o hello.o -o hello


main.o: main.c
$(CC) $(CFLAGS) main.c


sum.o: sum.c
$(CC) $(CFLAGS) sum.c


hello.o: hello.c
$(CC) $(CFLAGS) hello.c


Method 5:

With this brief introduction to Makefiles, you can create some very sophisticated mechanism for compiling your projects.

CC=gcc
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.c hello.c sum.c
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello


all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@


.c.o:
$(CC) $(CFLAGS) $< -o $@


If you understand this last example, you could adapt it to your own personal projects changing only 2 lines, no matter how many additional files you have !!!.

Thanks to:http://mrbook.org/tutorials/make/

The above examples is tested only on linux and Windows also supports make utility (through nmake utility), the readers are advised to work on their own in Windows. the following link will show you the way to nmake utility

http://msdn.microsoft.com/en-us/library/dd9y37ha(VS.71).aspx

Process ID and Parent Process ID in Linux

When referring to process IDs in a C or C++ program, always use the pid_t typedef, which is defined in <sys/types.h>.A program can obtain the process ID of the process it’s running in with the getpid() system call, and it can obtain the process ID of its parent process with the getppid() system call. For instance, the program in Listing 3.1 prints its process ID and its parent’s process ID.

   1:  // Printing the process ID and parent process ID
   2:  #include <stdio.h>
   3:  #include <unistd.h>
   4:  int main ()
   5:  {
   6:  printf (“The process ID is %d\n”, (int) getpid ());
   7:  printf (“The parent process ID is %d\n”, (int) getppid ());
   8:  return 0;
   9:  }
 
 


fork

When a program calls fork, a duplicate process, called the child process, is created. The parent process continues executing the program from the point that fork was called. The child process, too, executes the same program from the same place. So how do the two processes differ? First, the child process is a new process and therefore has a new process ID, distinct from its parent’s process ID.One way for a program to distinguish whether it’s in the parent process or the child process is to call getpid. However, the fork function provides different return values to the parent and child processes—one process “goes in” to the fork call, and two processes “come out,” with different return values.The return value in the parent process is the process ID of the child.The return value in the child process is zero. Because no process ever has a process ID of zero, this makes it easy for the program whether it is now running as the parent or the child process.

The following example show the fork to duplicate a program’s process. Note that the first block of the if statement is executed only in the parent process, while the else clause is executed in the child process.


   1:  // to create a process using fork()
   2:  #include <stdio.h>
   3:  #include <sys/types.h>
   4:  #include <unistd.h>
   5:  int main ()
   6:  {
   7:  pid_t child_pid;
   8:  printf (“the main program process ID is %d\n”, (int) getpid ());
   9:  child_pid = fork ();
  10:  if (child_pid != 0) {
  11:  printf (“this is the parent process, with id %d\n”, (int) getpid ());
  12:  printf (“the child’s process ID is %d\n”, (int) child_pid);
  13:  }
  14:  else
  15:  printf (“this is the child process, with id %d\n”, (int) getpid ());
  16:  return 0;
  17:  }


Observation:


The program can be compiled using gcc compiler

$: gcc –o <linkname> <filename.c>

$: ./linkname

Printing the Uptime and Idle Time of processor (Linux)

/proc/uptime file contains only two values in seconds, one is the Uptime of the processor (the time upto which the processor was on) and another is the idle time of all the processors (cores).

So idle is always higher than the uptime in case of multicore processors.

The following C program shows the uptime and idle time in terms of days hours and minutes. This is a very simple program just tells you how to convert a given time in days, hours, minutes and seconds.

using C FILE concept, the /proc/uptime file is been read using the “r” mode and values are fetched and then converted into days, hours and seconds.

   1:  // printing the uptime and idle time
   2:  #include <stdio.h>
   3:  /* Summarize a duration of time to standard output. TIME is the
   4:  amount of time, in seconds, and LABEL is a short descriptive label. */
   5:  void print_time (char* label, long time)
   6:  {
   7:  /* Conversion constants. */
   8:  const long minute = 60;
   9:  const long hour = minute * 60;
  10:  const long day = hour * 24;
  11:  /* Produce output. */
  12:  printf (“%s: %ld days, %ld:%02ld:%02ld\n”, label, time / day,
  13:  (time % day) / hour, (time % hour) / minute, time % minute);
  14:  }
  15:  int main ()
  16:  {
  17:  FILE* fp;
  18:  double uptime, idle_time;
  19:  /* Read the system uptime and accumulated idle time from /proc/uptime. */
  20:  fp = fopen (“/proc/uptime”, “r”);
  21:  fscanf (fp, “%lf %lf\n”, &uptime, &idle_time);
  22:  fclose (fp);
  23:  /* Summarize it. */
  24:  print_time (“uptime “, (long) uptime);
  25:  print_time (“idle time”, (long) idle_time);
  26:  return 0;
  27:  }

Printing Linux Environment using C Program


Linux provides each running program with an environment. The environment is a collection of variable/value pairs. Both environment variable names and their values are character strings. By convention, environment variable names are spelled in all capital letters. You’re probably familiar with several common environment variables already.

For instance:

USER contains your username.

HOME contains the path to your home directory.

PATH contains a colon-separated list of directories through which Linux searches for commands you invoke.

DISPLAY contains the name and display number of the X Window server on which windows from graphical X Window programs will appear.

//Printing the Execution Environment
#include <stdio.h>
/* The ENVIRON variable contains the environment. */
extern char** environ;
int main ()
{
char** var;
for (var = environ; *var != NULL; ++var)
printf (“%s\n”, *var);
return 0;
}

Setting Path in Linux

Setting a path information in windows is always been easier, since there is a GUI facility “Environmental Variables”, but I Linux setting a path is always been tricky and it should be done through CLI (Command Line Interface).  Here are the following ways to do:

Method 1:

For each user (Your login id) of Linux has a home folder (/home/username), there will be a file called as .bashrc (Ubuntu and Fedora) or .bash_profile (Fedora), whatever path has to be set, it should be entered in the above file.

For example: if the software is installed in /home/username/software1/, then the PATH has to be set in the .bashrc or .bash_profile file like this

export PATH=$PATH:/home/username/software1/

($PATH is a shell variable refers to the previous set path also to be included in the PATH setting.)

For Java Home

export JAVA_HOME=/home/username/<Java_path>

Method 2:

The above method of path is applicable only for that user. if other users wanted to access the software, then they have to set the paths. Because, for each user of Linux, the .bashrc or .bash_profile file exists.

if the same path is set for all the users, then the super user can set the path information in the following file

/etc/profile.d/your_path_name.sh

Open the file name (of your choice, but the extension is .sh) and has to be stored in /etc/profile.d/

This folder will be read during the booting process, so all the users of that machine will be able to access the software. The following line is copied to the shell file

export PATH=$PATH:/home/username/software1/

export JAVA_HOME=/home/username/<Java_path>

Basic Linux Commands for Beginners

Using a Linux machine using a shell Prompt is always a challenge these days. Many of us feel it is tougher to use Linux because of its Conventional Shell prompt, but the GUIs are so sophisticated when compared with Other Operating systems like windows, etc.

But still as a developer, one has to be good at Linux both in the GUI and as well as in Shell. For novice users and beginners, the following commands will make understand the importance of Linux and their commands.

Basic Commands

Commands usage Explanation
ls ls to list the files and folders
ls –l ls –l to list the files and folders in long format
chmod chmod 777 filename to change the mode of a file
pwd pwd display the present working directory
passwd passwd Changing the password of the current user
echo echo “hello” display the string hello
  echo $PATH Display the PATH Variable stored
  echo $HOME display the Home folder of the current user
  echo $SHELL displays the type of shell used /bin/bash
tar tar xf filename.tar to decompress the tar file and extract the folders
  tar xvf filename.tar to decompress the tar file and extract the folders with verbose mode
  tar zxvf filename.tar.gz to decompress from gzip and the extract the tar created.
gzip gzip –d filename.tar.gz
gzip –d filename.gz
to decompress the gzip file
bzip2 bzip2 –d filename.tar.bz2
bzip2 –d filename.bz2
to decompress the bzip2 file
rm rm name remove a file or directory called name (the directory should be empty to be deleted)
  rm –rf name

Kill off an entire directory and all it’s
includes files and subdirectories

cp cp filename /home/hello copy the file called filename to the folder /home/hello
mv mv filename /home/hello move the file called filename to the directory /home/hello
cat cat filename display the file called filename
su su login to superuser from current login (you should know the super user password)
exit exit exit out of the shell window or Stop being superuser and revert to normal user
dmesg dmesg display the boot time messages
ls ls list current processes
kill kill 123 kill a specific process with ID 123
ifconfig ifconfig

List ip addresses for all devices on
the machine

rpm rpm –ivh filename.rpm Install the rpm package called name
  rpm –Uvh filename.rpm

Upgrade the rpm package called
name

  rpm –e package

Delete the rpm package called
package

  rpm –l package

List the files in the package called
package

./configure ./configure

Execute the script preparing the
installed files for compiling

find find / –name fname

Starting with the root directory, look
for the file called fname

  find / -name ”*fname*”

Starting with the root directory, look
for the file containing the string fname

 

File Permissions

image

If the command ls -l is given, a long list of file names is displayed. The first column in this list details the permissions  applying to the file. If a permission is missing for a owner,
group of other, it is represented by - eg.

drwxr-x--x
Read = 4
Write = 2
Execute = 1
File permissions are altered by giving the chmod command and the appropriate octal code for each user type. eg chmod 7 6 4 filename will make the file called filename R+W+X for the owner, R+W for the group and R for others.

chmod 7 5 5 Full permission for the owner, read and execute access for the group and others.
chmod +x filename Make the file called filename executable to all users.