diff --git a/README.md b/README.md index dc7e6b4..abda2a2 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ We've organized this README into sections, to simplify navigation. 1. [Adding a New Dependency to OpenUxAS](#new-dependency) 4. [Troubleshooting](#troubleshooting) 1. [Verbosity](#verbosity) +5. [IDE Support](#ides) + 1. [VS Code](#vscode) + There are three components discussed in this README: @@ -542,3 +545,27 @@ Similarly, if a library or header file is not found during the build of OpenUxAS Anod and most of the other scripts provided in this repository offer more verbose logging. In general, passing additional `-v` flags will make logging more verbose. For example, for the most verbose logging, you can pass `-vv` to most scripts. + +# 5. IDE Support + +## 5.1. VS Code + +[Visual Studio Code](#https://code.visualstudio.com/) (VS Code) is an open-source, lightweight IDE supporting a large and growing number of langauges. +VS Code can be used to edit C and C++ code. +VS Code also provides feedback to developers of potential problems with their code and offers support for navigating code. + +To take full advantage of VS Code's capabilities, you must provide VS Code with the set of paths that should be searched to resolve header files included for project dependencies. +These settings are placed in a special JSON file named `c_cpp_properties.json` in the (typically hidden) directory `.vscode`. + +When using anod to supply OpenUxAS dependencies, this means that you must provide VS Code with paths into the anod sandbox for each OpenUxAS dependency. +To simplify this process, anod includes a command `configure-vscode` that will generate the `c_cpp_properties.json` and, by default, place it in the expected location: under `develop/OpenUxAS/.vscode`. + +If you used `anod devel-setup uxas` to configure your bootstrap environment for OpenUxAS development, you don't have to do anything extra: anod has already created `develop/OpenUxAS/.vscode/c_cpp_properties.json` for you. + +If you manually configured your bootstrap environment for OpenUxAS development and you want to use VS Code for OpenUxAS development, you should run `anod configure-vscode` like this: + + ~/bootstrap$ ./anod configure-vscode --out /path/to/OpenUxAS/.vscode/c_cpp_properties.json + +You can also have anod print the file to STDOUT and redirect it elsewhere, like this: + + ~/bootstrap$ ./anod configure-vscode --stdout > /path/to/OpenUxAS/.vscode/c_cpp_properties.json diff --git a/anod b/anod index 73931e3..12a392a 100755 --- a/anod +++ b/anod @@ -49,7 +49,7 @@ if __name__ == "__main__": command_arg = m.argument_parser.add_argument( "command", - choices=["build", "printenv", "devel-setup"], + choices=["build", "printenv", "devel-setup", "configure-vscode"], help="the subcommand to be run.", ) @@ -82,6 +82,11 @@ if __name__ == "__main__": exit(do_devel_setup(m)) + elif m.args.command == "configure-vscode": + from lib.anod_configure_vscode import do_configure + + exit(do_configure(m)) + else: # cannot happen exit(4) diff --git a/lib/anod_configure_vscode.py b/lib/anod_configure_vscode.py new file mode 100644 index 0000000..61c9ae6 --- /dev/null +++ b/lib/anod_configure_vscode.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +"""Anod vscode configurator.""" + +from __future__ import annotations + +from lib.anod.util import check_common_tools, create_anod_context, create_anod_sandbox +from lib.anod.paths import SPEC_DIR, SBX_DIR + +from e3.main import Main +from e3.env import BaseEnv + +import logging +import os +import pathlib + + +# Template for the c_cpp_properties.json file we generate +C_CPP_PROPERTIES_JSON = """\ +{ + "configurations": [ + { + "name": "OpenUxAS", + "includePath": [ + "${workspaceFolder}/**", + "%s" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "gnu11", + "cppStandard": "gnu++11", + "intelliSenseMode": "gcc-x64" + } + ], + "version": 4 +} +""" + +DEFAULT_PATH = "develop/OpenUxAS/.vscode/c_cpp_properties.json" + + +def do_configure(m: Main, set_prog: bool = True) -> int: + """Create the configuration file for VS Code.""" + if set_prog: + m.argument_parser.prog = m.argument_parser.prog + " configure-vscode" + + m.argument_parser.add_argument( + "spec_name", + nargs="?", + help="spec for which the VS Code configuration should be generated", + default="uxas", + ) + + m.argument_parser.add_argument("--qualifier", help="optional qualifier") + m.argument_parser.add_argument( + "--sandbox-dir", + help="directory in which build artifacts are stored", + default=SBX_DIR, + ) + + output_group = m.argument_parser.add_mutually_exclusive_group() + output_group.add_argument( + "--stdout", + help="print the configuration file to STDOUT", + action="store_true", + default=False, + ) + + output_group.add_argument( + "--out", help="specify the output file", default=DEFAULT_PATH + ) + + m.parse_args() + + # Disable logging messages except errors + logging.getLogger("").setLevel(logging.ERROR) + + check_common_tools() + + ac = create_anod_context(SPEC_DIR) + sbx = create_anod_sandbox(m.args.sandbox_dir, SPEC_DIR) + + anod_instance = ac.add_anod_action( + name=m.args.spec_name, + primitive="build", + qualifier=m.args.qualifier, + sandbox=sbx, + upload=False, + env=BaseEnv.from_env(), + ).anod_instance + + if hasattr(anod_instance, "build_setenv"): + anod_instance.build_setenv() + + config_content = C_CPP_PROPERTIES_JSON % '",\n "'.join( + os.environ["CPLUS_INCLUDE_PATH"].split(os.pathsep) + ) + + if m.args.stdout: + print(config_content) + else: + abspath = os.path.abspath(m.args.out) + + if not os.path.exists(os.path.dirname(abspath)): + pathlib.Path(os.path.dirname(abspath)).mkdir(parents=True) + + open(abspath, "w").write(config_content) + + return 0 + else: + logging.error( + f"Cannot generate a VS Code configuration for {m.args.spec_name} " + "because it does not export a build_setenv" + ) + + return 1 diff --git a/lib/anod_devel_setup.py b/lib/anod_devel_setup.py index 4dd53b6..c6cdc22 100644 --- a/lib/anod_devel_setup.py +++ b/lib/anod_devel_setup.py @@ -191,6 +191,10 @@ def do_devel_setup(m: Main, set_prog: bool = True) -> int: "OpenUxAS", args.uxas_remote, args.uxas_refspec, args.uxas_clone_dir ) + from lib.anod_configure_vscode import do_configure + + return do_configure(m) + if "lmcp" in args.component: update_yaml(REPOSITORIES_YAML_PATH, LMCP_YAML_KEY, args.lmcp_clone_dir) check_out( diff --git a/lib/anod_printenv.py b/lib/anod_printenv.py index ffbe3a9..fad55a0 100644 --- a/lib/anod_printenv.py +++ b/lib/anod_printenv.py @@ -13,6 +13,7 @@ import logging import os + # Help users who can't remember to use eval. BANNER = """ # ---------------------------------------------------------------------------- @@ -31,9 +32,10 @@ def do_printenv(m: Main, set_prog: bool = True) -> int: """Print the environment for the given spec.""" if set_prog: m.argument_parser.prog = m.argument_parser.prog + " printenv" + m.argument_parser.add_argument( "spec_name", - help="spec to build. This is " + help="spec for which environment should be printed. This is " "the basename of an .anod file (without the extension)", ) m.argument_parser.add_argument("--qualifier", help="optional qualifier")