• Non ci sono risultati.

Laboratorio di Sistemi Operativi Tool per la programmazione

N/A
N/A
Protected

Academic year: 2021

Condividi "Laboratorio di Sistemi Operativi Tool per la programmazione"

Copied!
52
0
0

Testo completo

(1)

Laboratorio di Sistemi Operativi Tool per la programmazione

Alberto Montresor Renzo Davoli

Copyright © 2004-2005 Alberto Montresor, Renzo Davoli

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found at:

http://www.gnu.org/licenses/fdl.html#TOC1

(2)

Sommario

Come gestire progetti di programmazione molto grandi

• Come organizzarli

• Come compilarli

• Come lavorare in cooperazione

Nota:

• Con un'enfasi sul C, ma i concetti valgono anche per altri linguaggi di

programmazione

(3)

Come organizzare un progetto

Ovviamente:

• Programmi di grandi dimensioni non possono essere contenuti in un file singolo

Nel C

• vi sono tecniche per semplificare gestione di file multipli

• non sono "enforced": sono lasciate al programmatore

Un programma grande è diviso in moduli:

• i file .h contengono le funzioni prototipo del modulo ed eventuali costanti

• i file .c contengono le definizioni di funzioni del modulo

• i moduli sono compilati separatamente

• viene generato un eseguibile tramite linking dei moduli

(4)

Esempio: sample.c

#include <stdio.h>

#include "my_math.h"

int main() {

int a, b, c;

puts("Input three numbers:");

scanf("%d %d %d", &a, &b, &c);

printf("The average of %d %d %d is %f.\n", a,b,c,average(a,b,c));

return 0;

}

(5)

Esempio - Modulo my_math

/* my_math.h */

#define PI 3.1415926 float average(int x,

int y, int z);

float sum(int x, int y, int z);

/* my_math.c */

#include "my_math.h"

float average(int x, int y, int z)

{

return sum(x,y,z)/3;

}

float sum(int x, int y, int z) {

return x+y+z;

}

(6)

Compilare questo semplice programma

Per generare my_math.o

• Abbiamo bisogno di my_math.c e my_math.h

gcc –c my_math.c

Per generare sample.o

• Abbiamo bisogno di sample.c e my_math.h

gcc –c sample.c

Per generare l'eseguibile

• Abbiamo bisogno di my_math.o e sample.o

gcc –o sample sample.o my_math.o

(7)

Come utilizzare make

I programmi che consistono di molti moduli sono impossibili da mantenere manualmente

Si crea un Makefile

# Makefile for the sample sample: sample.o my_math.o

cc –o sample sample.o my_math.o sample.o: sample.c my_math.h

cc –c sample.c

my_math.o: my_math.c my_math.h cc –c my_math.c

clean:

rm sample *.o core Target

Target Dipendenze

Comandi Indentazioni

con tab, non spazi

(8)

Makefile

Un makefile consiste in un insieme di regole del tipo:

target ... : prerequisites ...

command ...

...

Target:

• il nome di un file da generare

• un'azione da svolgere

Prerequisiti:

• uno o più file utilizzati come input per creare il file target

Regole

• una o più azioni da eseguire

Nota:

• la prima regola è quella di

"default", o radice

(9)

Come utilizzare make

Come?

• Si salva il file con il nome Makefile o makefile nella stessa directory contenente i file

• Si lancia l'utility make

Make

• trova il Makefile

• verifica le regole e le dipendenze e rigenera i file per cui è necessario un update

Esempio:

• Se solo sample.c è stato modificato:

cc –c sample.c

cc –o sample sample.o my_math.o

(10)

Come utilizzare make

Per rimuovere tutti i file generati

make clean

Per ricompilare, è possibile:

• Rimuovere tutti i file generati e ricompilare

make clean ; make

• Oppure è possibile cambiare la data di ultima modifica:

touch my_math.h ; make

• La data di ultima modifica di my_math.h prende l'ora corrente

• Nota: questo perchè tutti i file dipendono da my_math.h

(11)

Utilizzare make con directory multiple

Con l'aumentare del numero di file .c

• diventa difficile controllare tutto con un unico makefile

• conviene utilizzare più makefile, uno per modulo

Un programma viene organizzato in questo modo:

• una directory per modulo

• file header:

• una directory per tutti i file .h

