Overview

This shows how to create a minimal project from an application template.

See Minimal Module/Library project for Modules or Libraries.

After following these instructions you will have a new python, C/C++ or Arduino project with support for most activities you'll need.

Applications

The new application project name is "test-123". Most of the example steps below are for a python application since it is simplest.

initial

Create a directory for the project and set up minimal git

mkdir test-123
cd test-123

# must be a git project
git init

copy from template

Clone one of the templates:

Since this example is for python, clone devpy-app-template Copy files from the template. I use the "meld" or "bcompare" diff tool, since it is very easy to copy files over and to see any differences.

# run meld in the background
meld ../devpy-app-template . &
# -- or --
bcompare ../devpy-app-template . &

Copy these files:

  • tools/install/do_install_ubu (or _macos or_msys2 version)
  • tools/requirements.txt
  • tools/zpm
  • tools/zpm_env
  • .gitignore
  • xplat.cfg

Update config files

Open the project in PyCharm or your preferred IDE.

Modify xplat.cfg: new name, description and other info:

is_module = False     << check: indicates an application
mod_tech = 'python'   << check: indicates python

mod_name = 'test-123'
doxy_desc = 'application to test 123'

# these are optional until you are ready to publish your app
author = 'Your Name'
email = 'your@email.com'
homepage_url = 'https://bitbucket.org/{mod_type}/{mod_name}/src/master'
download_url = 'https://bitbucket.org/{mod_type}/{mod_name}/get/master.zip'

setup xplat_utils

Set up the initial content for the xplat_utils repo

# need to use tools version of zpm
# this will install 
tools/zpm xplat-install

TODO add how to update .bashrc

create python virtual environment

Install any common modules for the tech you're using:

zpm env-install update

Modify tools/requirements.txt: add all modules your repo needs:

# example modules:
PyWavelets
numpy
matplotlib

Install them:

zpm install full

tweak your IDE

  • in your IDE: mark these directories as excluded:
    • out
    • venv
  • update your IDE venv, e.g. for Pycharm:
    • Configure Python Interpreter
    • Add New Interpreter
    • Add Local Interpreter
    • click Existing
    • It should show the venv as the local interpreter
    • click OK

create initial source file(s)

Add your script to the lib directory, or update using the sample from the template e.g. devpy-app-template

mkdir lib
# create your script in lib
touch lib/test1.py

Update xplat.cfg doit.mainline and doit.mainrunner to invoke the script.

If this is an arduino app, set doit.upload to True to automatically upload the app to the microcontroller.

; --------------------
; additional cfg for doit
[doit]
; set to true if implemented
implemented = True
; mainline script to run
mainline = lib/test1.py      << update this
; mainline runner, one of: bash, python, make, ruby, dart
mainrunner = 'python'        << assumes python    
; if True upload the executable to the microcontroller; assumes make target is "xx-upload"
upload = False

run it

Invoke it zpm doit. Use zpm doit arg1 arg2 if you need additional parameters

Typical output:

==== doit: run doit python: lib/test1.py  << the script in doit.mainline
---> gen files...
     rc=0   constants_version.py
     rc=0   build_info.txt
---> doit python...
hello world                 << your script's output
OK   doit python: rc=0      << the return code from your script
---> doit: overall rc=0

The lib directory should have a new file "constants_version.py". This contains the version string from xplat.cfg

The "tools/version_info.json" will contain which OS you've run this app on.

"Ubuntu 24.04 noble, Python 3.12": {
    "num_runs": 1,
    "run_date": "2026-01-11",
    "cov_pct": "97%"
}

other commands available

  • zpm check : double-check your setup is correct and generate a License.txt file
  • zpm lint: run the linter e.g. pylint. These will be copied from templates in tools/xplat_utils
    • setup.cfg
  • zpm doc : run doxygen or the documentation generator
    • copy README_template.md from the template repo and rename it to README.md
    • add your specific doc to
  • zpm ut : run unit tests. these will be copied from templates in tools/xplat_utils
    • pytest.ini
    • setup.cfg
  • zpm ver : run medver tests. These will be copied from templates in tools/xplat_utils
    • pytest.ini
    • setup.cfg
  • zpm clean : to clean up temp directories etc.

