PlatformIO can build the same binary code under different host systems via the single command pio run without any dependent software or requirements.
A manifest describes how to produce binaries for a particular platform under one or multiple host systems by a set of build scripts, toolchains, the settings for the most popular embedded boards, etc.
This guide explains how to write manifests, to support building for new development platforms.
Step-by-Step Manual
Choose Packages for platform
Create Manifest File platform.json
Create Build Script main.py
Finish with the Installation.
Please take a look at the source code of existing PlatformIO Development Platforms.
Some tools are the same when compiling for several platforms, for example a common compiler. A package is some tool or framework that can be used when compiling for one or multiple platforms. Even if multiple platforms use the same package, the package only needs to be downloaded once. Since each package is pre-built for the different host systems (Windows, Mac, Linux), developers can get started without first compiling the tools.
PlatformIO has a registry with pre-built packages for the most popular operating systems and you can use them in your platform manifest. Custom packages can be uploaded to the PlatformIO Registry using pio pkg publish command.
platform.json
¶Each platform definition includes a manifest file with a particular format that is parsed by PlatformIO when handling projects using that platform.
Here is an example platform.json
for the fictitious platform “myplatform”:
{
"name": "myplatform",
"title": "My Platform",
"description": "My custom development platform",
"homepage": "https://mycompany.com",
"license": "Apache-2.0",
"keywords": ["keyword_1", "keyword_N"],
"repository": {
"type": "git",
"url": "https://github.com/platformio/platform-myplatform.git"
},
"version": "0.0.0",
"frameworks": {
"%FRAMEWORK_NAME_1%": {
"package": "framework-%FRAMEWORK_NAME_1%",
"script": "builder/frameworks/%FRAMEWORK_NAME_1%.py"
},
"%FRAMEWORK_NAME_N%": {
"package": "framework-%FRAMEWORK_NAME_N%",
"script": "builder/frameworks/%FRAMEWORK_NAME_N%.py"
}
},
"packages": {
"toolchain-gccarmnoneeabi": {
"type": "toolchain",
"owner": "platformio",
"version": ">=1.40803.0,<1.40805.0"
},
"framework-%FRAMEWORK_NAME_1%": {
"type": "framework",
"optional": true,
"version": "~1.10607.0"
},
"framework-%FRAMEWORK_NAME_N%": {
"type": "framework",
"optional": true,
"version": "~1.117.0"
},
"tool-direct-vcs-url": {
"type": "uploader",
"optional": true,
"version": "https://github.com/user/repo.git"
}
}
}
main.py
¶Each platform definition must include a main.py
.
PlatformIO’s build script is based on a next-generation build tool
named SCons. PlatformIO has its own built-in
firmware builder env.BuildProgram
with deep library search. Please
see the following template as start for developing your own main.py
.
"""
Build script for test.py
test-builder.py
"""
from os.path import join
from SCons.Script import AlwaysBuild, Builder, Default, DefaultEnvironment
env = DefaultEnvironment()
# A full list with the available variables
# http://www.scons.org/doc/production/HTML/scons-user.html#app-variables
env.Replace(
AR="ar",
AS="gcc",
CC="gcc",
CXX="g++",
OBJCOPY="objcopy",
RANLIB="ranlib",
UPLOADER=join("$PIOPACKAGES_DIR", "tool-bar", "uploader"),
UPLOADCMD="$UPLOADER $SOURCES"
)
env.Append(
ARFLAGS=["..."],
ASFLAGS=["flag1", "flag2", "flagN"],
CCFLAGS=["flag1", "flag2", "flagN"],
CXXFLAGS=["flag1", "flag2", "flagN"],
LINKFLAGS=["flag1", "flag2", "flagN"],
CPPDEFINES=["DEFINE_1", "DEFINE=2", "DEFINE_N"],
LIBS=["additional", "libs", "here"],
BUILDERS=dict(
ElfToBin=Builder(
action=" ".join([
"$OBJCOPY",
"-O",
"binary",
"$SOURCES",
"$TARGET"]),
suffix=".bin"
)
)
)
# The source code of "platformio-build-tool" is here
# https://github.com/platformio/platformio-core/blob/develop/platformio/builder/tools/platformio.py
#
# Target: Build executable and linkable firmware
#
target_elf = env.BuildProgram()
#
# Target: Build the .bin file
#
target_bin = env.ElfToBin(join("$BUILD_DIR", "firmware"), target_elf)
#
# Target: Upload firmware
#
upload = env.Alias(["upload"], target_bin, "$UPLOADCMD")
AlwaysBuild(upload)
#
# Target: Define targets
#
Default(target_bin)
Using the “myplatform” platform example above:
Create a platforms
directory in core_dir if it
doesn’t exist.
Create a myplatform
directory in platforms
Copy the platform.json
and builder/main.py
files to the myplatform
directory.
Search the available platforms via the pio platform search command. You
should see the new myplatform
platform.
Install the myplatform
platform via the pio platform install command.
Now, you can use myplatform
as value for the platform
option in “platformio.ini” (Project Configuration File).
You can publish a development platform to the PlatformIO Trusted Registry using pio pkg publish command. Other developers will be able to install it. Every time when you modify a source code of a development platform you will need to increment the “version” field in “platform.json” manifest and re-publish again.
If the published development platform has an issue and you would like to remove it from the PlatformIO Trusted Registry, please use pio pkg unpublish command.