# Custom Development Platforms

PlatformIO can build the same binary code under different host systems via the single command platformio 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

1. Choose Packages for platform

2. Create Manifest File platform.json

3. Create Build Script main.py

4. Finish with the Installation.

Contents

- Custom Development Platforms

  - Packages

  - Manifest File `platform.json`

  - Build Script `main.py`

  - Installation

  - Examples

## Packages

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. These packages are stored in the super-fast and reliably CDN storage provided by JFrog Bintray.

Each platform definition must define `packageRepositories` to link to package manifest files that lists how PlatformIO can download the used packages. To use the pre-built packages, include http://dl.platformio.org/packages/manifest.json in the `packageRepositories` list. Platform definitions can also use custom packages.

## Manifest File `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",
      "url": "http://example.com",
      "homepage": "https://platformio.org/platforms/myplatform",
      "license": "Apache-2.0",
      "engines": {
        "platformio": "~3.0.0"
      },
      "repository": {
        "type": "git",
        "url": "https://github.com/platformio/platform-myplatform.git"
      },
      "version": "0.0.0",
      "packageRepositories": [
        "https://dl.bintray.com/platformio/dl-packages/manifest.json",
        "http://dl.platformio.org/packages/manifest.json",
        {
          "my_custom_package": [
            {
              "url": "http://dl.example.com/my_custom_package-darwin_x86_64-1.2.3.tar.gz",
              "sha1": "bb7ddac56a314b5cb1926cc1790ae4de3a03e65c",
              "version": "1.2.3",
              "system": [
                  "darwin_x86_64",
                  "darwin_i386"
              ]
            },
            {
              "url": "http://dl.example.com/my_custom_package-linux_aarch64-1.2.3.tar.gz",
              "sha1": "127ddac56a314b5cb1926cc1790ae4de3a03e65c",
              "version": "1.2.3",
              "system": "linux_aarch64"
            }
          ],
          "framework-%FRAMEWORK_NAME_1%": [
            {
              "url": "http://dl.example.com/packages/framework-%FRAMEWORK_NAME_1%-1.10607.0.tar.gz",
              "sha1": "adce2cd30a830d71cb6572575bf08461b7b73c07",
              "version": "1.10607.0",
              "system": "*"
            }
          ]
        }
      ],
      "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",
          "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"
        }
      },
      "pythonPackages": {
        "pypi-pkg-1": "1.2.3",
        "pypi-pkg-2": ">=2.3, <3"
      }
    }

## Build Script `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)

## Installation

Using the “myplatform” platform example above:

1. Create a `platforms` directory in core_dir if it doesn’t exist.

2. Create a `myplatform` directory in `platforms`

3. Copy the `platform.json` and `builder/main.py` files to the `myplatform` directory.

4. Search the available platforms via the platformio platform search command. You should see the new `myplatform` platform.

5. Install the `myplatform` platform via the platformio platform install command.

Now, you can use `myplatform` as value for the platform option in “platformio.ini” (Project Configuration File).

## Examples

Please take a look at the source code of existing PlatformIO Development Platforms.