• oppure: file .h di un modulo nel modulo stesso

• Makefile nella directory radice per la creazione dell'eseguibile/libreria

• Makefile in ogni modulo dirigono la creazione dei file .o

(12)

Un esempio di Makefile

Si consideri un programma C composto da

• una struttura dati a coda queue

queue_types.h, queue_interface.h, queue.c

• una struttura dati a stack stack

stack_types.h, stack_interface.h, stack.c

• un modulo principale

main.c

Organizzazione

• Tre sottodirectory:

stack, queue, include

• Tutti i file .h in include

stack queue include

main.c

Makefile Makefile

s_t.h stack.c Makefile

stack.c

(13)

Un esempio di Makefile

 stack contiene stack.c e il seguente Makefile :

all: stack.o

stack.o: stack.c \

../include/stack_types.h \ ../include/stack_interface.h gcc -I../include -c stack.c

clean:

rm -f *.o

Note: opzione -I di gcc

• Specifica uno o più path in cui cercare per trovare file .h

• Path multipli separati da virgole ","

(14)

Un esempio di Makefile

 queue contiene queue.c e il seguente Makefile :

all: queue.o

queue.o: queue.c \

../include/queue_types.h \ ../include/queue_interface.h gcc -I../include -c queue.c

clean:

rm -f *.o

(15)

Un esempio di Makefile

 main contiene main.c e il seguente Makefile :

all: main.o stackdir queuedir

gcc -o main main.o ../stack/stack.o \ ../queue/queue.o

