diff options
Diffstat (limited to 'util/ide-config.sh')
-rwxr-xr-x | util/ide-config.sh | 475 |
1 files changed, 0 insertions, 475 deletions
diff --git a/util/ide-config.sh b/util/ide-config.sh deleted file mode 100755 index 25edca2407..0000000000 --- a/util/ide-config.sh +++ /dev/null @@ -1,475 +0,0 @@ -#!/bin/bash -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -# Usage: ./util/ide-config.sh vscode all all:RO | tee .vscode/c_cpp_properties.json -# This tool needs to be run from the base ec directory. -# -# Future works should be put towards adding new IDE generators and adding -# mechanism for passing IDE specific parameters to the IDE generator. - -DEFAULT_IMAGE=RW -INDENT_WIDTH=${INDENT_WIDTH:-1} -INDENT_CHAR=${INDENT_CHAR:-$'\t'} -INCLUDES_DROP_ROOT=${INCLUDES_DROP_ROOT:-false} -PARALLEL_CACHE_FILL=${PARALLEL_CACHE_FILL:-true} -FORCE_INCLUDE_CONFIG_H=${FORCE_INCLUDE_CONFIG_H:-false} -# JOB_BATCH_SIZE is the number of jobs allowed to spawn at any given point. -# This is an inefficient manner of resource management, but at least it -# throttles process creation. Due to the low utilization or each job, -# multiply the number of real processors by 2. -JOB_BATCH_SIZE=${JOB_BATCH_SIZE:-$(($(nproc) * 2))} - -MAKE_CACHE_DIR="" - -init() { - MAKE_CACHE_DIR=$(mktemp -t -d ide-config.XXXX) - mkdir -p "${MAKE_CACHE_DIR}/defines" - mkdir -p "${MAKE_CACHE_DIR}/includes" - trap deinit EXIT -} - -deinit() { - rm -rf "${MAKE_CACHE_DIR}" -} - -usage() { - cat <<-HEREDOC - Usage: ide-config.sh <vscode|eclipse> [BOARD:IMAGE] [BOARD:IMAGE...] - Generate a C language configuration for a given IDE and EC board. - - Examples: - ide-config.sh vscode all:RW all:RO | tee .vscode/c_cpp_properties.json - ide-config.sh vscode nocturne # implicitly :RW - ide-config.sh vscode nocturne_fp:RO - ide-config.sh vscode nocturne:RO hatch:RW - ide-config.sh vscode all # implicitly :RW - ide-config.sh eclipse nocturne_fp > ~/Downloads/nocturne_fp-RW.xml - HEREDOC -} - -# Usage: iprintf <indent-level> <printf-fmt> [printf-args...] -iprintf() { - local level=$1 - shift - - local n=$((INDENT_WIDTH*level)) - if [[ $n -ne 0 ]]; then - eval printf '"${INDENT_CHAR}%.0s"' "{1..$n}" - fi - # shellcheck disable=SC2059 - printf "$@" - return $? -} - -# Usage: parse-cfg-board <cfg-string> -# -# Example: parse-cfg-board nocturne:RW -parse-cfg-board() { - local cfg=$1 - # Remove possible :RW or :RO - local board=${cfg%%:*} - if [[ -z ${board} ]]; then - return 1 - fi - echo "${board}" -} - -# Usage: parse-cfg-image <cfg-string> -# -# Example: parse-cfg-image nocturne:RW -# Example: parse-cfg-image nocturne -parse-cfg-image() { - local cfg=$1 - - local board - if ! board=$(parse-cfg-board "${cfg}"); then - return 1 - fi - # Remove known board part - cfg=${cfg#${board}} - cfg=${cfg#":"} - # Use default image if none set - cfg=${cfg:-${DEFAULT_IMAGE}} - - case ${cfg} in - RW|RO) - echo "${cfg}" - return 0 - ;; - *) - return 1 - ;; - esac -} - -# Usage: make-defines <board> <RO|RW> -make-defines() { - local board=$1 - local image=$2 - - local cache="${MAKE_CACHE_DIR}/defines/${board}-${image}" - - if [[ ! -f "${cache}" ]]; then - make print-defines BOARD="${board}" BLD="${image}" >"${cache}" - fi - - cat "${cache}" -} - -# Usage: make-includes <board> <RO|RW> -# -# Rerun a newline separated list of include directories relative to the ec's -# root directory. -make-includes() { - local board=$1 - local image=$2 - - local cache="${MAKE_CACHE_DIR}/includes/${board}-${image}" - - if [[ ! -f "${cache}" ]]; then - make print-includes BOARD="${board}" BLD="${image}" \ - | xargs realpath --relative-to=. \ - | { - if [[ "${INCLUDES_DROP_ROOT}" == true ]]; then - grep -v "^\.$" - else - cat - fi - } >"${cache}" - fi - - cat "${cache}" -} - -# Usage: make-boards -make-boards() { - local cache="${MAKE_CACHE_DIR}/boards" - - if [[ ! -f "${cache}" ]]; then - make print-boards >"${cache}" - fi - - cat "${cache}" -} - -# Usage: <newline-list> | join <left> <right> <separator> -# -# JSON: includes nocturne_fp RW | join '"' '"' ',\n' -# C: includes nocturne_fp RW | join '"' '",' '\n' -join() { - local left=$1 - local right=$2 - local sep=$3 - - local first=true - while read -r line; do - # JSON is ridiculous for not allowing a trailing , - if [[ "${first}" == true ]]; then - first=false - else - printf "%b" "${sep}" - fi - printf "%b%s%b" "${left}" "${line}" "${right}" - done - echo -} - -# Usage: <content> | encap <header> <footer> [indent] -# -# Encapsulate the content from stdin with a header, footer, and indentation. -encap() { - local header=$1 - local footer=$2 - local indent=${3:-0} - - iprintf "${indent}" "%b" "${header}" - while IFS="" read -r line; do - iprintf $((1+indent)) "%s\n" "${line}" - done - iprintf "${indent}" "%b" "${footer}" -} - -########################################################################## - -# Usage: vscode [cfg...] -# -# Generate the content for one c_cpp_properties.json that contains -# multiple selectable configurations for each board-image pair. -# In VSCode you can select the config in the bottom right, next to the -# "Select Language Mode". You will only see this option when a C/C++ file -# is open. Additionally, you can select a configuration by pressing -# Ctrl-Shift-P and selecting the "C/C++ Select a Configuration..." option. -vscode() { - local first=true - { - for cfg; do - local board image - if ! board=$(parse-cfg-board "${cfg}"); then - echo "Failed to parse board from cfg '${cfg}'" - return 1 - fi - if ! image=$(parse-cfg-image "${cfg}"); then - echo "Failed to parse image from cfg '${cfg}'" - return 1 - fi - { - printf '"name": "%s",\n' "${board}:${image}" - make-includes "${board}" "${image}" \ - | join '"' '"' ',\n' \ - | encap '"includePath": [\n' '],\n' - make-defines "${board}" "${image}" \ - | join '"' '"' ',\n' \ - | encap '"defines": [\n' '],\n' - - if [[ "${FORCE_INCLUDE_CONFIG_H}" == true ]]; then - echo '"include/config.h"' \ - | encap '"forcedInclude": [\n' '],\n' - fi - - echo '"compilerPath": "/usr/bin/arm-none-eabi-gcc",' - # echo '"compilerArgs": [],' - # The macro __STDC_VERSION__ is 201710L, which corresponds to c18. - # VSCode doesn't have a C18 option, so go with C17. Since we seem - # to use a lot of GNUC features, let's go with gnu17 instead of c17. - echo '"cStandard": "gnu17",' - # echo '"cppStandard": "c++17",' - echo '"intelliSenseMode": "gcc-x64"' - } | { - # A single named configuration - if [[ "${first}" == true ]]; then - encap '{\n' '}' - else - encap ',\n{\n' '}' - fi - } - first=false - done - echo - } \ - | { - encap '"configurations": [\n' '],\n' - echo '"version": 4' - } \ - | encap '{\n' '}\n' -} - -# Usage: eclipse-cdt-import [cfg...] -# -# * Add odd EC "File Types" -# - *.tasklist *.mocklist *.testlist *.irqlist "C Header File" -# - *.inc "C Header File" -# - gpio.wrap "C Header File" -# * Enable the indexer to follow current build configuration -# - Enable "Index all header variants" -# - Enable "Use active build configuration" (ensure this options sticks) -# - Probably bump up the Cache Limit->"Absolute Limit" -# * Remove default system includes -# - Depending on your eclipse toolchain configuration, it may be possible -# to remove the standard C headers. -# This helps satisfy the EC's -nostdinc usage. -eclipse-cdt-import() { - if [[ $# -gt 1 ]]; then - echo "Error - eclipse generator can only process one board cfg" >&2 - return 1 - fi - - local cfg=$1 - local board image - - board=$(parse-cfg-board "${cfg}") - image=$(parse-cfg-image "${cfg}") - - local includes - # Grab workspace/project local paths - includes+="$(make-includes "${board}" "${image}" | grep -v "^\.\." \ - | join '<includepath workspace_path="true">' '</includepath>' '\n\t\t\t')" - # Add separator manually - includes+="$(printf "\n\t\t\t")" - # Grab external paths (wil start with .. because forced relative) - # shellcheck disable=SC2016 - includes+="$(make-includes "${board}" "${image}" | grep "^\.\." \ - | join '<includepath>${ProjDirPath}/' '</includepath>' '\n\t\t\t')" - - local macros - macros="$( - while read -r name value; do - { - join '<name>' '</name>' '' <<<"${name}" - join '<value>' '</value>' '' <<<"${value}" - } | encap '<macro>\n' '</macro>\n' 3 - done < <(make-defines "${board}" "${image}" | tr '=' '\t') - )" - - cat <<EOF -<?xml version="1.0" encoding="UTF-8"?> -<!-- Generated for ${board}:${image} --> -<cdtprojectproperties> - <section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths"> - <!-- Start Normal CDT --> - <language name="holder for library settings"></language> - - <language name="Assembly"> - ${includes} - </language> - - <language name="GNU C++"> - ${includes} - </language> - - <language name="GNU C"> - ${includes} - </language> - <!-- End Normal CDT --> - - <!-- Start CDT Cross/Embedded --> - <language name="C Source File"> - ${includes} - </language> - - <language name="Object File"> - </language> - - <language name="Assembly Source File"> - ${includes} - </language> - <!-- End CDT Cross/Embedded --> - </section> - - <section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros"> - <!-- Start Normal CDT --> - <language name="holder for library settings"></language> - - <language name="Assembly"> -${macros} - </language> - - <language name="GNU C++"> -${macros} - </language> - - <language name="GNU C"> -${macros} - </language> - <!-- End Normal CDT --> - - <!-- Start CDT Cross/Embedded --> - <language name="C Source File"> -${macros} - </language> - - <language name="Object File"> - </language> - - <language name="Assembly Source File"> -${macros} - </language> - <!-- End CDT Cross/Embedded --> - </section> -</cdtprojectproperties> -EOF -} - -# Usage: main <ide> [cfgs...] -main() { - # Disaply help if no args - if [[ $# -lt 1 ]]; then - usage - exit 1 - fi - # Search for help flag - for flag; do - case ${flag} in - help|--help|-h) - usage - exit 0 - ;; - esac - done - - local ide=$1 - shift - - # Expand possible "all" cfgs - local board image - local -a cfgs=( ) - for cfg; do - # We parse both board and image to pre-sanatize the input - if ! board=$(parse-cfg-board "${cfg}"); then - echo "Failed to parse board from cfg '${cfg}'" >&2 - exit 1 - fi - if ! image=$(parse-cfg-image "${cfg}"); then - echo "Failed to parse image from cfg '${cfg}'" >&2 - exit 1 - fi - # Note "all:*" could be specified multiple times for RO and RW - # Note "all:*" could be specified with other specific board:images - if [[ "${board}" == all ]]; then - local -a allboards=( ) - mapfile -t allboards < <(make-boards) - cfgs+=( "${allboards[@]/%/:${image}}" ) - else - cfgs+=( "${cfg}" ) - fi - done - - # Technically, we have not sanitized the cfgs generated from - # "all" expression. - - # Make configs unique (and sorted) - mapfile -t cfgs < <(echo "${cfgs[@]}" | tr ' ' '\n' | sort -u) - echo "# Generating a config for the following board:images: " >&2 - echo "${cfgs[@]}" | tr ' ' '\n' | sort -u | column >&2 - - # Prefill the make cache in parallel - # This is important because each make request take about 700ms. - # When running on all boards, this could result in (127*2)*700ms = 3mins. - if [[ "${PARALLEL_CACHE_FILL}" == true ]]; then - echo "# Fetching make defines and includes. Please wait." >&2 - - # We run into process limits if we launch all processes at the - # same time, so we must split them in half. - # This need some jobserver management. - - # Run make for RWs and ROs - local -i jobs=0 - for cfg in "${cfgs[@]}"; do - if ! board="$(parse-cfg-board "${cfg}")"; then - echo "Failed to parse board from cfg '${cfg}'" >&2 - exit 1 - fi - if ! image="$(parse-cfg-image "${cfg}")"; then - echo "Failed to parse image from cfg '${cfg}'" >&2 - exit 1 - fi - make-defines "${board}" "${image}" >/dev/null & - ((++jobs % JOB_BATCH_SIZE == 0)) && wait - make-includes "${board}" "${image}" >/dev/null & - ((++jobs % JOB_BATCH_SIZE == 0)) && wait - done - wait - fi - - # Run the IDE's generator - case "${ide}" in - vscode) - vscode "${cfgs[@]}" || exit $? - ;; - eclipse) - eclipse-cdt-import "${cfgs[@]}" || exit $? - ;; - *) - echo "Error - IDE '${ide}' is an unsupported." >&2 - exit 1 - ;; - esac -} - -init - -# Only start if not being sourced -if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then - main "$@" -fi |