Ruby Applications

copy from template

Use this template instead devrb-app-template

# run meld in the background
meld ../devcpp-app-template . &
bcompare ../devcpp-app-template . &

Update config files

is_module = False     << check: indicates an application
mod_tech = 'ruby'     << check: indicates ruby

Modify tools/requirements.txt: add all gems your repo needs:

# example modules:
rexical

Install them:

zpm install full

create initial source file(s)

Copy the src/main.rb from the template file or create your own.

other commands

These are the same as what is used above for python. Because of the mod_tech value, they will use ruby appropriate commands e.g. rubocop for zpm lint

C/C++ Applications

copy from template

Use this template instead for C/C++ devcpp-app-template

# run meld in the background
meld ../devcpp-app-template . &
bcompare ../devcpp-app-template . &

In addition to the other files, copy this as well:

  • gen.py

Update config files

xplat.cfg has a few differences:

mod_tech = 'cpp'     << check indicates C/C++

; --------------------
; additional cfg for do_mk_gen
[do_mk_gen]
; set to true if implemented
implemented = True
; mainline script to run; if blank then not run
mainline = gen.py                 <== used to generate the Makefile(s) needed
; reset coverage                  <== can be used to confirm that gen.py content is being used
reset_coverage = False
; run with coverage
do_coverage = False
; report coverage
report_coverage = False

; --------------------
; additional cfg for do_mk_build
[do_mk_build]
; set to true if implemented
implemented = True
; makefile targets; if blank then not run
mk_targets = all

; --------------------
; additional cfg for doit
[doit]
; set to true if implemented
implemented = True
; mainline script to run
mainline = {mod_name}-run     <== the makefile target to run
; mainline runner, one of: bash, python, make, ruby, dart
mainrunner = 'make'
; if True upload the executable to the microcontroller; assumes make target is "xx-upload"
upload = False

create initial source file(s)

Copy the src/main.cpp from the template file or create your own.

generate Makefile

Start with the gen.py in the template-repo. See pyalamake for more details on using pyalamake.

from pyalamake import alamake

# === C++ tgt
tgt = alamake.create('test-123', 'cpp')  << ensure target is test-123
tgt.add_sources([
    'src/main.cpp',
])
tgt.add_include_directories(['src'])

# === generate makefile for all targets
alamake.makefile()

Generate the Makeifle

zpm mk-gen
# check the Makefile content

build the app

zpm mk-build

run it

zpm doit
zpm doit arg1 arg2   # <== for any CLI arguments

The src directory should have a new file "version.h". This contains the version string from xplat.cfg

The "tools/version_info.json" will contain which OS you've run this app on.

"Ubuntu 24.04 noble, Python 3.10": {
    "num_runs": 1,
    "run_date": "2025-01-11",
    "cov_pct": "97%"
}

Arduino Applications

copy from template

same as for C++ except:

Clone Arduino devino-app-template Also see the C/C++ section above.

# run meld in the background
meld ../devino-app-template . &
bcompare ../devino-app-template . &

In addition to the other files, copy this as well:

  • gen.py

Update config files

Also see the C/C++ section above.

Modify xplat.cfg: new name, description and other info:

mod_tech = 'arduino'     << check indicates arduino

create initial source file(s)

same as for C++, except the source file has to be Arduino compatible.

generate Makefile

  • open gen.py
from pyalamake import alamake

sh1 = alamake.create_arduino_shared()
sh1.set_boardid('nano-atmega328old')    # <== update to your board type
port = alamake.get_port('1A86:7523')    # <== use this to be cross-platform compatiable
if not port:
    sys.exit(1)
sh1.set_avrdude_port(port)

# <snip>

See C/C++ to generate the Makefile and to build the binary

run it

Turn on the Arduino; ensure it is plugged into the USB port.

zpm doit
# or since it is already built:
zpm upload

The output should indicate the arduino was flashed correctly.

The src directory should have a new file "version.h". This contains the version string from xplat.cfg

The "tools/version_info.json" will contain which OS you've run this app on.

"Ubuntu 24.04 noble, Python 3.10": {
    "num_runs": 1,
    "run_date": "2025-01-11",
    "cov_pct": "97%"
}   

- John Arrizza