Algorithmes et C appliqués aux Systèmes Numériques
			
                           Les appels systèmes, les erreurs et la chaine de compilation  
                        John Samuel 
                          CPE LyonAnnée : 2019-2020Courriel : john(dot)samuel(at)cpe(dot)fr
                        
                
                              
		 
		
	 
	
		
		
			Objectifs 
			
				La portée des variables 
				Préprocesseur 
				Les appels systèmes 
				Les erreurs 
				La chaine de compilation 
			 
		 
		
	 
	
		
		
                        Une variable constante 
                        
			  
				/* Une variable constante
				#include  <stdio.h> int  main ()
				{ const int  year  = 2017 ; // une variable constante
                                  year  = 2019 ; // une variable constante
				  printf ("C'est l'annee %d" , year ); //affiche 2017return  0;
                      
		 
		
	 
	
		
		
			Erreur pendant la compilation 
                        
			  $ gcc bonjour.c
                          const.c: In function ‘main’:
                          const.c:5:8: error: assignment of read-only variable ‘year’
                          year = 2019;
                          
                        
		 
		
	 
	
		
		
                        Une variable globale 
                        
			  
				/* affiche un message à l'écran en utilisant une variable globale
				#include  <stdio.h> int  year  = 2017  // une variable globale;
				int  main ()
				{ printf ("C'est l'annee %d" , year ); //affiche 2017return  0;
                      
		 
		
	 
	
		
		
                        Une variable locale 
                        
			  
				/* affiche un message à l'écran en utilisant une variable locale
				#include  <stdio.h> int  year  = 2017  // une variable globale;
				int  main ()
				{ int  year  = 2018  // une variable locale; printf ("C'est l'annee %d" , year ); //affiche 2018return  0;
                      
		 
		
	 
	
		
		
                        Une variable locale 
                        
			  
				/* affiche un message à l'écran en utilisant une variable locale
				#include  <stdio.h> int  year  = 2017  // une variable globale;
				int  main ()
				{ int  year  = 2018  // une variable locale; int  year  = 2019  // une variable locale; printf ("C'est l'annee %d" , year ); //affiche 2019return  0;
                      
		 
		
	 
	
		
		
                        Passage par valeur 
                        
			  
                        void 
                        echange(
                        int 
                        a ,
                        int 
                        b 
                        ) { 
                          int 
                        temp 
                        = a ;
                          a 
                        = b ;
                          b 
                        = temp ;
                        }
                                  int  main ()
				{ int  a  = 10;
                          int  b  = 20;
                          echange (a , b );
				   printf ("a: %d, b: %d" , a , b ); //affiche 10, 20return  0;
                      
		 
		
	 
	
		
		
                        Passage par référence 
                        
			  
                        void 
                        echange(
                        int 
                        *a ,
                        int 
                        *b 
                        ) { 
                          int 
                        temp 
                        = *a ;
                          *a 
                        = *b ;
                          *b 
                        = temp ;
                        }
                                  int  main ()
				{ int  a  = 10;
                          int  b  = 20;
                          echange (&a , &b );
				   printf ("a: %d, b: %d" , a , b ); //affiche 20, 10return  0;
                      
		 
		
	 
	
		
		
			
cercle.c 
			#define  PI 3.14159
			float  area (
			float  radius ) { return (PI * radius 
						* radius ); 
	
		
		
			Prototype (defs.h) 
                        
			#define  PI 3.14159
			cercle.c 
			
				#include  "defs.h" #ifndef  PI // Si PI n'est pas défini#define  PI 3.14159#endif float  area (
					float  radius ) { return (PI * radius 
						* radius );
			
				Remarque 1:  PI n'est pas une variable
				Remarque 2:  Utilisez l'option  gcc -E   pour comprendre l'objectif d'un préprocesseur
			
		 
		
	 
	
		
		
                        Prototype (defs.h) 
                        
			Erreur:  PI n'est pas une variable
                        
			
				#include  "defs.h" #ifndef  PI #define  PI 3.14159#endif float  area (
					float  radius ) { return (PI * radius 
						* radius );
                        Erreur (compilation) 
		 	
                        Error: lvalue required as left operand of assignment
                        PI = 3.15;
                           ^
		 	
		 
		
	 
	
		
		
                        
operators.h 
			
                                int 
                                add(
                                int ,
                                int ); 
			L'utilisation 
                        
		        #include 
                        "operators.h"  // en-têtes(headers) #include 
                        "operators.h"  // pas d'erreurs 
		
		
	 
	
		
		
                        
operators.h 
			
                                int 
                                num  = 20; 
			L'utilisation 
                        
		        #include 
                        "operators.h"  // en-têtes(headers) #include 
                        "operators.h"  // erreur 
		 	
                        $ gcc operator.c
                        note: previous definition of ‘num’ was here
                        int num=20;
		 	
		
		
	 
	
		
		
                        
operators.h 
			
				#ifndef  __OPERATORS_H__ #define  __OPERATORS_H__ int 
                                num  = 20; int 
                                add(
                                int ,
                                int ); #endif  //__OPERATORS_H__
		 	
			L'utilisation 
                        
		        #include 
                        "operators.h"  // en-têtes(headers) #include 
                        "operators.h"  // 2eme fois, mais pas d'erreurs 
		
		
	 
	
		
		
			
				#ifndef  PI #define  PI 3.14159#endif #ifndef  square #define  square(value) value * value#endif float  area (
					float  radius ) { return (PI * square(radius) );
			
				Remarque:  Il'n y a pas d'espace entre square et (
			
		 
		
	 
	
		
		
			
                          struct  couleur1{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
			
			
                          struct  couleur2{ 
                           unsigned char  rouge;
			   unsigned int   count;
                           unsigned char  vert;
                           unsigned char  bleu;
                        };
			
			
                           printf (
                          "size- couleur1: %lu, couleur2: %lu\n" , 
                            sizeof (
                          struct 
                          couleur1 ),
                          sizeof (
                          struct 
                          couleur2 ));
			
                   
		     Question:  Quel est l'affichage de ce programme?
                   
		 
		
	 
	
		
		
                        Alignement d'un octet 
                        
                           couleur1 
                         
                        
                           couleur2 
                         
		 
		
	 
	
		
		
                        Alignement de 4 octets 
                        
                           couleur1 
                         
                        
                           couleur2 
                         
		 
		
	 
	
		
		
                        En utilisant gcc 
			
                          #pragma pack(push) 
                          #pragma pack(1)  //alignement d'un octet
                          struct  couleur3{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                        #pragma pack(pop) 
                           printf (
                          "%lu\n" ,
                          sizeof (struct  couleur3 ));
			
                   
		     Remarque:  L'affichage de ce programme: 7
		   
			
                            
		 
		
	 
	
		
		
			
                          struct  couleur4{ //alignement de 4 octets
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
                           unsigned char  _pad;
			   unsigned int   count;
                        };
                          struct  couleur5{ //alignement de 4 octets
                           unsigned char  rouge;
                           unsigned char  _pad1[3];
			   unsigned int   count;
                           unsigned char  vert;
                           unsigned char  bleu;
                           unsigned char  _pad2[2];
                        };
			
                   
		     Remarque:  Utilisez l'option  gcc -Wpadded   pour savoir si une structure nécessite du padding our être alignée
			
                   
		 
		
	 
	
		
		
			
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                          int  main () {
                           struct  couleur c1 ;
                           struct  couleur *scptr  = &c1 ;
                           c1.bleu  = 0xff ;
                           scptr->bleu  = 0x01 ;
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0x01
                        }
			
		
		
	 
	
		
		
			
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                          void  change (
                          struct  couleur *c) {
                           c->bleu  = 0x01 ;
                        }
                          int  main () {
                           struct  couleur c1 ;
                           c1.bleu  = 0xff ;
                           change(&c1 );
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0x01
                        }
			
		
		
	 
	
		
		
			Une liste de couleurs simplement chaînée 
                        
                           
		 
		
	 
	
		
		
			
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
                        };
                          void  nochange (
                          struct  couleur c) {
                           c.bleu  = 0x03 ;
                        }
                          int  main () {
                           struct  couleur c1 ;
                           c1.bleu  = 0xff ;
                           nochange(c1 );
                           printf (
                          "c1.bleu: %hhx\n" , c1.bleu ); //0xff
                        }
			
		
		
	 
	
		
		
			Une liste de couleurs simplement chaînée 
			
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
			   struct  couleur *next;
                        };
			
                        
                           
		 
		
	 
	
		
		
			Une liste de couleurs simplement chaînée 
			
                          int  main () {
                           struct  couleur first , c1 , c2 ;
                           struct  couleur *cptr ;
                           first.next  = &c1 ;
                           c1.next  = &c2 ;
                           c2.next  = NULL ;
                           cptr  = &first ;
                           while (cptr  != NULL ) { //navigation
                            printf (
                          "cptr->bleu: %hhx\n" , cptr->bleu );
                            cptr  = cptr->next ; //couleur suivante
                           }
                        }
			
                        
                           
		 
		
	 
	
		
		
			Une liste d'entiers simplement chaînée 
                          
                             
		 
		
	 
	
		
		
			
Une liste d'entiers simplement chaînée 
			
                          struct  element{ 
			   unsigned int   numero;
			   struct  element *suivant;
                        };
                        // insertion d'un élement dans une listevoid  insertion (struct  element *, int );
                        // parcours de la listevoid  parcours (struct  element *);
			
		
		
	 
	
		
		
			
La saisie d'entiers par l'utilisateur 
			
                          int  main () {
                           struct  element premier ;
                           premier.suivant  = NULL ;
                           while (1) {
                             int  num ;
                             char  strnum [50];
                             fgets (strnum , sizeof(strnum ), stdin );
                             if (strcmp (strnum , "FIN\n" ) == 0) {
                               break ;
                             }
                             sscanf (strnum , "%d\n" , &num );
                             insertion (&premier , num );
                           }
                           parcours (&premier );
                        }
			
		
		
	 
	
		
		
			
Insertion d'un élément et parcours d'une liste simplement chaînée 
			
                          void  insertion (struct  element *premier , int  num ) {
                            struct  element *nouveau ;
                            nouveau  = malloc (sizeof (*nouveau ));
                            nouveau->num  = num; 
                            nouveau->suivant  = premier->suivant ;
                            premier->suivant  = nouveau ;
                          }
                           
                          void  parcours (struct  element *premier ) {
                             struct  element *elem  = premier ;
                             while (elem  != NULL ) {
                             printf("%d\n" , elem->num );
                             elem  = elem->suivant ;
                            }
                           }
			 
		
		
	 
	
		
		
			Une liste de couleurs doublement chaînée 
                        
                           
		 
		
	 
	
		
		
			
Une liste de couleurs doublement chaînée 
			
                          struct  couleur{ 
                           unsigned char  rouge;
                           unsigned char  vert;
                           unsigned char  bleu;
			   unsigned int   count;
			   struct  couleur *next;
			   struct  couleur *prev;
                        };
			
		
		
	 
	
		
		
			
                          int  main () {
                           struct  couleur first , c1 , c2 , last ;
                           struct  couleur *cptr  = &last ;
                           first.next  = &c1 ;
                           first.prev  = NULL ;
                           last.next  = NULL ;
                           last.prev  = &c2 ;
                           c1.next  = &c2 ;
                           c1.prev  = &first ;
                           c2.next  = &last ;
                           c2.prev  = &c1 ;
                           while (cptr  != &first ) { //navigation
                            printf (
                          "cptr->bleu: %hhx\n" , cptr->bleu );
                            cptr  = cptr->prev ; //couleur précédente
                           }
                        }
			
		
		
	 
	
		
		
			Une liste d'entiers simplement chaînée 
                          
                             
		 
		
	 
	
		
		
			
Insertion d'un élément et parcours d une liste doublement chaînée 
			
                           struct  element  {
                             int  num ;
                             struct  element *suivant ;
                             struct  element *precedent ;
                           };
                           
                           struct  liste  {
                             struct  element premier ;
                             struct  element dernier ;
                           };
                           
                           void  insertion_debut (struct  liste  *, struct  element  *);
                           void  insertion_fin (struct  liste  *, struct  element  *);
                           void  parcourir_debut (struct  liste  *);
                           void  parcourir_fin (struct  liste  *);
			
		
		
	 
	
		
		
			
Une liste d'entiers doublement chaînée 
			
                           void  insertion_debut (struct  liste *liste , struct  element *nouveau ) {
                             nouveau->suivant  = liste->premier.suivan t;
                             nouveau->precedent  = &liste->premier ;
                             liste->premier.suivant->precedent  = nouveau ;
                             liste->premier.suivant  = nouveau ;
                           }
                           
                           void  insertion_fin (struct  liste *liste , struct  element *nouveau ) {
                             nouveau->suivant  = &liste->dernier ;
                             nouveau->precedent  = liste->dernier.precedent ;
                             liste->dernier.precedent->suivant  = nouveau ;
                             liste->dernier.precedent  = nouveau ;
                           }
			
		
		
	 
	
		
		
			
Une liste d'entiers doublement chaînée 
			
                           void  parcourir_debut (struct  liste *liste ) {
                             struct  element *elem  = liste->premier.suivant ;
                             while (elem  != &liste->dernier ) {
                                printf ("%d\n" , elem->num );
                                elem  = elem->suivant ;
                             }
                           }
                           
                           void  parcourir_fin (struct  liste *liste ) {
                             struct  element *elem  = liste->dernier.precedent ;
                             while (elem  != &liste->premier ) {
                                printf ("%d\n" , elem->num );
                                elem  = elem->precedent ;
                             }
                           }
			
		
		
	 
	
		
		
			
La saisie d'entiers par l'utilisateur 
			
                           int  main () {
                             struct  liste liste ;
                             liste.premier.suivant  = &liste.dernier ;
                             liste.dernier.precedent  = &liste.premier ;
                             liste.premier.precedent  = NULL ;
                             liste.dernier.suivant  = NULL ;
                           
			
		
		
	 
	
		
		
			
La saisie d'entiers par l'utilisateur 
			
                             while  (1) {
                                char  strnum [50];
                                struct  element *elem  = malloc (sizeof (*elem ));
                                fgets (strnum , sizeof (strnum ), stdin );
                                if (strcmp(strnum, "FIN\n" ) == 0) {
                                   break ;
                                }
                           
                                sscanf (strnum , "%d\n" , &elem->num );
                                insertion_fin (&liste, elem );
                             }
                           
                             parcourir_debut (&liste );
                             parcourir_fin (&liste );
                           }
			
		
		
	 
	
		
		
                        
                        int 
                        add(
                        int 
                        a ,
                        int 
                        b 
                        ) { 
                         return 
                        a 
                        + b ;
                        }
                        int 
                        subtract(
                        int 
                        a ,
                        int 
                        b 
                        ) { 
                         return 
                        a 
                        - b ;
                        }
                        
		
		
	 
	
		
		
                        
                          int  main () {
                           int  (*func )(int , int ); //pointeur de function
                           char  op  = '-' ;
                           int  num1  = 20 , num2  = 30 ;
                           if  (op  == '+' ) {
                            func  = add ;
   }
                           else  {
                            func  = subtract ;
                           }
                           printf ("value: %d\n" ,func (20, 30));
                          }
                        
		
		
	 
	
		
		
			
				/* Fichier: stats.c #include 
                                        <stdio.h>  // en-têtes(headers) #include 
                                        <sys/types.h>   #include 
                                        <sys/stat.h>   #include 
                                        <unistd.h>   int  main (int  argc , char **  argv)
				{ 
                                      struct stat   sf ;
                                      stat  ("./stats.c" , &sf);
                                      printf ("Taille: %ld octets" , sf.st_size );
                                      return  0;
		
		
	 
	
		
		
			
					#include 
                                        <stdio.h>  // en-têtes(headers) #include 
                                        <sys/types.h>   #include 
                                        <sys/stat.h>   #include 
                                        <unistd.h>   #include 
                                        <stdlib.h>   int  main (int  argc , char **  argv)
				{ 
                                      struct stat   sf ;
                                      int   status ;
                                      status  = stat  (argv[1] , &sf);
                                      if  (status  == -1) {
                                       perror ("Stats" );
                                       return (EXIT_FAILURE);
                                      }
                                      printf ("Taille: %ld octets" , sf.st_size );
                                      return  0;
		
		
	 
	
		
		
			
La compilation  
			
				$ gcc -o stats  stats.c
			
			L'exécution 
			
				$./stats stats.c
                                Taille: ... octets
				$ echo $? 
                                0
			
		
		
	 
	
		
		
			
La compilation  
			
				$ gcc -o stats  stats.c
			
			L'exécution 
			
                        $ ./stats nostats 
                        Stats: No such file or directory
                        $ echo $?
                        1
			
		
		
	 
	
		
		
                
                    #include  <sys/types.h>
                    #include  <dirent.h>
                    #include  <unistd.h>
                    #include  <stdlib.h>
                    #include  <stdio.h>
                    
                    int  main (int  argc , char  **argv ) {
                       if  (argc  < 2) {
                        printf ("Usage: readdir path\n" );
                        return (EXIT_FAILURE);
                       }
                    
                       DIR  *dirp  = opendir (argv [1]);
                    
                       if  (dirp  == NULL ) {
                        perror ("opendir" );
                        return (EXIT_FAILURE);
                       }
                    
                
		
		
	 
	
		
		
                
                       struct  dirent * ent;
                       while (1) {
                        ent  = readdir (dirp );
                        if  (ent  == NULL ) {
                         break ;
                        }
                        printf ("%s\n" , ent->d_name );
                       }
                    
                       closedir (dirp );
                     
                       return (0);
                    }
                
		
		
	 
	
        
        
		
		
                   
                    #define  PORT 8089
                    int  main() {
                     int  socketfd;
                     int  bind_status;
                     struct  sockaddr_in server_addr, client_addr;
                    
                     /*
                      * Creation of a socket
                      * AF_INET: IPv4 Internet protocols
                      * SOCK_STREAM: two-way, connection-based byte streams
                      */ 
                     socketfd = socket(AF_INET, SOCK_STREAM, 0);
                     if  ( socketfd < 0 ) {
                      perror("Unable to open a socket" );
                      return  -1;
                     }
                  
		
		
	 
	
		
		
                   
                       //server address details 
                       memset(&server_addr, 0, sizeof(server_addr));
                       server_addr.sin_family = AF_INET;
                       server_addr.sin_port = htons(PORT);
                       server_addr.sin_addr.s_addr = INADDR_ANY;
                    
                       //Connect to the server 
                       int  connect_status = connect(socketfd, (struct sockaddr *) 
                           &server_addr, sizeof(server_addr));
                       if  ( connect_status < 0 ) {
                          perror("Unable to connect to server" );
                          return  -1;
                       }
                   
		
		
	 
	
	
		
		
                   
                    int  main() {
                    
                     int  socketfd;
                     int  bind_status;
                    
                     struct  sockaddr_in server_addr, client_addr;
                    
                     /*
                      * Creation of a socket
                      * AF_INET: IPv4 Internet protocols
                      * SOCK_STREAM: two-way, connection-based byte streams
                      */ 
                     socketfd = socket(AF_INET, SOCK_STREAM, 0);
                     if  ( socketfd < 0 ) {
                      perror("Unable to open a socket" );
                      return  -1;
                     }
                    
                   
		
		
	 
	
		
		
                   
                       int  option = 1;
                       setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, 
                        &option, sizeof(option));
                    
                       //server address details 
                       memset(&server_addr, 0, sizeof(server_addr));
                       server_addr.sin_family = AF_INET;
                       server_addr.sin_port = htons(PORT);
                       server_addr.sin_addr.s_addr = INADDR_ANY;
                    
                       bind_status = bind(socketfd, (struct sockaddr *) 
                         &server_addr, sizeof(server_addr));
                       if  (bind_status < 0 ) {
                        perror("Unable to bind to socket");
                        return  -1;
                       }
                    
                       // Start listening to the socket 
                       listen(socketfd, 10);
                   
		
		
	 
	
		
		
                   
                       char  data[1024];
                    
                       int  client_addr_len = sizeof(client_addr);
                       int  client_socket_fd = accept(socketfd, 
                         (struct sockaddr *) &client_addr, &client_addr_len);
                       if (client_socket_fd < 0 ) {
                        perror("Unable to accept client requests");
                        return  -1;
                       }
                   
		
		
	 
	
		
		
                  6 étapes de la chaine de compilation 
                  
                     
		 
		
	 
	
		
		
                  
