-
Notifications
You must be signed in to change notification settings - Fork 1.1k
NXP backend: Building MCUXpresso example #21140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jirioc
wants to merge
1
commit into
pytorch:main
Choose a base branch
from
nxp-upstream:EIEX-1006-building-mcuxpresso-example-from-oss-executorch
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| # Using the MCUXpresso Example | ||
|
|
||
| This example demonstrates how to build and run the ExecuTorch CIFARNet application for the NXP RT700 platform using the MCUXpresso SDK and the GNU Arm Embedded Toolchain. Before building the project, make sure that all required dependencies are installed and that the necessary environment variables are configured correctly. | ||
|
|
||
| ## 1. Install the Arm GNU Toolchain | ||
|
|
||
| First, download the Arm GCC cross-compilation toolchain that is supported by the RT700 platform: | ||
|
|
||
| ```text | ||
| https://developer.arm.com/-/media/Files/downloads/gnu/15.2.rel1/binrel/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-eabi.tar.xz | ||
| ``` | ||
|
|
||
| After extracting the archive, create an environment variable called `ARMGCC_DIR` that points to the root directory of the toolchain installation. The build scripts use this variable to locate the compiler, linker, and other required tools. | ||
|
|
||
| Example on Linux: | ||
|
|
||
| ```bash | ||
| export ARMGCC_DIR=/path/to/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-eabi | ||
| ``` | ||
|
|
||
| To verify the installation, you can run: | ||
|
|
||
| ```bash | ||
| $ARMGCC_DIR/bin/arm-none-eabi-gcc --version | ||
| ``` | ||
|
|
||
| The command should print the installed compiler version. | ||
|
|
||
| ## 2. Download the MCUXpresso SDK | ||
|
|
||
| Next, download MCUXpresso SDK version **26.06** for the RT700 device family: | ||
|
|
||
| ```text | ||
| https://mcuxpresso.nxp.com/builder?hw=MIMXRT700-EVK | ||
| ``` | ||
|
|
||
| When generating the SDK package, make sure that you select: | ||
|
|
||
| - **Toolchain:** ARMGCC | ||
| - **SDK Layout:** Classic Layout | ||
| - **Target Board:** MIMXRT700-EVK | ||
|
|
||
| After extracting the SDK package, configure the `SdkRootDirPath` environment variable to point to the SDK root directory. | ||
|
|
||
| Example on Linux: | ||
|
|
||
| ```bash | ||
| export SdkRootDirPath=/path/to/SDK_26_06 | ||
| ``` | ||
|
|
||
| The build system relies on this variable to locate board support packages, middleware components, startup code, linker scripts, and device-specific libraries. | ||
|
|
||
| ## 3. Prepare the Model Header File | ||
|
|
||
| Before building the application, a compiled model must be provided as a C header file named `model_pte.h` and placed alongside the build script. The `prepare_model.sh` script automates this process. It installs the required Python packages, compiles the CIFARNet model using the NXP ExecuTorch backend, and generates the `model_pte.h` header from the resulting `.pte` file. | ||
|
|
||
| > **Important:** The MCUXpresso SDK package includes a pre-built CIFARNet model and a set of Neutron libraries, but this build flow deliberately does **not** use either of them. Instead, the `prepare_model.sh` script installs the exact eiq-neutron-sdk version that was verified with the current ExecuTorch release, recompiles the CIFARNet model from scratch using that SDK, and later the linker picks the matching Neutron libraries from the same installation. This ensures that the ExecuTorch AoT, the model bytecode, the Neutron driver, the Neutron firmware, and the ExecuTorch runtime are all in sync. | ||
|
|
||
| ## 4. Build the Application | ||
|
|
||
| Once the environment variables have been configured and `model_pte.h` is present in the project directory, set the `NEUTRON_LIB_DIR` variable to the directory that contains the Neutron static libraries shipped with the eiq-neutron-sdk: | ||
|
|
||
| ```bash | ||
| export NEUTRON_LIB_DIR=/path/to/eiq_neutron_sdk/libs | ||
| ``` | ||
|
|
||
| The build script expects the following libraries to exist in that directory: | ||
|
|
||
| - `libNeutronDriver.a` | ||
| - `libNeutronFirmware.a` | ||
|
|
||
| Then build the project by executing the provided script: | ||
|
|
||
| ```bash | ||
| cd examples/nxp/mcuxpresso/imxrt700/executorch_cifarnet | ||
| ./build_example.sh | ||
| ``` | ||
|
|
||
| The script validates all required inputs, configures CMake, compiles the source code, links the application, and generates the executable image: | ||
|
|
||
| ```text | ||
| executorch_cifarnet.elf | ||
| ``` | ||
|
|
||
| If the build completes successfully, the ELF file will be available in the `cmake-out` build output directory and ready for programming onto the target board. | ||
|
|
||
| ## 5. Flash the Application | ||
|
|
||
| The generated application can be programmed onto the RT700 device using SEGGER J-Link tools. | ||
|
|
||
| ### Linux | ||
|
|
||
| ```bash | ||
| echo "loadfile executorch_cifarnet.elf" | \ | ||
| /opt/SEGGER/JLink_V796k/JLinkExe \ | ||
| -IF SWD \ | ||
| -speed auto \ | ||
| -Device MIMXRT798S_M33_0 | ||
| ``` | ||
|
|
||
| Before flashing, ensure that: | ||
|
|
||
| - The board is powered on. | ||
| - The J-Link debugger is connected to the target. | ||
| - The SWD interface is available and correctly wired. | ||
| - No other debugging application is currently using the J-Link connection. | ||
|
|
||
| The programming process typically takes only a few seconds. Once the image has been loaded successfully, the application can be started directly from flash memory. | ||
|
|
||
| ## 6. Running the Example | ||
|
|
||
| After the firmware is programmed, reset the board and open a serial terminal connected to the device's debug UART interface. The application will initialize the hardware, load the embedded CIFARNet model, and begin performing image inference. | ||
|
|
||
| During execution, inference results and diagnostic messages are printed to the terminal. The included demonstration image contains a cat, and the model is expected to classify the image accordingly. | ||
|
|
||
| A successful run produces output similar to the following: | ||
|
|
||
|  | ||
|
|
||
| This example serves as a basic validation that the ExecuTorch runtime, model integration, SDK configuration, and hardware platform are all functioning correctly. It can also be used as a starting point for evaluating custom neural network models and experimenting with on-device machine learning workloads on the RT700 platform. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
151 changes: 151 additions & 0 deletions
151
examples/nxp/mcuxpresso/imxrt700/executorch_cifarnet/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| # Copyright 2026 NXP | ||
| # | ||
| # This source code is licensed under the BSD-style license found in the | ||
| # LICENSE file in the root directory of this source tree. | ||
|
|
||
| cmake_minimum_required(VERSION 3.10.0) | ||
|
|
||
| # THE VERSION NUMBER | ||
| set(MCUXPRESSO_CMAKE_FORMAT_MAJOR_VERSION 2) | ||
| set(MCUXPRESSO_CMAKE_FORMAT_MINOR_VERSION 0) | ||
|
|
||
| set(CMAKE_EXECUTABLE_LIBRARY_PREFIX) | ||
| set(CMAKE_EXECUTABLE_LIBRARY_SUFFIX) | ||
|
|
||
| # CURRENT DIRECTORY | ||
| set(ProjDirPath ${CMAKE_CURRENT_SOURCE_DIR}) | ||
|
|
||
| set(EXECUTABLE_OUTPUT_PATH ${ProjDirPath}/${CMAKE_BUILD_TYPE}) | ||
| set(LIBRARY_OUTPUT_PATH ${ProjDirPath}/${CMAKE_BUILD_TYPE}) | ||
|
|
||
| # Skip link step during compiler check (bare-metal cross-compilation). | ||
| set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) | ||
|
|
||
| project(executorch_cifarnet) | ||
|
|
||
| enable_language(ASM) | ||
|
|
||
| set(MCUX_BUILD_TYPES flash_debug flash_release) | ||
|
|
||
| set(MCUX_SDK_PROJECT_NAME executorch_cifarnet.elf) | ||
|
|
||
| set(EXECUTORCH_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..) | ||
|
|
||
| # CPU and FPU flags required for Cortex-M33 with single-precision FPU. | ||
| set(CPU_FLAGS "-mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16") | ||
| set(CPU_DEFINES | ||
| "-DCPU_MIMXRT798SGFOA_cm33_core0 -DCPU_MIMXRT798SGFOB_cm33_core0 \ | ||
| -DMIMXRT798S_cm33_core0_SERIES -DMCUXPRESSO_SDK \ | ||
| -D__STARTUP_INITIALIZE_NONCACHEDATA -D__STARTUP_CLEAR_BSS \ | ||
| -DDSP_IMAGE_COPY_TO_RAM=1 -DBOOT_HEADER_ENABLE=1 \ | ||
| -DEIQ_EXAMPLE_HSRUN_CLOCK -DMCUX_META_BUILD \ | ||
| -DPRINTF_ADVANCED_ENABLE=1 -DPRINTF_FLOAT_ENABLE=1 -DNO_HEAP_USAGE=1 \ | ||
| -DSDK_DEBUGCONSOLE=1 -DSDK_I2C_BASED_COMPONENT_USED=1" | ||
| ) | ||
| set(CMAKE_C_FLAGS | ||
| "${CMAKE_C_FLAGS} ${CPU_FLAGS} ${CPU_DEFINES} -fno-common -ffunction-sections -fdata-sections -fno-builtin -mapcs -std=gnu99" | ||
| ) | ||
| set(CMAKE_CXX_FLAGS | ||
| "${CMAKE_CXX_FLAGS} ${CPU_FLAGS} ${CPU_DEFINES} -fno-common -ffunction-sections -fdata-sections -fno-builtin -mapcs -fno-rtti -fno-exceptions" | ||
| ) | ||
| set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${CPU_FLAGS} ${CPU_DEFINES}") | ||
| set(CMAKE_EXE_LINKER_FLAGS | ||
| "${CMAKE_EXE_LINKER_FLAGS} ${CPU_FLAGS} -fno-common -ffunction-sections -fdata-sections -fno-builtin -mapcs -Wl,--gc-sections -Wl,-static -specs=nano.specs -specs=nosys.specs -T\"${SdkRootDirPath}/examples/_boards/mimxrt700evk/eiq_examples/executorch_cifarnet/cm33_core0/gcc/MIMXRT798Sxxxx_cm33_core0_flash.ld\" -static" | ||
| ) | ||
|
|
||
| add_executable( | ||
| ${MCUX_SDK_PROJECT_NAME} | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/flash_config/flash_config.c | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/eiq_examples/executorch_cifarnet/cm33_core0/hardware_init.c | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/eiq_examples/executorch_cifarnet/cm33_core0/pin_mux.c | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/board.c | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/pmic_support.c | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/common/clock/cm33_core0/clock_config.c | ||
| ${SdkRootDirPath}/examples/eiq_examples/executorch_cifarnet/main.cpp | ||
| ${SdkRootDirPath}/examples/eiq_examples/executorch_cifarnet/RegisterKernels.cpp | ||
| ${SdkRootDirPath}/examples/eiq_examples/common/timer.c | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/startup_MIMXRT798S_cm33_core0.c | ||
| ${EXECUTORCH_ROOT_DIR}/backends/nxp/runtime/NeutronBackend.cpp | ||
| ${SdkRootDirPath}/middleware/tfm/tf-m/platform/ext/common/syscalls_stub.c | ||
| # Device-level drivers (clock, power, reset, system init). | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/drivers/fsl_clock.c | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/drivers/fsl_power.c | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/drivers/fsl_reset.c | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/system_MIMXRT798S_cm33_core0.c | ||
| # Common ARM driver (provides SDK_DelayAtLeastUs). | ||
| ${SdkRootDirPath}/drivers/common/fsl_common_arm.c | ||
| # Peripheral drivers. | ||
| ${SdkRootDirPath}/drivers/cache/xcache/fsl_cache.c | ||
| ${SdkRootDirPath}/drivers/lpflexcomm/fsl_lpflexcomm.c | ||
| ${SdkRootDirPath}/drivers/lpflexcomm/lpi2c/fsl_lpi2c.c | ||
| ${SdkRootDirPath}/drivers/lpflexcomm/lpuart/fsl_lpuart.c | ||
| ${SdkRootDirPath}/drivers/gpio/fsl_gpio.c | ||
| ${SdkRootDirPath}/drivers/glikey/fsl_glikey.c | ||
| # UART HAL adapter (provides HAL_UartInit etc.). | ||
| ${SdkRootDirPath}/components/uart/fsl_adapter_lpuart.c | ||
| # PMIC driver. | ||
| ${SdkRootDirPath}/components/pmic/pca9422/fsl_pca9422.c | ||
| # Debug console (provides DbgConsole_Init/Printf). | ||
| ${SdkRootDirPath}/components/debug_console_lite/fsl_debug_console.c | ||
| ) | ||
|
|
||
| target_include_directories( | ||
| ${MCUX_SDK_PROJECT_NAME} | ||
| PRIVATE | ||
| ${CMAKE_CURRENT_SOURCE_DIR} | ||
| ${SdkRootDirPath}/arch/arm/CMSIS/Core/Include | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/cm33_core0 | ||
| ${SdkRootDirPath}/devices/RT/RT700/MIMXRT798S/drivers | ||
| ${SdkRootDirPath}/devices/RT/RT700/periph | ||
| ${SdkRootDirPath}/drivers/common | ||
| ${SdkRootDirPath}/components/pmic/pca9422 | ||
| ${SdkRootDirPath}/components/uart | ||
| ${SdkRootDirPath}/components/debug_console_lite | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/flash_config | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/eiq_examples/executorch_cifarnet/cm33_core0 | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/common/clock/cm33_core0 | ||
| ${SdkRootDirPath}/examples/eiq_examples/executorch_cifarnet | ||
| ${SdkRootDirPath}/examples/eiq_examples/common | ||
| ${SdkRootDirPath}/boards/mimxrt700evk/eiq_examples/executorch_cifarnet/cm33_core0 | ||
| ${SdkRootDirPath}/examples/_boards/mimxrt700evk/eiq_examples/executorch_cifarnet/npu | ||
| ${SdkRootDirPath}/drivers/cache/xcache | ||
| ${SdkRootDirPath}/drivers/gpio | ||
| ${SdkRootDirPath}/drivers/lpflexcomm | ||
| ${SdkRootDirPath}/drivers/lpflexcomm/lpuart | ||
| ${SdkRootDirPath}/drivers/lpflexcomm/lpi2c | ||
| ${SdkRootDirPath}/drivers/xspi | ||
| ${SdkRootDirPath}/drivers/reset | ||
| ${SdkRootDirPath}/drivers/clock | ||
| ${SdkRootDirPath}/drivers/glikey | ||
| ${SdkRootDirPath}/drivers/mu1 | ||
| ${SdkRootDirPath}/drivers/power | ||
| ${SdkRootDirPath}/drivers/iopctl | ||
| ${SdkRootDirPath}/components/str | ||
| ) | ||
|
|
||
| set(EXECUTORCH_BUILD_PYBIND OFF) | ||
| set(EXECUTORCH_BUILD_TESTS OFF) | ||
| set(EXECUTORCH_BUILD_DEVTOOLS OFF) | ||
| set(EXECUTORCH_BUILD_EXECUTOR_RUNNER OFF) | ||
| set(EXECUTORCH_BUILD_CPUINFO OFF) | ||
| set(EXECUTORCH_BUILD_PTHREADPOOL OFF) | ||
| set(EXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL ON) | ||
| set(EXECUTORCH_BUILD_PORTABLE_OPS ON) | ||
| set(EXECUTORCH_BUILD_KERNELS_QUANTIZED ON) | ||
| set(CMAKE_POSITION_INDEPENDENT_CODE OFF) | ||
| add_subdirectory(${EXECUTORCH_ROOT_DIR} EXCLUDE_FROM_ALL executorch) | ||
|
|
||
| target_link_libraries( | ||
| ${MCUX_SDK_PROJECT_NAME} | ||
| PRIVATE -Wl,--start-group | ||
| executorch | ||
| executorch_core | ||
| extension_runner_util | ||
| quantized_kernels | ||
| portable_kernels | ||
| ${NEUTRON_LIB_DIR}/libNeutronDriver.a | ||
| ${NEUTRON_LIB_DIR}/libNeutronFirmware.a | ||
| -Wl,--end-group | ||
| ) |
45 changes: 45 additions & 0 deletions
45
examples/nxp/mcuxpresso/imxrt700/executorch_cifarnet/build_example.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/bin/bash | ||
| # Copyright 2026 NXP | ||
| # | ||
| # This source code is licensed under the BSD-style license found in the | ||
| # LICENSE file in the root directory of this source tree. | ||
|
|
||
| cd "$(dirname "$0")" | ||
|
|
||
| if [ -z ${ARMGCC_DIR+x} ]; then | ||
| echo "ARMGCC_DIR needs to be set in the environment!" | ||
| exit 1; | ||
| fi | ||
|
|
||
| if [ -z ${SdkRootDirPath+x} ]; then | ||
| echo "SdkRootDirPath needs to be set in the environment!" | ||
| exit 1; | ||
| fi | ||
|
|
||
| if [ ! -f model_pte.h ]; then | ||
| echo "Cannot find model_pte.h!" | ||
| exit 1; | ||
| fi | ||
|
|
||
| if [ ! -f ${NEUTRON_LIB_DIR}/libNeutronDriver.a ]; then | ||
| echo "Neutron driver not found in ${NEUTRON_LIB_DIR}!" | ||
| exit 1; | ||
| fi | ||
|
|
||
| if [ ! -f ${NEUTRON_LIB_DIR}/libNeutronFirmware.a ]; then | ||
| echo "Neutron firmware not found in ${NEUTRON_LIB_DIR}!" | ||
| exit 1; | ||
| fi | ||
|
|
||
| mkdir -p cmake-out | ||
|
|
||
| cd cmake-out | ||
|
|
||
| cmake -DSdkRootDirPath=${SdkRootDirPath} \ | ||
| -DCMAKE_TOOLCHAIN_FILE=${SdkRootDirPath}/cmake/toolchain/armgcc.cmake \ | ||
| -DNEUTRON_LIB_DIR=${NEUTRON_LIB_DIR} \ | ||
| -DCMAKE_BUILD_TYPE=flash_release \ | ||
| -G "Unix Makefiles" \ | ||
| .. | ||
|
|
||
| make -j 6 executorch_cifarnet.elf |
32 changes: 32 additions & 0 deletions
32
examples/nxp/mcuxpresso/imxrt700/executorch_cifarnet/prepare_model.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #!/bin/bash | ||
| # Copyright 2026 NXP | ||
| # | ||
| # This source code is licensed under the BSD-style license found in the | ||
| # LICENSE file in the root directory of this source tree. | ||
|
|
||
| set -u | ||
| EIQ_PYPI_URL="${EIQ_PYPI_URL:-https://eiq.nxp.com/repository}" | ||
|
|
||
| pushd "$(dirname "$0")/../../../../.." | ||
|
|
||
| ./install_executorch.sh | ||
| ./devtools/install_requirements.sh | ||
|
|
||
| pip install --index-url ${EIQ_PYPI_URL} eiq-neutron-sdk==3.2.0 | ||
|
|
||
| python3 -m examples.nxp.aot_neutron_compile -m cifar10 -d -q --use_channels_last_dim_order --remove-quant-io-ops | ||
| mv cifar10_nxp_delegate.pte model.pte | ||
| xxd -i model.pte > model_pte.h | ||
|
|
||
| popd | ||
| cd "$(dirname "$0")" | ||
|
|
||
| echo '#ifdef __MCUXPRESSO' > model_pte.h | ||
| echo '#define __PLACEMENT __attribute__((section(".data.$modeldata")))' >> model_pte.h | ||
| echo '#else' >> model_pte.h | ||
| echo '#define __PLACEMENT __attribute__((section(".modeldata")))' >> model_pte.h | ||
| echo '#endif' >> model_pte.h | ||
| echo >> model_pte.h | ||
| echo 'static const uint8_t model_pte[] __ALIGNED(16) __PLACEMENT = {' >> model_pte.h | ||
|
|
||
| cat ../../../../../model_pte.h | grep -v unsigned >> model_pte.h |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.