Arborescence du projet
Pour plus de clarté, l'arborescence du projet évolue :
idreammicro |_build_system | |_env_avr.py | |_env_arduino_mega2560.py | |_env_arduino_uno.py |_libraries | |_digital_io |_helloworld.c |_SConscript |_SConstruct
- Le dossier build_system accueille les fichiers permettant de configurer l'environnement de construction, à savoir les fichiers env_avr.py, env_arduino_mega2560.py et env_arduino_uno.py.
- Le dossier libraries contient les bibliothèques, chacune disposant de son propre sous-dossier. Par exemple la bibliothèque digital_io se trouve dans le dossier libraries/digital_io.
[Télécharger l'archive complète]
Construction de la bibliothèque
L'arborescence d'une bibliothèque a déjà fait l'objet d'une présentation dans un précédent article. On se contentera d'un simple rappel tout en l'adaptant à la bibliothèque digital_io.
digital_io |_demo | |_demo_digital_io.c | |_SConscript |_include |_src | |_digital_io.c | |_SConscript |_test | |_test_digital_io.c | |_SConscript |_digital_io.h |_SConscript |_SConstruct
L'objectif de cet article est de présenter la construction d'une bibliothèque, et non la bibliothèque en elle même. Par conséquent, la bibliothèque digital_io fait l'objet d'un autre article.
Compilation de la bibliothèque
Le fichier digital_io/SConscript ne fait qu'appeler le script de construction de la bibliothèque. Son unique rôle est de masquer la complexité de la construction de la bibliothèque aux projets qui l'utilisent.
# Import environment set for target. Import('env_target', 'env_name', 'DEVICE') # Define directories to process. directories = [ 'src/' ] # Process directories. for directory in directories: SConscript( directory + 'SConscript', variant_dir = '#build/' + env_name + '/libraries/digital_io/' + directory, exports = { 'env_target' : env_target, 'env_name' : env_name }, duplicate = 0 )
Le fichier digital_io/src/SConscript est le script le plus important : son rôle est de compiler la bibliothèque et de la rendre accessible. La construction d'une bibliothèque est très semblable à celle d'un programme. Les points remarquables sont les suivants :
- ligne 13 : construction d'une bibliothèque statique ;
- ligne 16 : ajout du chemin du dossier contenant la bibliothèque à la variable LIBPATH indiquant les dossiers de recherche des bibliothèques ;
- ligne 17 : ajout de la bibliothèque à la variable LIBS indiquant les noms des bibliothèques avec lesquelles linker.
# Import environment set for target. Import('env_target', 'env_name', 'DEVICE') # Define target name. TARGET = 'digital_io' # Define source files. sources = [ 'digital_io.c' ] # Build static library. env_target.StaticLibrary(target = TARGET, source = sources) # Append LIBPATH and LIBS. env_target.Append(LIBPATH = [ '#build/' + env_name + '/libraries/' + TARGET + '/src']) env_target.Append(LIBS = [ TARGET ])
Logiciel de démonstration
Le fichier digital_io/demo/SConscript est le script de construction du logiciel de démonstration de la bibliothèque.
# Import environment set for target. Import('env_target', 'env_name', 'DEVICE') # Set target name. TARGET = 'demo_digital_io' # Set source file. sources = [ 'demo_digital_io.c' ] # Build program. env_target.Program(target = TARGET + '.elf', source = sources) # Create hex binary file. env_target.Command( TARGET + '.hex', TARGET + '.elf', env_target['OBJCOPY'] + ' -O ihex $SOURCE $TARGET' ) # Compute memory usage. env_target.Command( None, TARGET + '.elf', env_target['SIZE'] + ' -C --mcu=' + DEVICE + ' $SOURCE' )
Logiciel de test
Le fichier digital_io/test/SConscript est le script de construction du logiciel de test de la bibliothèque.
# Import environment set for target. Import('env_target', 'env_name', 'DEVICE') # Set target name. TARGET = 'test_digital_io' # Set source file. sources = [ 'test_digital_io.c' ] # Build program. env_target.Program(target = TARGET + '.elf', source = sources) # Create hex binary file. env_target.Command( TARGET + '.hex', TARGET + '.elf', env_target['OBJCOPY'] + ' -O ihex $SOURCE $TARGET' ) # Compute memory usage. env_target.Command( None, TARGET + '.elf', env_target['SIZE'] + ' -C --mcu=' + DEVICE + ' $SOURCE' )
Démonstration et test
Le fichier digital_io/SConstruct propose un environnement de construction minimal permettant de construire la bibliothèque ainsi que les projets de démonstration et de test.
# Create and initialize the environment. env = Environment() # Set environment for AVR-GCC. env['CC'] = 'avr-gcc' env['CPPPATH'] = '/usr/lib/avr/include' env['OBJCOPY'] = 'avr-objcopy' env['SIZE'] = 'avr-size' env['AR'] = 'avr-ar' env['RANLIB'] = 'avr-ranlib' env.Append(CCFLAGS = '-Os') # Declare some variables about microcontroller. # Microcontroller type. DEVICE = 'atmega328p' # Microcontroller frequency. CPU_FREQUENCY = '16000000UL' # Hz # Set environment for an Atmel AVR ATmega328p microcontroller. env.Append(CCFLAGS = '-mmcu=' + DEVICE) env.Append(LINKFLAGS = '-mmcu=' + DEVICE) env.Append(CPPDEFINES = 'F_CPU=' + CPU_FREQUENCY) env.Append(CPPPATH = [ '#../' ]) # Build library. SConscript( 'src/SConscript', variant_dir = '#build/lib/', exports = { 'env_target' : env, 'env_name' : 'env_arduino_uno', 'DEVICE' : DEVICE }, duplicate = 0 ) # Append LIBPATH and LIBS. env.Append(LIBPATH = [ '#build/lib/']) env.Append(LIBS = [ 'digital_io' ]) # Build demonstration program. SConscript( 'demo/SConscript', variant_dir = '#build/demo/', exports = { 'env_target' : env, 'env_name' : 'env_arduino_uno', 'DEVICE' : DEVICE }, duplicate = 0 ) # Build test program. SConscript( 'test/SConscript', variant_dir = '#build/test/', exports = { 'env_target' : env, 'env_name' : 'env_arduino_uno', 'DEVICE' : DEVICE }, duplicate = 0 )
Construction du projet
Fichier source
Le fichier source helloworld.c inclut et utilise la bibliothèque digital_io pour faire basculer le niveau de la sortie PB5 (port B, broche 5).
/**************************************************************************//** * \file helloworld.c ******************************************************************************/ /****************************************************************************** * Header file inclusions. ******************************************************************************/ #include <digital_io/digital_io.h> #include <avr/io.h> #include <util/delay.h> /****************************************************************************** * Main function. ******************************************************************************/ /**************************************************************************//** * \fn int main(void) * * \brief Main function. ******************************************************************************/ int main ( void ){ // Declare pin. digital_io__pin_position_t pin = DIGITAL_IO__PORT_B | DIGITAL_IO__PIN_5; // Configure pin as output. digital_io__configure_pin(pin, DIGITAL_IO__DIRECTION__OUTPUT); while (1) { // Set pin level. digital_io__set_pin_level(pin, DIGITAL_IO__LEVEL__HIGH); _delay_ms(1000); // Reset pin level. digital_io__set_pin_level(pin, DIGITAL_IO__LEVEL__LOW); _delay_ms(1000); } return 0; }
Fichier SConscript
Désormais le projet utilise une bibliothèque. Il est donc nécessaire de modifier le fichier SConscript afin de la construire :
- les lignes 7 à 10 indiquent la liste des bibliothèques utilisées ;
- les lignes 12 à 18 ordonnent leur construction.
On remarquera que seules les bibliothèques utilisées par le projet seront compilées. Contrairement à d'autres systèmes de construction tel qu'Arduino qui compilent toutes les bibliothèques avant de compiler le projet.
# Import environment set for target. Import('env_target', 'env_name', 'DEVICE') # Set target name. TARGET = 'helloworld' # Set libraries to use. libraries = [ 'digital_io' ] # Build libraries. for library in libraries: SConscript( '#libraries/' + library + '/SConscript', exports = { 'env_target' : env_target, 'env_name' : env_name }, duplicate = 0 ) # Set source file. sources = 'helloworld.c' # Build program. env_target.Program(target = TARGET + '.elf', source = sources) # Create hex binary file. env_target.Command( TARGET + '.hex', TARGET + '.elf', env_target['OBJCOPY'] + ' -O ihex $SOURCE $TARGET' ) # Compute memory usage. env_target.Command( None, TARGET + '.elf', env_target['SIZE'] + ' -C --mcu=' + DEVICE + ' $SOURCE' )
Fichier SConstruct
Le fichier SConstruct situé à la racine du dossier régit la construction de tout l'environnement, c'est à dire des projets et des bibliothèques utilisées.
Par rapport au fichier SConstruct d'une bibliothèque, celui-ci ne diffère que par la ligne 8. Elle permet d'ajouter le chemin du dossier contenant les bibliothèques à la variable CPPPATH, et plus particulièrement leurs fichiers d'entête.
# Set environment for AVR-GCC. SConscript('#build_system/env_avr.py') # Import environment set for AVR-GCC. Import('env_avr') # Append CPPPATH with the root path of libraries. env_avr.Append(CPPPATH = [ '#libraries/' ]) # Define environments to use (one environment per target). environments = [ 'env_arduino_uno', 'env_arduino_mega2560' ] # Browse environments. for environment in environments: # Set environment for target. SConscript( '#build_system/' + environment + '.py', exports = 'env_avr' ) # Import environment set for target. Import('env_target') # Build program. SConscript( 'SConscript', variant_dir = '#build/' + environment, exports = { 'env_target' : env_target, 'env_name' : environment }, duplicate = 0 )
Conclusion
Ce principe de construction d'une bibliothèque sera repris par toutes les bibliothèques iDreamMicro.