main.o: main.c include/*.h gcc -Iinclude -c main.c

stackdir:

cd stack ; make all

queuedir:

cd queue ; make all

(16)

Un esempio di Makefile

clean:

rm -f *.o main core cleanall:

rm -f *.o main core cd stack ; make clean cd queue ; make clean

Nota:

• Ogni riga di comando viene eseguita tramite una subshell

• Come viene gestita la directory corrente

• Cosa succede se una directory manca?

(17)

Utilizzazione delle macro nei makefile

Macro nei Makefile

• Utilizzate per semplificare la modifica dei Makefile

• Utilizzate per ridurre la dimensione dei file semplificando espressioni ripetute

Sintassi

• Definizione: name = value

• Riferimenti: $(name) o ${name}

(18)

Un esempio di Makefile, rivisitato

Makefile in stack:

CC = gcc

HDIR = ../include INCPATH = -I$(HDIR)

DEPH = $(HDIR)/stack_types.h \ $(HDIR)/stack_interface.h SOURCE = stack.c

OBJECTS = stack.o all: $(OBJECTS)

stack.o: $(SOURCE) $(DEPH)

$(CC) $(INCPATH) -c $(SOURCE) clean:

rm -f *.o

(19)

Un esempio di Makefile, rivisitato

Makefile in queue

CC = gcc

HDIR = ../include INCPATH = -I$(HDIR)

DEPH = $(HDIR)/queuetypes.h \ $(HDIR)/queueinterface.h SOURCE = queue.c

OBJECTS = queue.o all: $(OBJECTS)

queue.o: $(SOURCE) $(DEPH)

$(CC) $(INCPATH) -c $(SOURCE) clean:

rm -f *.o

(20)

Un esempio di Makefile, rivisitato

Makefile per main

CC = gcc

HDIR = include INCPATH = -I$(HDIR)

DEPH = $(HDIR)/queue_types.h \

$(HDIR)/queue_interface.h \ $(HDIR)/stack_types.h \

$(HDIR)/stack_interface.h OBJECTS = stack/stack.o queue/queue.o all: main

main: main.o stackdir queuedir

$(CC) -o main main.o $(OBJECTS)

(21)

Un esempio di makefile, rivisitato

main.o: main.c $(HDIR)/*.h

$(CC) $(INCPATH) -c main.c stackdir:

cd stack && make all queuedir:

cd queue && make all clean:

rm -f *.o main core cleanall:

-rm -f *.o main core cd stack && make clean cd queue && make clean

Ignora eventuali errori

Solo in caso di successo con cd

(22)

Makefile "avanzati"

Le funzionalità di make non si esauriscono qui

• Strutture di controllo come statement condizionali e loop

• Regole implicite che agiscono come default quando non sono presenti regole esplicite

• Semplici funzioni di supporto per trasformare testo

• Variabili automatiche che si riferiscono a vari elementi di un Makefile, come target e dipendenze.

Per ulteriori dettagli:

• http://www.gnu.org/manual/make/html_mono/make.html

(23)

Esempi

Dipendenze automatiche

• make è in grado di inferire alcune dipendenze e regole

OBJECTS = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(OBJECTS)

cc -o edit $(objects) main.o : defs.h

kbd.o : defs.h command.h

command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h

files.o : defs.h buffer.h command.h utils.o : defs.h

main.o : defs.h main.c gcc -c main.c

(24)

Esempi

Uno stile alternativo

• è possibile "raggruppare" le dipendenze

OBJECTS = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(OBJECTS)

cc -o edit $(OBJECTS)

$(OBJECTS) : defs.h

kbd.o command.o files.o : command.h

display.o insert.o search.o files.o : buffer.h

(25)

Esempi

Regole "statiche"

• Specificano il comportamento per una classe di file

• gnuplot: input

set{eps|gpt}.gpt *.plt

, output

output.{eps|gpt}

.PHONY: all eps png all: eps png

eps: quota.eps transfer.eps single.eps png: quota.png transfer.png single.png

%.eps : %.plt seteps.gpt

gnuplot seteps.gpt $< ; mv output.eps $@

%.png : %.plt seteps.gpt

gnuplot setpng.gpt $< ; mv output.png $@

clean:

rm -f *.eps *.png Identifica il target

Identifica il prerequisito Afferma che sono solo azioni

(26)

Portabilità

E' sempre un problema!

• Diversi tipi di: processori / compilatori / librerie / s.o.

• Diverse versioni di: compilatori / librerie / s.o.

Makefile per la portabilità:

• scrivere un makefile è facile

• come abbiamo visto...

scrivere un buon makefile è difficile

• maintanance target (install, dist, distclean, ...)

• opzioni utente

• gestione delle dipendenze !!!!!

scrivere un makefile portatile è molto difficile

(27)

Auto-tools

GNU project "auto-tools"

• automake - generazione automatica makefile

• autoheader - generazione config headers; per portabilità

• autoconf - genera configure script

• libtool - gestione librerie statiche/dinamiche

Makefile.am Configure.in

autoconf

automake Makefile.in

configure config.h Makefile

(28)

Esempio di autoconf

programmer@c:~/project> ls -1 my_math.c

my_math.h sample.c

programmer@c:~/project>:~/tmp> autoscan programmer@c:~/project>:~/tmp> ls -1

autoscan.log configure.scan my_math.c

my_math.h sample.c

Autoscan crea il file configure.scan, che ci servirà come template per creare il file configure.in

Project autoscan configure.scan

(29)

Esempio di autoconf

programmer@c:~/project> cat configure.scan

# -*- Autoconf -*-

# Process this file with autoconf for a configure script.

AC_PREREQ(2.57)

AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) AC_CONFIG_SRCDIR([my_math.c])

AC_CONFIG_HEADER([config.h])

# Checks for programs.

AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT

(30)

Esempio di autoconf

programmer@c:~/project> cat configure.in

# -*- Autoconf -*-

# Process this file with autoconf for a configure script.

AC_PREREQ(2.57)

AC_INIT(sample, [1.00], [programmer@c.com]) AC_CONFIG_SRCDIR([my_math.h])

#AC_CONFIG_HEADER([config.h])

# Checks for programs.

AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

Questa riga è commentata, perchè non abbiamo bisogno di un file

config.h (per gestire portabilità)

(31)

Esempio di autoconf

programmer@c:~/project> automake -a

configure.in: `AM_INIT_AUTOMAKE' must be used

automake: no implementation of AM_INIT_AUTOMAKE was found, automake: probably because aclocal.m4 is missing...

automake: You should run aclocal to create this file, then automake: run automake again.

automake: no `Makefile.am' found or specified -a aggiunge alcuni file standard al

progetto; altrimenti li richiede

automake autoscan.in

Makefile.am Makefile.in

(32)

Esempio di autoconf

programmer@c:~/project> cat configure.in

# -*- Autoconf -*-

# Process this file with autoconf for a configure script.

AC_PREREQ(2.57)

AC_INIT(sample, [1.00], [programmer@c.com]) AC_CONFIG_SRCDIR([my_math.h])

AM_INIT_AUTOMAKE

# Checks for programs.

AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

(33)

Esempio di autoconf

programmer@c:~/project> cat Makefile.am noinst_PROGRAMS=sample

sample_SOURCES=sample.c my_math.c

#Ulteriori esempi, commentati:

#bin_PROGRAMS=sample

#include_HEADERS=my_math.h

#lib_LIBRARIES=mymath.a

#mymath_a_SOURCE=my_math.c

Struttura generale: where_WHAT where - dove mettere i file generati WHAT - quale file considerare

(34)

Esempio di autoconf

programmer@c:~/project> aclocal

programmer@c:~/project> automake -a automake

Makefile.am: required file `./NEWS' not found Makefile.am: required file `./README' not found Makefile.am: required file `./AUTHORS' not found Makefile.am: required file `./ChangeLog' not found programmer@c:~/project> touch \

README NEWS AUTHORS ChangeLog programmer@c:~/project> automake -a programmer@c:~/project> autoconf

autoconf autoscan.in

configure

(35)

Esempio di autoconf

programmer@c:~/project> ./configure

checking for a BSD-compatible install.. /usr/bin/install -c checking whether build environment is sane... yes

checking for gawk... gawk

checking whether make sets $(MAKE)... yes checking for gcc... gcc

checking for C compiler default output... a.out checking whether the C compiler works... yes

checking whether we are cross compiling... no checking for suffix of executables...

checking for suffix of object files... o

checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes

checking for gcc option to accept ANSI C... none needed checking for style of include used by make... GNU

checking dependency style of gcc... gcc configure: creating ./config.status

config.status: creating Makefile

config.status: executing depfiles commands

(36)

Autoconf

Note finali

• Con questo esempio abbiamo solo "scalfito" le potenzialità di auto*

• Maggiori informazioni presso:

• google://automake

• google://autoheader

• google://autoconf

• google://libtool

(37)

CVS - Concurrent Versioning System

Perchè utilizzare CVS?

• tenere traccia delle differenti versioni dei vostri file

• mantenere le vecchie versioni

• lavorare sugli stessi file da postazioni diverse

• lavorare sugli stessi file in cooperazione con altre persone

Per chi è indicato?

• Programmatori, scrittori (per chi usa latex)

Open-source

• http://www.cvshome.org/.

(38)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 1

Working dir 2

(39)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 2 /home/pippo/proj1

/home/pippo/proj1/a.c /home/pippo/proj1/b.c

Working dir 2 checkout

(40)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 1 /home/pippo/proj1

/home/pippo/proj1/a.c /home/pippo/proj1/b.c

/home/pippo/prog2

/home/pippo/prog2/a.tex

Working dir 2 checkout

(41)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 1 /home/pippo/proj1

/home/pippo/proj1/a.c /home/pippo/proj1/b.c

/home/pippo/prog2

/home/pippo/prog2/a.tex

Working dir 2 /home/pluto/proj1

/home/pluto/proj1/a.c /home/pluto/proj1/b.c checkout

(42)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 1 /home/pippo/proj1

/home/pippo/proj1/a.c /home/pippo/proj1/b.c /home/pippo/prog2

/home/pippo/prog2/a.tex

Working dir 2 /home/pluto/proj1

/home/pluto/proj1/a.c Modificato

(43)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 1 /home/pippo/proj1

/home/pippo/proj1/a.c /home/pippo/proj1/b.c

/home/pippo/prog2

/home/pippo/prog2/a.tex

Working dir 2 /home/pluto/proj1

/home/pluto/proj1/a.c /home/pluto/proj1/b.c commit

(44)

CVS

Repository /home/cvs

/home/cvs/proj1

/home/cvs/proj1/a.c,v /home/cvs/proj1/b.c,v

/home/cvs/proj2

/home/cvs/proj2/a.tex,v

Working dir 1 /home/pippo/proj1

/home/pippo/proj1/a.c /home/pippo/proj1/b.c

/home/pippo/prog2

/home/pippo/prog2/a.tex

Working dir 2 /home/pluto/proj1

/home/pluto/proj1/a.c update

(45)

CVS

Come funziona CVS?

• Orientato ai file / orientato alla linea

• Nessun vero e proprio concetto di "progetto"

• Lavoro soprattutto con file testuali; può gestire file binari

(46)

CVS

Come indicare dove si trova un repository?

• Local path

• External :ext:user@host:path

• Password server :pserver:user@host:path

Da linea di comando:

cvs -d /home/cvs checkout proj

cvs -d :pserver:pippo@cvs.c.com:/home/cvs login Password: xxxxxxx

cvs checkout

Tramite configurazione, una volta:

export CVSROOT=cvs.c.com:/home/cvs

(47)

CVS - Importare un progetto

pippo@c:~> cd temp pippo@c:~/temp> ls

my_math.c my_math.h sample.c

pippo@c:~/project> cvs -d /home/cvs import \ -m "First release" sample pippo start

N sample/sample.c N sample/my_math.c N sample/my_math.h

No conflicts generated by this import pippo@c:~/project>

(48)

CVS - Importare un progetto

pippo@c:~> cvs -d /home/cvs checkout sample cvs checkout: Updating sample

U sample/my_math.c U sample/my_math.h U sample/sample.c

pippo@c:~/> ls sample

CVS/ my_math.c my_math.h sample.c pippo@c:~/> ls sample/CVS/

Entries Repository Root

pippo@c:~/> cat sample/CVS/Root /home/cvs

Da qui in poi, non è più

(49)

CVS - Modificare un progetto

pippo@c:~/sample> cp sample.c sample2.c pippo@c:~/sample> vi sample.c

pippo@c:~/sample> cvs add sample2.c cvs add: scheduling file

`sample2.c' for addition

cvs add: use 'cvs commit' to add this file permanently

#include <stdio.h>

#include "my_math.h"

int main() {

int a, b, c;

puts("Inserisci tre numeri:");

scanf("%d %d %d", &a, &b, &c);

printf("The average of %d %d %d is %f\n", a,b,c,average(a,b,c));

}

/* Commento finale */

