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.
