SlideShare a Scribd company logo
2015 Pebble Developer Retreat
waf, wscript & Your Pebble App
Cherie Williams - Troublemaker
Agenda
• Why modify my wscript?
• Pebble SDK & Fat PBW
• What is this “waf” thing?
• Why is Pebble using waf?
• wscript
• Why do I care about waf?
• wscript Recipes
• Debugging
Why modify my wscript?
Making the Pebble SDK build system work for you
You can…
• Add C compiler flags
• Add custom defines for your apps (eg. #ifdef
NOLOG)
• Concatenate multiple JS files or do other file
manipulations at build time
You can…
• Collect & build source from a non-standard
project
• Add a linter (or two!)
• Run arbitrary scripts at build time to modify
resources or other files
You can…
• Add automatic testing
• Profile builds or add build visualizations
• Read in arbitrary text at build (eg. appinfo.json)
You can…
• Include an external library
• Build libraries for distribution
…the possibilities are endless!
Fine Print
Recipes + content from today’s talk are
*not* compatible with CloudPebble
Pebble SDK & Fat PBW
SDK: Capabilities Today
• Builds for up to 3 Pebble platforms
• Can build apps, as well as workers
• Handles platform-specific resources
• Packages a single PBW for distribution
aplite
Pebble Classic
Pebble Steel
basalt
Pebble Time
Pebble Time Steel
chalk Pebble Time Round
What is this “waf” thing?
A brief introduction to the Pebble build system
Introducing waf, a Python build system
• Open source, actively maintained
• Active community on Google Groups
• Task parallelization & dependency handling
• Language agnostic, but includes C compiler support
• Integrates with Eclipse, Visual Studio and Xcode
• Includes framework to build & distribute custom build
systems
Why is Pebble using waf?
This guy
Why Pebble uses waf
• Efficiently handles dependencies for large, complex
projects (such as Pebble firmware)
• Python!!
• Easy method overriding
• Can package & distribute additional scripts in the SDK
• Convenience modules for Logs, Node and methods
for easy file substitutions
wscript
The build script behind waf
Basic wscript (non-Pebble)
def configure(ctx):
print "Configure"
def build(ctx):
print "Build"
Basic wscript
$ waf configure build
Setting top to : /Users/cherie/waf-demo/
default
Setting out to : /Users/cherie/waf-demo/
default/build
Configure
'configure' finished successfully (0.009s)
Waf: Entering directory '/Users/cherie/waf-demo/default/build'
Build
Waf: Leaving directory '/Users/cherie/waf-demo/default/build'
'build' finished successfully (0.009s)
Invoking waf via the pebble-tool
pebble clean waf distclean
pebble build waf configure build (-v)
pebble build (-- --other-flags) waf configure build (--other-flags)
Standard Pebble wscript
def options(ctx):
ctx.load('pebble_sdk')
def configure(ctx):
ctx.load('pebble_sdk')
def build(ctx):
ctx.load('pebble_sdk')
build_worker = os.path.exists('worker_src')
binaries = []
for p in ctx.env.TARGET_PLATFORMS:
ctx.set_env(ctx.all_envs[p])
ctx.set_group(ctx.env.PLATFORM_NAME)
app_elf='{}/pebble-app.elf'.format(ctx.env.BUILD_DIR)
ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), target=app_elf)
if build_worker:
worker_elf='{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR)
binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf})
ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'), target=worker_elf)
else:
binaries.append({'platform': p, 'app_elf': app_elf})
ctx.set_group('bundle')
ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js'))
Read in command line options
Configure environment for build
Run build
For each HW platform:
• Create app binary
• Create worker binary (optional)
Bundle into PBW
Why do I care about waf?
Understanding how your Pebble project is built
wscript
The build script behind waf
Basic wscript (non-Pebble)
def configure(ctx):
print "Configure"
def build(ctx):
print "Build"
Glossary
Context
An object for each command executed that stores all the
information necessary for the command execution
BuildContext
The build context holds all the information necessary for a
build
Basic wscript (non-Pebble)
def configure(ctx):
print "Configure"
def build(ctx):
print "Build"
Modified Basic wscript
def configure(ctx):
ctx.env.MESSAGE = "Hello World"
def build(ctx):
pass
Glossary
Environment
A group of settings and variables that are stored in a
Context and that is cached between execution of
commands
NOTE: A single Context can have many, arbitrary
environments
build/c4che/*.py
AR = 'arm-none-eabi-gcc-ar'
ARFLAGS = 'rcs'
AS = 'arm-none-eabi-gcc'
BINDIR = '/usr/local/bin'
BUILD_DIR = 'basalt'
CC = ['arm-none-eabi-gcc']
CCLNK_SRC_F = []
CCLNK_TGT_F = ['-o']
CC_NAME = 'gcc'
CC_SRC_F = []
CC_TGT_F = ['-c', '-o']
CC_VERSION = ('4', '8', '4')
CFLAGS = ['-std=c99', '-mcpu=cortex-m3', '-mthumb', '-ffunction-sections', '-
fdata-sections', '-g', '-Os', '-D_TIME_H_', '-Wall', '-Wextra', '-Werror', '-Wno-
unused-parameter', '-Wno-error=unused-function', '-Wno-error=unused-variable']
CFLAGS_MACBUNDLE = ['-fPIC']
CFLAGS_cshlib = ['-fPIC']
CPPPATH_ST = '-I%s'
DEFINES = ['RELEASE', 'PBL_PLATFORM_BASALT', 'PBL_COLOR', 'PBL_RECT', 'PBL_SDK_3']
DEFINES_ST = '-D%s'
DEST_BINFMT = 'elf'
DEST_CPU = 'arm'
DEST_OS = 'darwin'
INCLUDES = ['basalt']
LD = 'arm-none-eabi-ld'
LIBDIR = '/usr/local/lib'
LIBPATH_ST = '-L%s'
LIB_ST = ‘-l%s'
LINKFLAGS = ['-mcpu=cortex-m3', '-mthumb', '-Wl,--gc-sections', '-Wl,--warn-
common', '-Os']
LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup']
LINKFLAGS_cshlib = ['-shared']
LINKFLAGS_cstlib = ['-Wl,-Bstatic']
LINK_CC = ['arm-none-eabi-gcc']
MESSAGE = ‘Hello World'
PBW_BIN_DIR = 'basalt'
PEBBLE_SDK = '/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/basalt'
PEBBLE_SDK_COMMON = '/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/common'
PLATFORM = {'PBW_BIN_DIR': 'basalt', 'TAGS': ['basalt', 'color', 'rect'],
'ADDITIONAL_TEXT_LINES_FOR_PEBBLE_H': [], 'MAX_APP_BINARY_SIZE': 65536,
'MAX_RESOURCES_SIZE': 1048576, 'MAX_APP_MEMORY_SIZE': 65536,
'MAX_WORKER_MEMORY_SIZE': 10240, 'NAME': 'basalt', 'BUILD_DIR': 'basalt',
'MAX_RESOURCES_SIZE_APPSTORE': 262144, 'DEFINES': ['PBL_PLATFORM_BASALT',
'PBL_COLOR', 'PBL_RECT']}
PLATFORM_NAME = 'basalt'
PREFIX = '/usr/local'
RPATH_ST = '-Wl,-rpath,%s'
SDK_VERSION_MAJOR = 5
SDK_VERSION_MINOR = 70
SHLIB_MARKER = None
SIZE = 'arm-none-eabi-size'
SONAME_ST = '-Wl,-h,%s'
STLIBPATH_ST = '-L%s'
STLIB_MARKER = None
STLIB_ST = '-l%s'
TARGET_PLATFORMS = [u'basalt', u'aplite']
cprogram_PATTERN = '%s'
cshlib_PATTERN = 'lib%s.so'
cstlib_PATTERN = 'lib%s.a'
macbundle_PATTERN = '%s.bundle'
Modified Basic wscript
def configure(ctx):
ctx.env.MESSAGE = "Hello World"
def build(ctx):
ctx(rule="echo ${MESSAGE}",
source='', target='')
Glossary
Task Generator
An object that handles the creation of task instances, and
helps simplify the creation of ordering constraints
Task
An object that represents the production of something
during the build (files, in general) and may be executed in
sequence or in parallel
${MESSAGE} is shorthand for ctx.env.MESSAGE
Modified Basic wscript
$ ../Pebble/waf configure build
Setting top to : /Users/cherie/waf-demo/
default
Setting out to : /Users/cherie/waf-demo/
default/build
'configure' finished successfully (0.002s)
Waf: Entering directory '/Users/cherie/waf-demo/default/build'
[1/1] echo ${MESSAGE}:
Hello World
Waf: Leaving directory '/Users/cherie/waf-demo/default/build'
'build' finished successfully (0.030s)
Modified Basic wscript w/Dependency
def build(ctx):
ctx(rule="echo 'hello' > ${TGT}",
source='',
target='message.txt')
ctx(rule="cp ${SRC} ${TGT}",
source='message.txt',
target='copy.txt')
Glossary
Build Order
The sequence in which tasks must be executed.
Dependency
A dependency represents the conditions by which a task can be
considered up-to-date or not, and can be explicit (dependency
on file inputs & outputs) or abstract (dependency on a value). waf
uses dependencies to determine whether tasks need to be run
(changed checksum of source files) and the build order of tasks.
${SRC} and ${TGT} are shorthand for source and target
Pebble Project Build
Let’s see how dependencies work
Glossary
Node
A data structure used to represent the filesystem. Nodes
may represent files or folders. File nodes are associated
with signatures, which can be hashes of the file contents
(source files) or task signatures (build files)
Node != Existing File
Glossary
Command
A function defined in the wscript file that is executed
when its name is given on the command-line, and can be
chained with other commands
Ex:
waf distclean (`pebble clean`)
waf configure build (`pebble build`)
Agenda
• Why modify my wscript?
• Pebble SDK & Fat PBW
• What is this “waf” thing?
• Why is Pebble using waf?
• wscript
• Why do I care about waf?
• wscript Recipes
• Debugging
wscript Recipes
https://developer.getpebble.com/build
Recipe #1
Add compile time flags
Create waftools/pedantic.py
def configure(ctx):
ctx.env.append_value('CFLAGS', '-pedantic')
def configure(ctx):
ctx.load('pebble_sdk')
+ ctx.load('pedantic', tooldir='waftools')
Add to wscript
[23/35] c: src/default.c -> build/src/default.c.18.o
In file included from ../src/default.c:1:0:
/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/aplite/include/pebble.h:
974:33: error: ISO C does not permit named variadic macros [-
Werror=variadic-macros]
#define APP_LOG(level, fmt, args...) 
^
/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/aplite/include/pebble.h:
1121:3: error: type of bit-field 'type' is a GCC extension [-
Werror=pedantic]
TupleType type:8;
^
/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/aplite/include/pebble.h:
1132:13: error: ISO C forbids zero-size array 'data' [-Werror=pedantic]
uint8_t data[0];
^
Recipe #2
Add build options & associated defines
Create waftools/defines.py
def options(ctx):
ctx.add_option('--no-log', action='store_true', default=False,
help="Mark a build to exclude app logging output")
def configure(ctx):
if ctx.options.no_log:
ctx.env.append_value('DEFINES', 'NOLOG')
Add to wscript for options & configure
ctx.load('defines', tooldir='waftools')
Add to main project.c file
#include <pebble.h>
#if defined(NOLOG)
#undef APP_LOG
#define APP_LOG(...)
#endif
Before
$ pebble install --emulator aplite --logs
Installing app...
App install succeeded.
[22:45:45] default.c:60> Done initializing, pushed window: 0x2001a5fc
[22:45:50] javascript> Ready!
$ pebble build -- --no-logs
…
$ pebble install --emulator aplite --logs
Installing app...
App install succeeded.
[22:49:34] javascript> Ready!
After
Recipe #3
Add a linter
Create waftools/linter.py
def options(ctx):
ctx.add_option('--jshint', action='store_true',
help="Run JSHint on the JS files in the build")
def configure(ctx):
if ctx.options.jshint:
try:
ctx.find_program('jshint', var='JSHINT')
except ctx.errors.ConfigurationError:
print "jshint was not found"
def build(ctx):
if ctx.env.JSHINT:
ctx(rule='${JSHINT} ${SRC}', source=ctx.path.ant_glob('src/**/*.js'))
Add to wscript
def options(ctx):
ctx.load('pebble_sdk')
+ ctx.load('linter', tooldir='waftools')
def configure(ctx):
ctx.load(‘pebble_sdk')
+ ctx.load('linter', tooldir='waftools')
def build(ctx):
ctx.load('pebble_sdk')
+ ctx.load('linter', tooldir='waftools')
$ pebble build -- --jshint
[25/36] jshint ${SRC}: src/js/another.js src/js/pebble-js-
app.js
../src/js/pebble-js-app.js: line 2, col 24, Missing semicolon.
1 error
Waf: Leaving directory `/Users/cherie/pebble-apps/default/
build'
Build failed
-> task in '' failed (exit status 2):
{task 4343355600: jshint ${SRC} another.js,pebble-js-
app.js -> }
' jshint ../src/js/another.js ../src/js/pebble-js-app.js '
Recipe #4
Use source code from multiple folders (2.x + 3.x)
Modify wscript
def build(ctx):
for p in ctx.env.TARGET_PLATFORMS:
- ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'),
target=app_elf)
+ ctx.pbl_program(source=ctx.path.ant_glob('src/{}/**/*.c'.format(p)),
target=app_elf)
if build_worker:
- ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'),
target=worker_elf)
+ ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/{}/'
'**/*.c'.format(p)),
target=worker_elf)
Recipe #5
Concatenate multiple JS files
Modify wscript
def build(ctx):
ctx.set_group('bundle')
+ js_files = ctx.path.ant_glob('src/**/*.js')
+ if js_files:
+ ctx(rule='cat ${SRC} > ${TGT}', source=js_files, target='pebble-js-
app.js')
- ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/
*.js'))
+ ctx.pbl_bundle(binaries=binaries, js='pebble-js-app.js' if js_files else
[])
A Word on Future
Proofing
Sometimes the SDK default wscript will be updated, but by
abstracting code out of wscript and into waf tools, it will be
much easier to maintain customizations!
Debugging
When your wscript changes go wrong
`pebble -v` (waf -v) for command-lines
[ 6/41] c: src/concentricity.c -> build/src/concentricity.c.16.o
21:27:05 runner ['arm-none-eabi-gcc', '-std=c99', '-mcpu=cortex-m3', '-
mthumb', '-ffunction-sections', '-fdata-sections', '-g', '-Os', '-D_TIME_H_',
'-Wall', '-Wextra', '-Werror', '-Wno-unused-parameter', '-Wno-error=unused-
function', '-Wno-error=unused-variable', '-fPIE', '-I/Users/cherie/pebble-
apps/pebble-dev/PebbleSDK-dev/Pebble/chalk/include', '-I/Users/cherie/pebble-
dev/PebbleSDK-dev/Pebble/chalk/include', '-I/Users/cherie/pebble-apps/
concentricity/build', '-I/Users/cherie/pebble-apps/concentricity', '-I/Users/
cherie/pebble-apps/concentricity/build/src', '-I/Users/cherie/pebble-apps/
concentricity/src', '-I/Users/cherie/pebble-apps/concentricity/build/chalk',
'-I/Users/cherie/pebble-apps/concentricity/chalk', '-DRELEASE', '-
DPBL_PLATFORM_CHALK', '-DPBL_COLOR', '-DPBL_ROUND', '-DPBL_SDK_3', '-
D__FILE_NAME__="concentricity.c"', '../src/concentricity.c', '-c', '-o',
'src/concentricity.c.16.o']
`pebble -vvv` (waf -vvv) for complete
21:51:50 preproc reading file '/Users/cherie/pebble-apps/
concentricity/build/chalk/src/resource_ids.auto.h'
21:51:50 deps deps for [/Users/cherie/pebble-apps/concentricity/
build/chalk/appinfo.auto.c]: [/Users/cherie/pebble-apps/
concentricity/build/chalk/src/resource_ids.auto.h]; unresolved
['pebble_process_info.h']
21:51:50 task task {task 4344651216: c appinfo.auto.c ->
appinfo.auto.c.16.o} must run as it was never run before or the
task code changed
21:51:50 runner_env kw={'shell': False, 'cwd': '/Users/cherie/
pebble-apps/concentricity/build', 'env': None}
21:51:50 envhash d751713988987e9331980363e24189ce []
Zone Description
runner command-lines executed (same as -v)
deps implicit dependencies found
task_gen task creation & task generator method execution
action functions to execute for building the targets
env environment contents
envhash hashes of the environment objects
build build context operations, like filesystem access
preproc preprocessor execution
group groups & task generators
$ pebble build -- --zones=deps
23:01:45 deps deps for [/Users/cherie/pebble-apps/concentricity/src/
concentricity.c]: [/Users/cherie/pebble-apps/concentricity/src/ui.h];
unresolved ['pebble.h']
Helpful waf Links
• Pebble Recipes
• https://developer.getpebble.com/build
• GitHub Project
• https://github.com/waf-project/waf
• Google Group
• https://groups.google.com/forum/#!forum/waf-users
• Book
• https://waf.io/book/
2015 Pebble Developer Retreat
Questions?
https://developer.getpebble.com/build

More Related Content

What's hot

Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
Guillaume Laforge
 
Gradle in a Polyglot World
Gradle in a Polyglot WorldGradle in a Polyglot World
Gradle in a Polyglot World
Schalk Cronjé
 
Developing IT infrastructures with Puppet
Developing IT infrastructures with PuppetDeveloping IT infrastructures with Puppet
Developing IT infrastructures with Puppet
Alessandro Franceschi
 
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
ngotogenome
 
Golang Project Layout and Practice
Golang Project Layout and PracticeGolang Project Layout and Practice
Golang Project Layout and Practice
Bo-Yi Wu
 
Scripting Embulk Plugins
Scripting Embulk PluginsScripting Embulk Plugins
Scripting Embulk Plugins
Sadayuki Furuhashi
 
Puppet Systems Infrastructure Construction Kit
Puppet Systems Infrastructure Construction KitPuppet Systems Infrastructure Construction Kit
Puppet Systems Infrastructure Construction Kit
Alessandro Franceschi
 
carrow - Go bindings to Apache Arrow via C++-API
carrow - Go bindings to Apache Arrow via C++-APIcarrow - Go bindings to Apache Arrow via C++-API
carrow - Go bindings to Apache Arrow via C++-API
Yoni Davidson
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
Hiroshi SHIBATA
 
Fluentd - road to v1 -
Fluentd - road to v1 -Fluentd - road to v1 -
Fluentd - road to v1 -
N Masahiro
 
Writing Ansible Modules (CLT'19)
Writing Ansible Modules (CLT'19)Writing Ansible Modules (CLT'19)
Writing Ansible Modules (CLT'19)
Martin Schütte
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
Hiroshi SHIBATA
 
AngularDart - Meetup 15/03/2017
AngularDart - Meetup 15/03/2017AngularDart - Meetup 15/03/2017
AngularDart - Meetup 15/03/2017
Stéphane Este-Gracias
 
Puppet: From 0 to 100 in 30 minutes
Puppet: From 0 to 100 in 30 minutesPuppet: From 0 to 100 in 30 minutes
Puppet: From 0 to 100 in 30 minutes
Alessandro Franceschi
 
Modules of the twenties
Modules of the twentiesModules of the twenties
Modules of the twenties
Puppet
 
Bolt C++ Standard Template Libary for HSA by Ben Sanders, AMD
Bolt C++ Standard Template Libary for HSA  by Ben Sanders, AMDBolt C++ Standard Template Libary for HSA  by Ben Sanders, AMD
Bolt C++ Standard Template Libary for HSA by Ben Sanders, AMD
HSA Foundation
 
Embuk internals
Embuk internalsEmbuk internals
Embuk internals
Sadayuki Furuhashi
 
Build microservice with gRPC in golang
Build microservice with gRPC in golangBuild microservice with gRPC in golang
Build microservice with gRPC in golang
Ting-Li Chou
 
MongoDB & Hadoop: Flexible Hourly Batch Processing Model
MongoDB & Hadoop: Flexible Hourly Batch Processing ModelMongoDB & Hadoop: Flexible Hourly Batch Processing Model
MongoDB & Hadoop: Flexible Hourly Batch Processing ModelTakahiro Inoue
 
Experiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRubyExperiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRuby
Matthew Gaudet
 

What's hot (20)

Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
 
Gradle in a Polyglot World
Gradle in a Polyglot WorldGradle in a Polyglot World
Gradle in a Polyglot World
 
Developing IT infrastructures with Puppet
Developing IT infrastructures with PuppetDeveloping IT infrastructures with Puppet
Developing IT infrastructures with Puppet
 
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
 
Golang Project Layout and Practice
Golang Project Layout and PracticeGolang Project Layout and Practice
Golang Project Layout and Practice
 
Scripting Embulk Plugins
Scripting Embulk PluginsScripting Embulk Plugins
Scripting Embulk Plugins
 
Puppet Systems Infrastructure Construction Kit
Puppet Systems Infrastructure Construction KitPuppet Systems Infrastructure Construction Kit
Puppet Systems Infrastructure Construction Kit
 
carrow - Go bindings to Apache Arrow via C++-API
carrow - Go bindings to Apache Arrow via C++-APIcarrow - Go bindings to Apache Arrow via C++-API
carrow - Go bindings to Apache Arrow via C++-API
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 
Fluentd - road to v1 -
Fluentd - road to v1 -Fluentd - road to v1 -
Fluentd - road to v1 -
 
Writing Ansible Modules (CLT'19)
Writing Ansible Modules (CLT'19)Writing Ansible Modules (CLT'19)
Writing Ansible Modules (CLT'19)
 
How DSL works on Ruby
How DSL works on RubyHow DSL works on Ruby
How DSL works on Ruby
 
AngularDart - Meetup 15/03/2017
AngularDart - Meetup 15/03/2017AngularDart - Meetup 15/03/2017
AngularDart - Meetup 15/03/2017
 
Puppet: From 0 to 100 in 30 minutes
Puppet: From 0 to 100 in 30 minutesPuppet: From 0 to 100 in 30 minutes
Puppet: From 0 to 100 in 30 minutes
 
Modules of the twenties
Modules of the twentiesModules of the twenties
Modules of the twenties
 
Bolt C++ Standard Template Libary for HSA by Ben Sanders, AMD
Bolt C++ Standard Template Libary for HSA  by Ben Sanders, AMDBolt C++ Standard Template Libary for HSA  by Ben Sanders, AMD
Bolt C++ Standard Template Libary for HSA by Ben Sanders, AMD
 
Embuk internals
Embuk internalsEmbuk internals
Embuk internals
 
Build microservice with gRPC in golang
Build microservice with gRPC in golangBuild microservice with gRPC in golang
Build microservice with gRPC in golang
 
MongoDB & Hadoop: Flexible Hourly Batch Processing Model
MongoDB & Hadoop: Flexible Hourly Batch Processing ModelMongoDB & Hadoop: Flexible Hourly Batch Processing Model
MongoDB & Hadoop: Flexible Hourly Batch Processing Model
 
Experiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRubyExperiments in Sharing Java VM Technology with CRuby
Experiments in Sharing Java VM Technology with CRuby
 

Similar to #PDR15 - waf, wscript and Your Pebble App

An introduction to maven gradle and sbt
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbt
Fabio Fumarola
 
Road to sbt 1.0 paved with server
Road to sbt 1.0   paved with serverRoad to sbt 1.0   paved with server
Road to sbt 1.0 paved with server
Eugene Yokota
 
Cloud Foundry V2 | Intermediate Deep Dive
Cloud Foundry V2 | Intermediate Deep DiveCloud Foundry V2 | Intermediate Deep Dive
Cloud Foundry V2 | Intermediate Deep DiveKazuto Kusama
 
Continuous Integration/Deployment with Docker and Jenkins
Continuous Integration/Deployment with Docker and JenkinsContinuous Integration/Deployment with Docker and Jenkins
Continuous Integration/Deployment with Docker and Jenkins
Francesco Bruni
 
Road to sbt 1.0: Paved with server (2015 Amsterdam)
Road to sbt 1.0: Paved with server (2015 Amsterdam)Road to sbt 1.0: Paved with server (2015 Amsterdam)
Road to sbt 1.0: Paved with server (2015 Amsterdam)
Eugene Yokota
 
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverageTesting NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoveragemlilley
 
Dockercon EU 2014
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014
Rafe Colton
 
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
Sencha
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
orkaplan
 
Scala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camouScala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camou
J On The Beach
 
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, OrchestrationThe Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
Erica Windisch
 
Kolla talk at OpenStack Summit 2017 in Sydney
Kolla talk at OpenStack Summit 2017 in SydneyKolla talk at OpenStack Summit 2017 in Sydney
Kolla talk at OpenStack Summit 2017 in Sydney
Vikram G Hosakote
 
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
Docker, Inc.
 
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js TutorialOSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js TutorialTom Croucher
 
Programming in Linux Environment
Programming in Linux EnvironmentProgramming in Linux Environment
Programming in Linux Environment
Dongho Kang
 
Setting Up a TIG Stack for Your Testing
Setting Up a TIG Stack for Your TestingSetting Up a TIG Stack for Your Testing
Setting Up a TIG Stack for Your Testing
Jet Liu
 
Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...
Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...
Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...
Neven Cvetković
 
Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)
HungWei Chiu
 

Similar to #PDR15 - waf, wscript and Your Pebble App (20)

An introduction to maven gradle and sbt
An introduction to maven gradle and sbtAn introduction to maven gradle and sbt
An introduction to maven gradle and sbt
 
Road to sbt 1.0 paved with server
Road to sbt 1.0   paved with serverRoad to sbt 1.0   paved with server
Road to sbt 1.0 paved with server
 
Gradle como alternativa a maven
Gradle como alternativa a mavenGradle como alternativa a maven
Gradle como alternativa a maven
 
Cloud Foundry V2 | Intermediate Deep Dive
Cloud Foundry V2 | Intermediate Deep DiveCloud Foundry V2 | Intermediate Deep Dive
Cloud Foundry V2 | Intermediate Deep Dive
 
Continuous Integration/Deployment with Docker and Jenkins
Continuous Integration/Deployment with Docker and JenkinsContinuous Integration/Deployment with Docker and Jenkins
Continuous Integration/Deployment with Docker and Jenkins
 
Road to sbt 1.0: Paved with server (2015 Amsterdam)
Road to sbt 1.0: Paved with server (2015 Amsterdam)Road to sbt 1.0: Paved with server (2015 Amsterdam)
Road to sbt 1.0: Paved with server (2015 Amsterdam)
 
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverageTesting NodeJS with Mocha, Should, Sinon, and JSCoverage
Testing NodeJS with Mocha, Should, Sinon, and JSCoverage
 
Dockercon EU 2014
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014
 
Play framework
Play frameworkPlay framework
Play framework
 
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
SenchaCon 2016: Develop, Test & Deploy with Docker - Jonas Schwabe
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
 
Scala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camouScala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camou
 
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, OrchestrationThe Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
The Docker "Gauntlet" - Introduction, Ecosystem, Deployment, Orchestration
 
Kolla talk at OpenStack Summit 2017 in Sydney
Kolla talk at OpenStack Summit 2017 in SydneyKolla talk at OpenStack Summit 2017 in Sydney
Kolla talk at OpenStack Summit 2017 in Sydney
 
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
 
OSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js TutorialOSCON 2011 - Node.js Tutorial
OSCON 2011 - Node.js Tutorial
 
Programming in Linux Environment
Programming in Linux EnvironmentProgramming in Linux Environment
Programming in Linux Environment
 
Setting Up a TIG Stack for Your Testing
Setting Up a TIG Stack for Your TestingSetting Up a TIG Stack for Your Testing
Setting Up a TIG Stack for Your Testing
 
Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...
Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...
Cloud Foundry Summit Europe 2018 - Deveveloper Experience with Cloud Foundry ...
 
Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)Build Your Own CaaS (Container as a Service)
Build Your Own CaaS (Container as a Service)
 

More from Pebble Technology

#PDR15 - Awesome Appstore Assets
#PDR15 - Awesome Appstore Assets#PDR15 - Awesome Appstore Assets
#PDR15 - Awesome Appstore Assets
Pebble Technology
 
#PDR15 - Smartstrap Workshop
#PDR15 - Smartstrap Workshop#PDR15 - Smartstrap Workshop
#PDR15 - Smartstrap Workshop
Pebble Technology
 
#PDR15 - Data Analytics and Pebble
#PDR15 - Data Analytics and Pebble#PDR15 - Data Analytics and Pebble
#PDR15 - Data Analytics and Pebble
Pebble Technology
 
#PDR15 - Best Use Cases For Timeline
#PDR15 - Best Use Cases For Timeline#PDR15 - Best Use Cases For Timeline
#PDR15 - Best Use Cases For Timeline
Pebble Technology
 
#PDR15 - PebbleKit iOS 3.0
#PDR15 - PebbleKit iOS 3.0#PDR15 - PebbleKit iOS 3.0
#PDR15 - PebbleKit iOS 3.0
Pebble Technology
 
#PDR15 - Voice API
#PDR15 - Voice API#PDR15 - Voice API
#PDR15 - Voice API
Pebble Technology
 
#PDR15 - Developing for Round
#PDR15 - Developing for Round#PDR15 - Developing for Round
#PDR15 - Developing for Round
Pebble Technology
 
#PDR15 - Designing for Pebble
#PDR15 - Designing for Pebble#PDR15 - Designing for Pebble
#PDR15 - Designing for Pebble
Pebble Technology
 
#PDR15 Kick-Off
#PDR15 Kick-Off#PDR15 Kick-Off
#PDR15 Kick-Off
Pebble Technology
 
Pebble Slate Workshop
Pebble Slate WorkshopPebble Slate Workshop
Pebble Slate Workshop
Pebble Technology
 
Connecting Pebble to the World
Connecting Pebble to the WorldConnecting Pebble to the World
Connecting Pebble to the World
Pebble Technology
 
Guest Presentation - Strap | Pebble Developer Retreat 2014
Guest Presentation - Strap | Pebble Developer Retreat 2014Guest Presentation - Strap | Pebble Developer Retreat 2014
Guest Presentation - Strap | Pebble Developer Retreat 2014
Pebble Technology
 
Battery Life | Pebble Developer Retreat 2014
Battery Life | Pebble Developer Retreat 2014Battery Life | Pebble Developer Retreat 2014
Battery Life | Pebble Developer Retreat 2014
Pebble Technology
 
Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014
Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014
Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014
Pebble Technology
 
Advanced Techniques: Size | Pebble Developer Retreat 2014
Advanced Techniques: Size | Pebble Developer Retreat 2014Advanced Techniques: Size | Pebble Developer Retreat 2014
Advanced Techniques: Size | Pebble Developer Retreat 2014
Pebble Technology
 
Advanced Techniques: Graphics | Pebble Developer Retreat 2014
Advanced Techniques: Graphics | Pebble Developer Retreat 2014Advanced Techniques: Graphics | Pebble Developer Retreat 2014
Advanced Techniques: Graphics | Pebble Developer Retreat 2014
Pebble Technology
 
Announcing Pebble SDK 2.0
Announcing Pebble SDK 2.0Announcing Pebble SDK 2.0
Announcing Pebble SDK 2.0
Pebble Technology
 

More from Pebble Technology (18)

#PDR15 - Awesome Appstore Assets
#PDR15 - Awesome Appstore Assets#PDR15 - Awesome Appstore Assets
#PDR15 - Awesome Appstore Assets
 
#PDR15 - Smartstrap Workshop
#PDR15 - Smartstrap Workshop#PDR15 - Smartstrap Workshop
#PDR15 - Smartstrap Workshop
 
#PDR15 - Data Analytics and Pebble
#PDR15 - Data Analytics and Pebble#PDR15 - Data Analytics and Pebble
#PDR15 - Data Analytics and Pebble
 
#PDR15 - Best Use Cases For Timeline
#PDR15 - Best Use Cases For Timeline#PDR15 - Best Use Cases For Timeline
#PDR15 - Best Use Cases For Timeline
 
#PDR15 - PebbleKit iOS 3.0
#PDR15 - PebbleKit iOS 3.0#PDR15 - PebbleKit iOS 3.0
#PDR15 - PebbleKit iOS 3.0
 
#PDR15 - Voice API
#PDR15 - Voice API#PDR15 - Voice API
#PDR15 - Voice API
 
#PDR15 - Developing for Round
#PDR15 - Developing for Round#PDR15 - Developing for Round
#PDR15 - Developing for Round
 
#PDR15 - Designing for Pebble
#PDR15 - Designing for Pebble#PDR15 - Designing for Pebble
#PDR15 - Designing for Pebble
 
#PDR15 Kick-Off
#PDR15 Kick-Off#PDR15 Kick-Off
#PDR15 Kick-Off
 
Pebble Slate Workshop
Pebble Slate WorkshopPebble Slate Workshop
Pebble Slate Workshop
 
Connecting Pebble to the World
Connecting Pebble to the WorldConnecting Pebble to the World
Connecting Pebble to the World
 
Guest Presentation - Strap | Pebble Developer Retreat 2014
Guest Presentation - Strap | Pebble Developer Retreat 2014Guest Presentation - Strap | Pebble Developer Retreat 2014
Guest Presentation - Strap | Pebble Developer Retreat 2014
 
Battery Life | Pebble Developer Retreat 2014
Battery Life | Pebble Developer Retreat 2014Battery Life | Pebble Developer Retreat 2014
Battery Life | Pebble Developer Retreat 2014
 
Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014
Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014
Thomas Sarlandie Kickoff Talk | Pebble Developer Retreat 2014
 
Advanced Techniques: Size | Pebble Developer Retreat 2014
Advanced Techniques: Size | Pebble Developer Retreat 2014Advanced Techniques: Size | Pebble Developer Retreat 2014
Advanced Techniques: Size | Pebble Developer Retreat 2014
 
Advanced Techniques: Graphics | Pebble Developer Retreat 2014
Advanced Techniques: Graphics | Pebble Developer Retreat 2014Advanced Techniques: Graphics | Pebble Developer Retreat 2014
Advanced Techniques: Graphics | Pebble Developer Retreat 2014
 
Pebble wearables devcon
Pebble wearables devconPebble wearables devcon
Pebble wearables devcon
 
Announcing Pebble SDK 2.0
Announcing Pebble SDK 2.0Announcing Pebble SDK 2.0
Announcing Pebble SDK 2.0
 

Recently uploaded

From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 

Recently uploaded (20)

From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 

#PDR15 - waf, wscript and Your Pebble App

  • 1. 2015 Pebble Developer Retreat waf, wscript & Your Pebble App Cherie Williams - Troublemaker
  • 2. Agenda • Why modify my wscript? • Pebble SDK & Fat PBW • What is this “waf” thing? • Why is Pebble using waf? • wscript • Why do I care about waf? • wscript Recipes • Debugging
  • 3. Why modify my wscript? Making the Pebble SDK build system work for you
  • 4. You can… • Add C compiler flags • Add custom defines for your apps (eg. #ifdef NOLOG) • Concatenate multiple JS files or do other file manipulations at build time
  • 5. You can… • Collect & build source from a non-standard project • Add a linter (or two!) • Run arbitrary scripts at build time to modify resources or other files
  • 6. You can… • Add automatic testing • Profile builds or add build visualizations • Read in arbitrary text at build (eg. appinfo.json)
  • 7. You can… • Include an external library • Build libraries for distribution …the possibilities are endless!
  • 8. Fine Print Recipes + content from today’s talk are *not* compatible with CloudPebble
  • 9. Pebble SDK & Fat PBW
  • 10. SDK: Capabilities Today • Builds for up to 3 Pebble platforms • Can build apps, as well as workers • Handles platform-specific resources • Packages a single PBW for distribution aplite Pebble Classic Pebble Steel basalt Pebble Time Pebble Time Steel chalk Pebble Time Round
  • 11.
  • 12. What is this “waf” thing? A brief introduction to the Pebble build system
  • 13. Introducing waf, a Python build system • Open source, actively maintained • Active community on Google Groups • Task parallelization & dependency handling • Language agnostic, but includes C compiler support • Integrates with Eclipse, Visual Studio and Xcode • Includes framework to build & distribute custom build systems
  • 14. Why is Pebble using waf?
  • 16. Why Pebble uses waf • Efficiently handles dependencies for large, complex projects (such as Pebble firmware) • Python!! • Easy method overriding • Can package & distribute additional scripts in the SDK • Convenience modules for Logs, Node and methods for easy file substitutions
  • 18. Basic wscript (non-Pebble) def configure(ctx): print "Configure" def build(ctx): print "Build"
  • 19. Basic wscript $ waf configure build Setting top to : /Users/cherie/waf-demo/ default Setting out to : /Users/cherie/waf-demo/ default/build Configure 'configure' finished successfully (0.009s) Waf: Entering directory '/Users/cherie/waf-demo/default/build' Build Waf: Leaving directory '/Users/cherie/waf-demo/default/build' 'build' finished successfully (0.009s)
  • 20. Invoking waf via the pebble-tool pebble clean waf distclean pebble build waf configure build (-v) pebble build (-- --other-flags) waf configure build (--other-flags)
  • 21. Standard Pebble wscript def options(ctx): ctx.load('pebble_sdk') def configure(ctx): ctx.load('pebble_sdk') def build(ctx): ctx.load('pebble_sdk') build_worker = os.path.exists('worker_src') binaries = [] for p in ctx.env.TARGET_PLATFORMS: ctx.set_env(ctx.all_envs[p]) ctx.set_group(ctx.env.PLATFORM_NAME) app_elf='{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), target=app_elf) if build_worker: worker_elf='{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf}) ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'), target=worker_elf) else: binaries.append({'platform': p, 'app_elf': app_elf}) ctx.set_group('bundle') ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js')) Read in command line options Configure environment for build Run build For each HW platform: • Create app binary • Create worker binary (optional) Bundle into PBW
  • 22.
  • 23.
  • 24. Why do I care about waf? Understanding how your Pebble project is built
  • 26. Basic wscript (non-Pebble) def configure(ctx): print "Configure" def build(ctx): print "Build"
  • 27. Glossary Context An object for each command executed that stores all the information necessary for the command execution BuildContext The build context holds all the information necessary for a build
  • 28. Basic wscript (non-Pebble) def configure(ctx): print "Configure" def build(ctx): print "Build"
  • 29. Modified Basic wscript def configure(ctx): ctx.env.MESSAGE = "Hello World" def build(ctx): pass
  • 30. Glossary Environment A group of settings and variables that are stored in a Context and that is cached between execution of commands NOTE: A single Context can have many, arbitrary environments
  • 31. build/c4che/*.py AR = 'arm-none-eabi-gcc-ar' ARFLAGS = 'rcs' AS = 'arm-none-eabi-gcc' BINDIR = '/usr/local/bin' BUILD_DIR = 'basalt' CC = ['arm-none-eabi-gcc'] CCLNK_SRC_F = [] CCLNK_TGT_F = ['-o'] CC_NAME = 'gcc' CC_SRC_F = [] CC_TGT_F = ['-c', '-o'] CC_VERSION = ('4', '8', '4') CFLAGS = ['-std=c99', '-mcpu=cortex-m3', '-mthumb', '-ffunction-sections', '- fdata-sections', '-g', '-Os', '-D_TIME_H_', '-Wall', '-Wextra', '-Werror', '-Wno- unused-parameter', '-Wno-error=unused-function', '-Wno-error=unused-variable'] CFLAGS_MACBUNDLE = ['-fPIC'] CFLAGS_cshlib = ['-fPIC'] CPPPATH_ST = '-I%s' DEFINES = ['RELEASE', 'PBL_PLATFORM_BASALT', 'PBL_COLOR', 'PBL_RECT', 'PBL_SDK_3'] DEFINES_ST = '-D%s' DEST_BINFMT = 'elf' DEST_CPU = 'arm' DEST_OS = 'darwin' INCLUDES = ['basalt'] LD = 'arm-none-eabi-ld' LIBDIR = '/usr/local/lib' LIBPATH_ST = '-L%s' LIB_ST = ‘-l%s' LINKFLAGS = ['-mcpu=cortex-m3', '-mthumb', '-Wl,--gc-sections', '-Wl,--warn- common', '-Os'] LINKFLAGS_MACBUNDLE = ['-bundle', '-undefined', 'dynamic_lookup'] LINKFLAGS_cshlib = ['-shared'] LINKFLAGS_cstlib = ['-Wl,-Bstatic'] LINK_CC = ['arm-none-eabi-gcc'] MESSAGE = ‘Hello World' PBW_BIN_DIR = 'basalt' PEBBLE_SDK = '/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/basalt' PEBBLE_SDK_COMMON = '/Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/common' PLATFORM = {'PBW_BIN_DIR': 'basalt', 'TAGS': ['basalt', 'color', 'rect'], 'ADDITIONAL_TEXT_LINES_FOR_PEBBLE_H': [], 'MAX_APP_BINARY_SIZE': 65536, 'MAX_RESOURCES_SIZE': 1048576, 'MAX_APP_MEMORY_SIZE': 65536, 'MAX_WORKER_MEMORY_SIZE': 10240, 'NAME': 'basalt', 'BUILD_DIR': 'basalt', 'MAX_RESOURCES_SIZE_APPSTORE': 262144, 'DEFINES': ['PBL_PLATFORM_BASALT', 'PBL_COLOR', 'PBL_RECT']} PLATFORM_NAME = 'basalt' PREFIX = '/usr/local' RPATH_ST = '-Wl,-rpath,%s' SDK_VERSION_MAJOR = 5 SDK_VERSION_MINOR = 70 SHLIB_MARKER = None SIZE = 'arm-none-eabi-size' SONAME_ST = '-Wl,-h,%s' STLIBPATH_ST = '-L%s' STLIB_MARKER = None STLIB_ST = '-l%s' TARGET_PLATFORMS = [u'basalt', u'aplite'] cprogram_PATTERN = '%s' cshlib_PATTERN = 'lib%s.so' cstlib_PATTERN = 'lib%s.a' macbundle_PATTERN = '%s.bundle'
  • 32. Modified Basic wscript def configure(ctx): ctx.env.MESSAGE = "Hello World" def build(ctx): ctx(rule="echo ${MESSAGE}", source='', target='')
  • 33. Glossary Task Generator An object that handles the creation of task instances, and helps simplify the creation of ordering constraints Task An object that represents the production of something during the build (files, in general) and may be executed in sequence or in parallel
  • 34. ${MESSAGE} is shorthand for ctx.env.MESSAGE
  • 35. Modified Basic wscript $ ../Pebble/waf configure build Setting top to : /Users/cherie/waf-demo/ default Setting out to : /Users/cherie/waf-demo/ default/build 'configure' finished successfully (0.002s) Waf: Entering directory '/Users/cherie/waf-demo/default/build' [1/1] echo ${MESSAGE}: Hello World Waf: Leaving directory '/Users/cherie/waf-demo/default/build' 'build' finished successfully (0.030s)
  • 36. Modified Basic wscript w/Dependency def build(ctx): ctx(rule="echo 'hello' > ${TGT}", source='', target='message.txt') ctx(rule="cp ${SRC} ${TGT}", source='message.txt', target='copy.txt')
  • 37. Glossary Build Order The sequence in which tasks must be executed. Dependency A dependency represents the conditions by which a task can be considered up-to-date or not, and can be explicit (dependency on file inputs & outputs) or abstract (dependency on a value). waf uses dependencies to determine whether tasks need to be run (changed checksum of source files) and the build order of tasks.
  • 38. ${SRC} and ${TGT} are shorthand for source and target
  • 39. Pebble Project Build Let’s see how dependencies work
  • 40.
  • 41. Glossary Node A data structure used to represent the filesystem. Nodes may represent files or folders. File nodes are associated with signatures, which can be hashes of the file contents (source files) or task signatures (build files)
  • 43. Glossary Command A function defined in the wscript file that is executed when its name is given on the command-line, and can be chained with other commands Ex: waf distclean (`pebble clean`) waf configure build (`pebble build`)
  • 44.
  • 45. Agenda • Why modify my wscript? • Pebble SDK & Fat PBW • What is this “waf” thing? • Why is Pebble using waf? • wscript • Why do I care about waf? • wscript Recipes • Debugging
  • 47. Recipe #1 Add compile time flags
  • 48. Create waftools/pedantic.py def configure(ctx): ctx.env.append_value('CFLAGS', '-pedantic') def configure(ctx): ctx.load('pebble_sdk') + ctx.load('pedantic', tooldir='waftools') Add to wscript
  • 49. [23/35] c: src/default.c -> build/src/default.c.18.o In file included from ../src/default.c:1:0: /Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/aplite/include/pebble.h: 974:33: error: ISO C does not permit named variadic macros [- Werror=variadic-macros] #define APP_LOG(level, fmt, args...) ^ /Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/aplite/include/pebble.h: 1121:3: error: type of bit-field 'type' is a GCC extension [- Werror=pedantic] TupleType type:8; ^ /Users/cherie/pebble-dev/PebbleSDK-dev/Pebble/aplite/include/pebble.h: 1132:13: error: ISO C forbids zero-size array 'data' [-Werror=pedantic] uint8_t data[0]; ^
  • 50. Recipe #2 Add build options & associated defines
  • 51. Create waftools/defines.py def options(ctx): ctx.add_option('--no-log', action='store_true', default=False, help="Mark a build to exclude app logging output") def configure(ctx): if ctx.options.no_log: ctx.env.append_value('DEFINES', 'NOLOG') Add to wscript for options & configure ctx.load('defines', tooldir='waftools')
  • 52. Add to main project.c file #include <pebble.h> #if defined(NOLOG) #undef APP_LOG #define APP_LOG(...) #endif
  • 53. Before $ pebble install --emulator aplite --logs Installing app... App install succeeded. [22:45:45] default.c:60> Done initializing, pushed window: 0x2001a5fc [22:45:50] javascript> Ready! $ pebble build -- --no-logs … $ pebble install --emulator aplite --logs Installing app... App install succeeded. [22:49:34] javascript> Ready! After
  • 54. Recipe #3 Add a linter
  • 55. Create waftools/linter.py def options(ctx): ctx.add_option('--jshint', action='store_true', help="Run JSHint on the JS files in the build") def configure(ctx): if ctx.options.jshint: try: ctx.find_program('jshint', var='JSHINT') except ctx.errors.ConfigurationError: print "jshint was not found" def build(ctx): if ctx.env.JSHINT: ctx(rule='${JSHINT} ${SRC}', source=ctx.path.ant_glob('src/**/*.js'))
  • 56. Add to wscript def options(ctx): ctx.load('pebble_sdk') + ctx.load('linter', tooldir='waftools') def configure(ctx): ctx.load(‘pebble_sdk') + ctx.load('linter', tooldir='waftools') def build(ctx): ctx.load('pebble_sdk') + ctx.load('linter', tooldir='waftools')
  • 57. $ pebble build -- --jshint [25/36] jshint ${SRC}: src/js/another.js src/js/pebble-js- app.js ../src/js/pebble-js-app.js: line 2, col 24, Missing semicolon. 1 error Waf: Leaving directory `/Users/cherie/pebble-apps/default/ build' Build failed -> task in '' failed (exit status 2): {task 4343355600: jshint ${SRC} another.js,pebble-js- app.js -> } ' jshint ../src/js/another.js ../src/js/pebble-js-app.js '
  • 58. Recipe #4 Use source code from multiple folders (2.x + 3.x)
  • 59. Modify wscript def build(ctx): for p in ctx.env.TARGET_PLATFORMS: - ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), target=app_elf) + ctx.pbl_program(source=ctx.path.ant_glob('src/{}/**/*.c'.format(p)), target=app_elf) if build_worker: - ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'), target=worker_elf) + ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/{}/' '**/*.c'.format(p)), target=worker_elf)
  • 61. Modify wscript def build(ctx): ctx.set_group('bundle') + js_files = ctx.path.ant_glob('src/**/*.js') + if js_files: + ctx(rule='cat ${SRC} > ${TGT}', source=js_files, target='pebble-js- app.js') - ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/ *.js')) + ctx.pbl_bundle(binaries=binaries, js='pebble-js-app.js' if js_files else [])
  • 62. A Word on Future Proofing Sometimes the SDK default wscript will be updated, but by abstracting code out of wscript and into waf tools, it will be much easier to maintain customizations!
  • 63. Debugging When your wscript changes go wrong
  • 64. `pebble -v` (waf -v) for command-lines [ 6/41] c: src/concentricity.c -> build/src/concentricity.c.16.o 21:27:05 runner ['arm-none-eabi-gcc', '-std=c99', '-mcpu=cortex-m3', '- mthumb', '-ffunction-sections', '-fdata-sections', '-g', '-Os', '-D_TIME_H_', '-Wall', '-Wextra', '-Werror', '-Wno-unused-parameter', '-Wno-error=unused- function', '-Wno-error=unused-variable', '-fPIE', '-I/Users/cherie/pebble- apps/pebble-dev/PebbleSDK-dev/Pebble/chalk/include', '-I/Users/cherie/pebble- dev/PebbleSDK-dev/Pebble/chalk/include', '-I/Users/cherie/pebble-apps/ concentricity/build', '-I/Users/cherie/pebble-apps/concentricity', '-I/Users/ cherie/pebble-apps/concentricity/build/src', '-I/Users/cherie/pebble-apps/ concentricity/src', '-I/Users/cherie/pebble-apps/concentricity/build/chalk', '-I/Users/cherie/pebble-apps/concentricity/chalk', '-DRELEASE', '- DPBL_PLATFORM_CHALK', '-DPBL_COLOR', '-DPBL_ROUND', '-DPBL_SDK_3', '- D__FILE_NAME__="concentricity.c"', '../src/concentricity.c', '-c', '-o', 'src/concentricity.c.16.o']
  • 65. `pebble -vvv` (waf -vvv) for complete 21:51:50 preproc reading file '/Users/cherie/pebble-apps/ concentricity/build/chalk/src/resource_ids.auto.h' 21:51:50 deps deps for [/Users/cherie/pebble-apps/concentricity/ build/chalk/appinfo.auto.c]: [/Users/cherie/pebble-apps/ concentricity/build/chalk/src/resource_ids.auto.h]; unresolved ['pebble_process_info.h'] 21:51:50 task task {task 4344651216: c appinfo.auto.c -> appinfo.auto.c.16.o} must run as it was never run before or the task code changed 21:51:50 runner_env kw={'shell': False, 'cwd': '/Users/cherie/ pebble-apps/concentricity/build', 'env': None} 21:51:50 envhash d751713988987e9331980363e24189ce []
  • 66. Zone Description runner command-lines executed (same as -v) deps implicit dependencies found task_gen task creation & task generator method execution action functions to execute for building the targets env environment contents envhash hashes of the environment objects build build context operations, like filesystem access preproc preprocessor execution group groups & task generators $ pebble build -- --zones=deps 23:01:45 deps deps for [/Users/cherie/pebble-apps/concentricity/src/ concentricity.c]: [/Users/cherie/pebble-apps/concentricity/src/ui.h]; unresolved ['pebble.h']
  • 67. Helpful waf Links • Pebble Recipes • https://developer.getpebble.com/build • GitHub Project • https://github.com/waf-project/waf • Google Group • https://groups.google.com/forum/#!forum/waf-users • Book • https://waf.io/book/
  • 68. 2015 Pebble Developer Retreat Questions? https://developer.getpebble.com/build