(50)

CVS - Modificare un progetto

pippo@c:~/sample> cvs commit -m "Added file"

cvs commit: Examining . Checking in sample.c;

/home/montreso/cvs/sample/sample.c,v <-- sample.c new revision: 1.2; previous revision: 1.1

done

RCS file: /home/montreso/cvs/sample/sample2.c,v done

Checking in sample2.c;

/home/montreso/cvs/sample/sample2.c,v <-- sample2.c initial revision: 1.1

done

(51)

CVS - Varie ed eventuali

pippo@c:~/sample> cvs update cvs update: Updating .

Vedere le differenze:

pippo@c:~/sample> cvs diff -r1.1 sample.c Index: sample.c

RCS file: /home/montreso/cvs/sample/sample.c,v retrieving revision 1.1

retrieving revision 1.2 diff -r1.1 -r1.2

6c6

< puts("Input three numbers:");

---

> puts("Inserisci tre numeri:");

10d9

< return 0;

11a11

> /* Commento finale */

(52)

Conclusioni

Si può fare di più....

• Gestione delle versioni

• Gestione dei conflitti

• Fork di progetti

• Gestione sicura dei repository

• Etc. Etc.

Per ulteriori informazioni:

• google://cvs book

Riferimenti

Documenti correlati

 Per leggere dati da un file presente sul disco, Per leggere dati da un file presente sul disco, occorre dapprima costruire un oggetto di tipo occorre dapprima costruire un

• Il grafo delle dipendenze viene codificato in un file di testo chiamato Makefile che risiede nella stessa directory dei file sorgente.. • Esempio

Nella directory Main scrivere un file main.c che prende un argomento intero a riga di comando, calcola calcolaB di quel numero e usa il risultato come argomento

Per ciascun target elencato come dipendenze di .phony il make non cerca l'esistenza di un file e non cerca di applicare al target le regole implicite (non trattate qui). Dentro

 file e directory.. © 2002-2005 Renzo Davoli, Alberto Montresor

Data Set Authors: Daniele De Gregorio (Eyecan.ai Srl), Riccardo Zanella (University of Bologna), Gianluca Palli (University of Bologna), Luigi Di Stefano (University of

This view has been developed within the classic welfare economics perspective in which the public-good characteristics of knowledge lead to under-investment in the private

  Si noti che per ogni target di tipo .o file le dipendenze sono quasi sempre i corrispondente file .cc e .hh e gli altri file .hh (dell’utente) che sono inclusi