Dépendances au système
● 2 types de dépendances:
– valeurs/types (séparateur de fichier / ou \)
– comportements (casse des noms de fichiers)
● pour le 1er type, la gestion par #ifdef suffit
● pour le second, pas toujours
● chaque fois que quelque chose dépend du système, il faut l’expliciter
● exemple: longueur des noms de fichiers
– mauvaise solution: constante arbitraire
– bonne solution: utiliser la constante
FILENAME_MAX (stdio.h) adaptée au système courant
Tailles des types
● anticiper les différences d’architecture
● utiliser les constantes de limits.h
● utiliser sizeof
● exemple non portable:
void** new_ptr_array(int n) { void** ptr=malloc(n*4); if (ptr==NULL) {
/* … */
}
return ptr;
}
sur une machine 64 bits, sizeof(void*) vaut 8
● si on a besoin d’un type avec une taille en octets fixe, utiliser les constantes de stdint.h
● exemple: si on veut gérer Unicode non étendu, on a besoin d’un type non signé sur 2 octets
#include <stdint.h>
typedef uint16_t unichar;
Les sauts de lignes
● Windows: \r\n
● Linux: \n
● MacOS: \r
● il ne suffit pas que le programme soit portable
● est-ce que les données doivent l’être ?
– comment lire/écrire un fichier texte multi-plateforme ?
Endianness
● x86-like: little-endian
● Motorola-like: big-endian
● il ne suffit pas que le programme soit portable
● est-ce que les données doivent l’être ?*
– comment lire/écrire un fichier binaire contenant des int d’une façon multi-plateforme ?
– exemple de solution: encodage utf8
* (toute ressemblance avec un transparent existant serait forfuite et involontaire)
Makefile
● écrire des Makefile portables avec une variable qui dépend du système
● informations concernées:
– compilateur à utiliser
– options de compilation
– répertoires (include, lib, etc)
– commandes d’installation et de nettoyage
– noms des sorties (exemple: .exe ou pas?)
– etc.
● exemple: compilation portable d’une bibliothèque test sur une variable d’environnement pour savoir si on est sous Windows (à vérifier…) définitions dépendant du système
ifeq ($(strip $(PATHEXT)),)
SYSTEM = linux-like
else
SYSTEM = windows
endif
CC = gcc CFLAGS = -fPIC OBJS = utf8.o
ifeq ($(SYSTEM),linux-like)
CLEAN = rm -f
OUTPUT = libutf8.so
else
CLEAN = del
OUTPUT = utf8.dll
endif
instructions pour Linux
instructions pour Windows
all: $(OUTPUT)
%.o: %.c
$(CC) -c $< $(CFLAGS)
ifeq ($(SYSTEM),linux-like)
$(OUTPUT): $(OBJS)
$(CC) -shared $(OBJS) -o $(OUTPUT)
else
$(OUTPUT): $(OBJS)
$(CC) -shared $(OBJS) -Wl,–export-all-symbols -o $(OUTPUT) endif
clean:
$(CLEAN) *.o
$(CLEAN) $(OUTPUT)
Maintenabilité & réutilisabilité ou introduction au génie logiciel
Référence: L’art de la programmation UNIX, Eric S. Raymond, Vuibert
« Pour être un bon développeur en biniou, il suffit d’être bon en algo et de maîtriser la syntaxe de biniou » Proverbe étudiant
« Quand on est con, on est con »
Georges Brassens
Qu’est-ce que le GL ?
● ensemble de bonnes pratiques et de conseils à méditer
● objectifs: développer mieux et plus vite*
– mieux=moins de bugs, code réutilisable, évolutif, etc.
– plus vite=accélérer le débogage, éviter de tout casser tout le temps, etc.
● qu’est-ce qu’un code portable ?
● indépendance vis-à-vis:
– du compilateur
– du système
– de la machine
● pourquoi le faire ?
– force à coder proprement en prenant du recul
– facilite la diffusion des applications