diff --git a/tools/ide/module.lb b/tools/ide/module.lb new file mode 100644 index 0000000000..9af1187084 --- /dev/null +++ b/tools/ide/module.lb @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2021, Raphael Lehmann +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +# ----------------------------------------------------------------------------- +def init(module): + module.name = ":ide" + module.description = "IDE Support" + + +def prepare(module, options): + return True + + +def build(env): + pass diff --git a/tools/ide/vscode/c_cpp_properties.json.in b/tools/ide/vscode/c_cpp_properties.json.in new file mode 100644 index 0000000000..7dd4dc6107 --- /dev/null +++ b/tools/ide/vscode/c_cpp_properties.json.in @@ -0,0 +1,29 @@ +{ + "configurations": [ +%% for profile, config in profiles.items() + { + "name": "{{ platform }}GCC ({{ profile | capitalize }})", + "includePath": [ + %% for path in include_paths | sort + "${workspaceFolder}/{{ path | modm.windowsify(escape_level=1) }}"{% if not loop.last%},{% endif %} + %% endfor + ], + "defines": [ + %% for define in config.cppdefines | sort + "{{ define }}"{% if not loop.last%},{% endif %} + %% endfor + ], + "compilerPath": "{{ compiler_path }}", + "compilerArgs": [ + %% for flag in config.archflags | sort + "{{ flag }}"{% if not loop.last%},{% endif %} + %% endfor + ], + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "gcc-arm" + }{% if not loop.last%},{% endif %} +%% endfor + ], + "version": 4 +} diff --git a/tools/ide/vscode/launch.json.in b/tools/ide/vscode/launch.json.in new file mode 100644 index 0000000000..57611f3535 --- /dev/null +++ b/tools/ide/vscode/launch.json.in @@ -0,0 +1,42 @@ +{ + "version": "0.2.0", + "configurations": [ +%% for config in configs + { + "name": "Debug ({{ config.profile | capitalize }}, {{ config.tool | capitalize }}, {{ partname }})", + "cwd": "${workspaceFolder}", + "executable": "{{ config.executable }}", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd", + "device": "{{ partname }}", + "runToMain": true, + %% if with_freertos + "rtos": "FreeRTOS", + %% endif + "configFiles": [ + %% for cfg in openocd_cfg + "{{ cfg }}", + %% endfor + ], + %% if with_rtt + "rttConfig": { + "enabled": true, + "address": "0x{{"%0x" % rtt_ram.start}}", + "searchSize": {{ rtt_ram.size }}, + "searchId": "modm.rtt.modm", + "polling_interval": 1, + "decoders": [ + %% for id in rtt_channels + { + "port": {{id}}, + "type": "console" + }, + %% endfor + ] + }, + %% endif + }, +%% endfor + ] +} diff --git a/tools/ide/vscode/module.lb b/tools/ide/vscode/module.lb new file mode 100644 index 0000000000..deba28bb60 --- /dev/null +++ b/tools/ide/vscode/module.lb @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2021, Raphael Lehmann +# Copyright (c) 2021, Niklas Hauser +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +import subprocess +import platform + +def init(module): + module.name = ":ide:vscode" + module.description = FileReader("module.md") + + +def prepare(module, options): + module.depends(":build") + return True + + +def build(env): + pass + + +def post_build(env): + env.outbasepath = env.relcwdoutpath(".vscode/") + + configs = [] + build_path = env.relative_outpath(env[":build:build.path"]) + for buildtool in ["scons", "make"]: + for profile in ["release", "debug"]: + if env.has_module(":build:" + buildtool): + configs.append({ + "tool": buildtool, + "profile": profile, + "executable": "".join([build_path, "/", buildtool, "-", profile, "/", env[":build:project.name"], ".elf"]), + }) + + compiler = "" + core = "" + if env[":target"].has_driver("core:cortex-m*"): + compiler += "arm-none-eabi-" + core = "Arm " + elif env[":target"].has_driver("core:avr*"): + compiler += "avr-" + core = "AVR " + compiler += "g++" + + # Find out the toolchain location + if "Windows" in platform.platform(): + # FIXME: how do I query this on Windows? + compiler_path = compiler + ".exe" + else: + compiler_path = subprocess.run("which " + compiler, shell=True, stdout=subprocess.PIPE) + compiler_path = compiler_path.stdout.decode("ascii").strip() + + flags = env.query(":build:collect_flags")(env)[None] + profiles = { + p: {f: (flags[f][""] + flags[f][p]) for f in ["cppdefines", "archflags"]} + for p in ["release", "debug"] + } + + env.substitutions = { + "configs": configs, + "partname": env[":target"].partname.upper(), + "with_freertos": env.has_module(":freertos"), + "platform": core, + "profiles": profiles, + "include_paths": env.collector_values("::path.include"), + "compiler_path": compiler_path, + # FIXME: RTT block is searched for too early. + # See https://github.com/Marus/cortex-debug/wiki/SEGGER-RTT-support#known-issues + "with_rtt": False, # env.has_module(":platform:rtt"), + } + # IntelliSense config + env.template("c_cpp_properties.json.in") + + # Only generate the tasks file for non-CMake build systems! + if configs: + env.template("tasks.json.in") + + # Debugging support for Cortex-M only + if env[":target"].has_driver("core:cortex-m*"): + # rtt_ram = env.query(":platform:cortex-m:linkerscript", {}) + # rtt_ram = rtt_ram.get("cont_ram_regions", [{"start": 0x20000000, "size": 4096}])[0] + # env.substitutions["rtt_ram"] = rtt_ram + # env.substitutions["rtt_channels"] = range(len(env.get(":platform:rtt:buffer.tx", []))) + + openocd_cfg = ["modm/openocd.cfg"] + if env.get(":build:openocd.cfg", ""): + openocd_cfg.append(env[":build:openocd.cfg"]) + env.substitutions["openocd_cfg"] = openocd_cfg + + env.template("launch.json.in") diff --git a/tools/ide/vscode/module.md b/tools/ide/vscode/module.md new file mode 100644 index 0000000000..5610ecc188 --- /dev/null +++ b/tools/ide/vscode/module.md @@ -0,0 +1,33 @@ +# Visual Studio Code (VSCode) + +[Visual Studio Code (VSCode)][VSCode] is a popular IDE with an integrated +debugger UI. + +This module provides configuration files to integrate building, debugging, +uploading and code completion into the IDE: + +- `.vscode/tasks.json`: If the `modm:build:scons` and `modm:build:make` module + are included, this file wraps the building and uploading commands by profile. + You can invoke them by Ctl+Shift+B (macOS: Cmd+Shift+B). +- `.vscode/c_cpp_properties.json`: Configures IntelliSense for better code + completion and for using the correct system headers. You need the + [C/C++ extension][] installed. +- `.vscode/launch.json`: Configures the [Cortex-Debug][] extension to start the + debugger with a single click from the IDE. + +Note that not all build system features are provided in the IDE, only the most +common. You can call all build system tools from the command line. +In addition, the `modm:build:cmake` module is supported natively by the +[CMake Tools][] extension and is therefore not wrapped. + +We recommend adding this module from the command line so that you don't +accidentally overwrite your modified files later: `lbuild build -m ::vscode`. + +Note that some configuration options may be specific to your environment (such +as the compiler path) and may not work in other environments. + + +[VSCode]: https://code.visualstudio.com/ +[C/C++ extension]: https://github.com/Microsoft/vscode-cpptools +[CMake Tools]: https://github.com/microsoft/vscode-cmake-tools +[Cortex-Debug]: https://github.com/Marus/cortex-debug#readme diff --git a/tools/ide/vscode/tasks.json.in b/tools/ide/vscode/tasks.json.in new file mode 100644 index 0000000000..3261734da9 --- /dev/null +++ b/tools/ide/vscode/tasks.json.in @@ -0,0 +1,32 @@ +{ + // See https://code.visualstudio.com/docs/editor/tasks + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ +%% for config in configs + { + "type": "shell", + "label": "Build ({{ config.profile | capitalize }})", + "command": "{{ config.tool }} build profile={{ config.profile }}", + "group": "build", + "presentation": { + "reveal": "silent", + "showReuseMessage": false + }, + "problemMatcher": "$gcc" + }, +%% endfor +%% for config in configs + { + "type": "shell", + "label": "Upload ({{ config.profile | capitalize }})", + "command": "{{ config.tool }} program profile={{ config.profile }}", + "group": "build", + "presentation": { + "reveal": "silent", + "showReuseMessage": false + } + }, +%% endfor + ] +}