DevDifferent #2 – Struttura del progetto e funzionamento di “make”
Nella prima guida del DevDifferent abbiamo visto cosa ci serve per sviluppare applicazioni direttamente sul nostro iPhone. Non ci siamo soffermati, però, sulla struttura del nostro progetto, e dei vari file che lo compongono. Oggi vedremo proprio questi aspetti, per poi analizzare anche il funzionamento del comando make, che si occupa di compilare la nostra applicazione, leggendo i dati da un file chiamato “Makefile” (che vedremo nel dettaglio).
1. La struttura del nostro progetto
Apriamo la cartella del nostro progetto, vedremo che essa è composta dai seguenti file:
Qual è il loro compito? A cosa servono? Vediamoli nel dettaglio singolarmente:
- build, è la cartella in cui vengono salvati temporaneamente i file creati dal comando make. Ovvero, quando noi eseguiamo “make”, lui compila i nostri file sorgenti, e li trasforma in un’applicazione vera e propria. Questi file vengono momentaneamente salvati in questa cartella, per poi essere trasferiti in /Applications, dove risiedono tutte le applicazioni del nostro iPhone (quasi tutte).
- Classes, questa è la cartella dove risiedono tutti i file sorgenti del progetto. Ovvero sia i file “.h” che “.m” (se non sapete la differenza tranquilli, leggetevi questa mia lezione teorica).
- Resources, nel nostro esempio in questa cartella troveremo due file: “icon.png” e “Default.png”. Cosa sono queste due immagini? Semplice, una è l’icona della nostra applicazione, quella che verrà visualizzata sulla SpringBoard. Se non mettete nessuna icona, avrete una semplice icona bianca. Il file “Default.png”, invece, è quell’immagine che viene mostrata appena si apre l’applicazione, mentre la stessa carica i dati fondamentali per l’esecuzione. In questa cartella Resources potremo, comunque, mettere tutti quei file che serviranno alla nostra applicazione: immagini, suoni, video e tutti quei componenti che possono essere utilizzati in un’applicazione.
- Info.plist, questo è un file molto importante nella struttura della nostra applicazione. È un file xml, che contiene molte informazioni, ad esempio nome, versione dell’applicazione, nome dello sviluppatore e altre ancora. Ci occuperemo in dettaglio di questo file nel punto 2 di questa guida.
- Makefile, questo è il file da cui “make” prende tutte le informazioni relative alla compilazione della nostra applicazione. Nel punto 3 vedremo in dettaglio come è costituito questo file, e come adatatrlo alle nostre esigenze.
2. La struttura di “Info.plist”
Abbiamo accennato in precedenza del file Info.plist. Vediamo ora un esempio di questo file, analizzandone le caratteristiche principali:
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple Computer//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>HelloWorld</string>
<key>CFBundleIdentifier</key>
<string>org.iphone.HelloWorldapp</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>HelloWorld</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>SignerIdentity</key>
<string>Apple iPhone OS Application Signing</string>
</dict>
Possiamo osservare come questo file sia strutturato tramite XML, e contenga dei dettagli sulla nostra applicazione. Vediamo di spiegare alcuni di questi campi, che potete (e dovete) variare quando create una nuova applicazione:
- CFBundleDevelopmentRegion, è una stringa che identifica la lingua dell’applicazione. La chiave da usare sarà una coppia di lettere: ad esempio, en per l’inglese, it per l’italiano e così dicendo.
- CFBundleExecutable, questo è il campo che identifica l’eseguibile da lanciare. Fate ben attenzione di assegnare l’eseguibile corretto. Se la vostra applicazione crasha all’avvio è probabile che abbiate fatto un errore in questo campo.
- CFBundleIdentifier, identifica lo sviluppatore dell’applicazione, tramite una stringa come quella che vedete nell’esempio (org.iphone.HelloWorld), ovvero dominio.sviluppatore.applicazione. È comunque un campo che non ha grande importanza, quindi potete modificarlo a vostro piacimento (sempre rispettando la struttura).
- CFBundleName, è il nome della vostra applicazione che compare sulla SpringBoard. Quindi potremmo avere il progetto che si chiama HelloWorld, ma far apparire sul desktop dell’iPhone la scritta “CiaoMondo”.
- CFBundleVersion, questo campo, invece, identifica la versione dell’applicazione.
Queste sono le stringhe principali, che potete (sempre con attenzione) modificare nel file Info.plist, tramite un qualsiasi programma di editor di testi (Blocco Note, Notepad++).
3. Struttura del Makefile
Vi ho accennato in precedenza al Makefile. Questo è un file da cui il comando make legge i parametri in esso contenuti.Vi chiederete, ma che parametri possiamo ancora impostare? Ve ne cito alcuni io: il nome del progetti, i framework da includere. E vi ricordate l’istruzione “make install”? Beh, si può personalizzare anche quella, facendogli fare delle specifiche operazioni.
Vediamo, quindi, le varie parti che compongono il Makefile.
# Nome del progetto
PROJECTNAME=HelloWorld
# Valori da non modificare
APPFOLDER=$(PROJECTNAME).app
INSTALLFOLDER=$(PROJECTNAME).app
La prima istruzione non fa altro che settare il nome del progetto, varabile che servirà sia nelle successive due istruzioni, che in tutto il resto del Makefile. Le due istruzioni successive, come c’è scritto nel commento, non sono da modificare, devono sempre restare così.
# il compilatore responsabile della compilazione da non modificare
CC=arm-apple-darwin9-gcc
LD=$(CC)
# le librerire native del sistema che devono essere linkate all’interno dell’applicativo
# non sono tutte necessarie, quelle non indispensabili possono essere commentate o tolte
LDFLAGS = -arch arm -lobjc
LDFLAGS += -framework CoreFoundation
LDFLAGS += -framework Foundation
LDFLAGS += -framework UIKit
LDFLAGS += -framework QuartzCore
LDFLAGS += -framework CoreGraphics
LDFLAGS += -framework GraphicsServices
LDFLAGS += -framework CoreSurface
//LDFLAGS += -framework CoreAudio
//LDFLAGS += -framework Celestial
//LDFLAGS += -framework AudioToolbox
//LDFLAGS += -framework WebCore
//LDFLAGS += -framework WebKit
LDFLAGS += -L”/usr/lib”
LDFLAGS += -F”/System/Library/Frameworks”
LDFLAGS += -F”/System/Library/PrivateFrameworks”
LDFLAGS += -bind_at_load
LDFLAGS += -multiply_defined suppress
CFLAGS = -I”/var/include”
CFLAGS += -I”/usr/include”
CFLAGS += -F”/System/Library/Frameworks”
CFLAGS += -F”/System/Library/PrivateFrameworks”
#CFLAGS += -DDEBUG -O3 -Wall -std=c99 -funroll-loops
CFLAGS += -DDEBUG -Wall -std=c99
CFLAGS += -DMAC_OS_X_VERSION_MAX_ALLOWED=1050
BUILDDIR=./build/2.0
SRCDIR=./Classes
RESDIR=./Resources
OBJS=$(patsubst %.m,%.o,$(wildcard $(SRCDIR)/*.m))
OBJS+=$(patsubst %.c,%.o,$(wildcard $(SRCDIR)/*.c))
OBJS+=$(patsubst %.cpp,%.o,$(wildcard $(SRCDIR)/*.cpp))
RESOURCES=$(wildcard $(RESDIR)/*)
all: dist
$(PROJECTNAME): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $^
%.o: %.m
$(CC) -c $(CFLAGS) $< -o $@
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
%.o: %.cpp
$(CC) -c $(CPPFLAGS) $< -o $@
La prima parte di questo lungo set di istruzioni riguarda tutti quei framework che devono essere inclusi nel progetto. Se sapete su quali intervenire potete eliminare quelli che non usate, altrimenti lasciate tutto come è. Dovete ricordarvi, però, di aggiungerne se utilizzare funzioni particolari (come abbiamo fatto nel nostro tutorial in cui accedevamo all’applicazione Contatti).
Potete notare che nella seconda parte vengono settate le cartelle “Classes” e “Resources”, che abbiamo descritto in precedenza.
Guardiamo ora del codice sicuramente più interessante:
# Questi sono eventuali comandi che possono essere eseguiti con il comando make
dist: $(PROJECTNAME)
/bin/rm -rf $(BUILDDIR)
/bin/mkdir -p $(BUILDDIR)/$(APPFOLDER)
/bin/cp $(RESDIR)/* $(BUILDDIR)/$(APPFOLDER)
/bin/cp Info.plist $(BUILDDIR)/$(APPFOLDER)/Info.plist
@echo “APPL????” > $(BUILDDIR)/$(APPFOLDER)/PkgInfo
/usr/bin/ldid -S $(PROJECTNAME)
/bin/cp $(PROJECTNAME) $(BUILDDIR)/$(APPFOLDER)
#installa l’applicazione ed esegue il respring
install: dist
/bin/cp -r $(BUILDDIR)/$(APPFOLDER) /Applications/$(INSTALLFOLDER)
@echo “Application $(INSTALLFOLDER) installed”
killall SpringBoard
#rimuove completamente l’applicazione ed esegue il respring
uninstall:
/bin/rm -fr /Applications/$(INSTALLFOLDER)
killall SpringBoard
#reinstalla l’applicazione, ma non esegue il respring
reinstall: dist
/bin/rm -fr /Applications/$(INSTALLFOLDER)
/bin/cp -r $(BUILDDIR)/$(APPFOLDER) /Applications/$(INSTALLFOLDER)
@echo “Application $(INSTALLFOLDER) installed”
#pulisce ogni traccia della nostra applicazione
clean:
@rm -f $(SRCDIR)/*.o
@rm -rf $(BUILDDIR)
@rm -f $(PROJECTNAME)
Questa è sicuramente la parte più interessante del file Makeinstall. Qui possiamo modificare le varie operazioni che vengono compiute dal comando make. Ovvero, vi ricordate quando digitavamo “make install”? Se guardate il codice potete osservare quali siano le operazioni che vengono compiute quando sesegue il comando “make install”. Quindi, gli utenti più smaliziati (e quelli con il firmware 2.1 in particolar modo) diranno: non possiamo includere qui il respring di BossPrefs, in modo da risparmiare un comando? Ma certo! Basta modificare il file nel seguente modo:
install: dist
/bin/cp -r $(BUILDDIR)/$(APPFOLDER) /Applications/$(INSTALLFOLDER)
@echo “Application $(INSTALLFOLDER) installed”
/Applications/BossPrefs.app/Respring
Un altro esempio? Personalizziamo la disinstallazione della nostra applicazione:
uninstall:
/bin/rm -fr /Applications/$(INSTALLFOLDER)
@echo “L’applicazione stupenda $(INSTALLFOLDER) è stata disinstallata.. Ripensaci!”
killall SpringBoard
Quindi potete personalizzare in qualsiasi modo questi comandi, adattandoli alle vostre esigenze.
Concludiamo qui questa seconda guida del DevDifferent.
Nella prossima verranno discussi altri aspetti, analizzando il codice veroe e proprio dell’applicazione e altri aspetti fondamentali.
La guida è stata interamente realizzata da Andrea Busi per “The Bubi Devs”.
Ringraziamenti ad Osvaldo per il grande aiuto e per la bozza, mentre l’applicazione originale HelloWorld è opera di “Antirez weblog“.