Préprocesseur 
                  
                  $ gcc -E bonjour.c
                  
		
		
	 
	
		
		
                  
Langage intermédiaire 
                  
                  $ gcc -v bonjour.c # les étapes importantes
                  $ gcc -save-temps -v bonjour.c # les fichiers *.i, *.s
                  $ gcc -fdump-tree-all bonjour.c
                  $ gcc -fdump-rtl-all bonjour.c
                  
		
		
	 
	
		
		
                  Optimisation de code 
                  
                  $ gcc -O2 bonjour.c
                  $ gcc -O3 bonjour.c
                  
                   
		     Remarque:  Autres optimisations: -O1  -O2  -O3  -Os -Ofast -Og
			
                   
		 
		
	 
	
		
		
                  
Génération de code natif 
                  
                  $ gcc -S bonjour.c
                  $ cat bonjour.s
                  
		
		
	 
	
		
		
                  
Optimisation de code 
                  
                  int  main () {
                    int  num  = 2 + 3;
                    return (0);
                  }
                  
                  Compilation (Pas d'optimisations) 
                  
                  $ gcc -O0 -S add.c
                  
                  
                  add.s 
                    main:
                    .LFB0:
                      .cfi_startproc
                      pushq   %rbp
                      .cfi_def_cfa_offset 16
                      .cfi_offset 6, -16
                      movq    %rsp, %rbp
                      .cfi_def_cfa_register 6
                      movl    $5, -4(%rbp)
                      movl    $0, %eax
                      popq    %rbp
                      .cfi_def_cfa 7, 8
                      ret
                      .cfi_endproc
                  
		
		
	 
	
		
		
                  
Optimisation de code 
                  
                  int  main () {
                    int  num  = 2 + 3;
                    return (0);
                  }
                  
                  Compilation (optimisation: 2) 
                  
                  $ gcc -O2 -S add.c
                  
                  
                  add.s 
                    main:
                    .LFB0:
                      .cfi_startproc
                      xorl    %eax, %eax
                      ret
                      .cfi_endproc
                  
		
		
	 
	
		
		
                  
Génération de code 
                  sur une machine d'architecture 64 bits 
                  
                  $ gcc bonjour.c
                  $ file a.out 
                   a.out: ELF 64-bit LSB shared object, x86-64
                  
		
		
	 
	
		
		
                  
Génération de code 
                  sur une machine d'architecture 64 bits 
                  
                  $ gcc -march=i686 -m32 bonjour.c
                  $ gcc -S -march=i686 -m32 bonjour.c
                  $ file ./a.out 
                   ./a.out: ELF 32-bit LSB shared object, Intel 80386
                  
		
		
	 
	
		
		
                
Code objet 
                
                $ gcc -c client.c 
                $ gcc -c color.c 
                $ gcc -o color color.o client.o 
                
		
		
	 
	
		
		
                
Code objet (Modifications et recompilation) 
                
                $ gcc -c client.c 
                $ gcc -c color.c 
                $ gcc -o client client.o color.o 
                $ vim client.c 
                $ gcc -c client.c 
                $ gcc -c client.o color.o 
                $ vim client.c 
                $ gcc -c client.c 
                $ gcc -o client client.o color.o 
                
		
		
	 
	
		
		
                
Makefile 
                
                    CC  ?= gcc
                    
                    CFLAGS  ?= -Wall -Wextra -g
                    
                    COBJS  ?= client.o color.o
                    SOBJS  ?= server.o color.o
                    
                    .SUFFIXES : .c .o
                    
                    SERVER  = server
                    CLIENT  = client
                
		
		
	 
	
		
		
                
Makefile 
                
                    all : $(SERVER) $(CLIENT)
                    
                    $(SERVER ): $(SOBJS)
                        $(CC) -o $(SERVER) $(SOBJS)
                    
                    $(CLIENT ): $(COBJS)
                        $(CC) -o $(CLIENT) $(COBJS)
                    
                    .c.o: 
                        $(CC) -c $*.c
                
		
		
	 
	
		
		
                
Exécution d'un Makefile 
                
                $ vim server.c 
                $ vim client.c 
                $ vim color.c 
                $ make
                $ vim color.c 
                $ make
                
		
		
	 
	
		
		
			Références 
			
			Crédits d'images