This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Error Building Alexa Gadget Example in nRF Connect SDK

I am attempting to build the new alexa_gadget example that is included in the nRF Connect SDK.

Environment information:

  • Windows 64-bit
  • nRF Connect v3.6.0
  • nRF Connect SDK v1.4.0
  • SEGGER Embedded Studio for ARM v5.10d

I received an error about "nanopb" when attempting to create the alexa_gadeget example targeting the nRF Thingy 52. I found details in the logs that instructed to download nanopb and add it to the System PATH. After doing so, the project was created successfully.

Now when trying to build the solution, I am receiving the following error:

src/gadgets/CMakeFiles/protobuf_generation_BASE does not exist.
src\gadgets\CMakeFiles\protobuf_generation_BASE-aa7d0b8.bat 94e7958ce0a12f32
Error starting process src\gadgets\CMakeFiles\protobuf_generation_BASE-aa7d0b8.bat

Can anyone suggest a next step to try to resolve this issue?

  • I found that the Alexa Gadget example documentation does not mention support for the nRF52 Thingy board, so I created a new project targeting the nrf52dk_nrf52832 board. I'm still getting the same error with this selection.

  • Hello,

    there appears to be a couple of issues regarding the protobuf compiler invocation. We're looking at a proper fix, but I do have a workaround for now.

    First off, when compiling for Thingy:52 you will probably get some compilation errors  from main.c, as the LEDs and Buttons from the nRF52840-DK are used here. The workaround below uses the nrf52840dk_nrf52840 build target as a reference, but you can substitute with the thingy target.

    Two issues seen:

    1) protoc.exe does not create the output directory

    2) SES does not properly invoke the CMake-generated .bat-files that in turn invokes protoc.exe. Not yet sure if this is a windows PATH issue, or related to SES.

    Workaround for 1: manually create the following directory structure: "alexa_gadget\build_nrf52840dk_nrf52840\generated\alexa\protobuf", where alexa_gadget is the sample directory (and you can replace the nrf52840dk_nrf52840 name with your build target).

    Workaround for 2:

    Step 1: Navigate to the "alexa_gadget\build_nrf52840dk_nrf52840\src\gadgets\CMakeFiles" directory. Note The set of .bat files in this directory.

    Step 2: Create a set of empty folders in this directory as seen in screenshot below ("protobuf_generation_xyz")

    Step 3: Run the .bat files in this folder

    Now you should be able to build and run the sample in SES as normal.

    Edit:

    After running the .bat files, the generated/alexa/protobuf directory should be filled with .c and .h files:

  • Thanks for the reply and the above steps. The build was successful after completing these steps.

    Note that selecting "Rebuild" still produces errors after completing these steps, so only "build" should be used after completing these steps.

  • There is a better fix on the way: https://github.com/nrfconnect/sdk-nrf/pull/3392

    In the meantime you can replace your local alexa_gadget\src\gadgets\CMakeLists.txt with the attached one (same modifications as in referenced PR). This is a more convenient workaround than the steps described previously.

    #
    # Copyright (c) 2020 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
    #
    
    # The Gadgets Profile relies on the nanopb generator tool, which must be
    # available at the configuration stage.
    # This tool is used to compile the alexa .proto files at build time.
    # Output from the .proto compilation is a set of .c and .h files.
    
    # Note: as there doesn't seem to be an easy way of checking the version of the nanopb generator (protoc-gen-nanopb binary)
    # there is the possibility of a version mismatch between the generator and the nanopb source files that is used in the firmware sample.
    # If there is a mismatch, there will be a compilation error in the build step.
    # The easiest way to fix such an error is to download the appropriate nanopb generator .zip and extract it to this sample folder.
    # (https://jpa.kapsi.fi/nanopb/download/)
    
    
    # Check system for protoc and nanopb binaries presence.
    # Prefer local variable to make version matching easier
    find_program(PROTOC_BIN protoc HINTS "${PROJECT_SOURCE_DIR}/*/generator-bin/")
    find_program(NANOPB_BIN protoc-gen-nanopb HINTS "${PROJECT_SOURCE_DIR}/*/generator-bin/")
    
    if ((NOT NANOPB_BIN) OR (NOT PROTOC_BIN))
        message(STATUS "nanopb not found.")
        message(STATUS "Please download platform-specific nanopb from here https://jpa.kapsi.fi/nanopb/download/")
        message(STATUS "Extract the files to `${PROJECT_SOURCE_DIR}`, or add `<path-to>/nanopb-x.y.z-<platform>/generator-bin` to system PATH.")
        message(STATUS "Alternatively, specify install location using: `-DCMAKE_PROGRAM_PATH=<path-to>/nanopb-x.y.z-<platform>/generator-bin` when running CMake.")
        message(FATAL_ERROR "nanopb required by this project.")
    endif()
    
    # Locate alexa-embedded and nanopb in local ncs tree
    if(ALEXA_EMBEDDED_PATH)
      # Do nothing, just use the provided path
    elseif(WEST)
      ## Use Python and west to find the alexa-embedded path
      execute_process(
        COMMAND ${PYTHON_EXECUTABLE} -c
        "from west.manifest import Manifest; manifest = Manifest.from_file(); print(manifest.get_projects(['Alexa-Gadgets-Embedded-Sample-Code'])[0].posixpath)"
        OUTPUT_VARIABLE
        west_project_output
        RESULT_VARIABLE
        result
      )
      string(REGEX REPLACE "[\r\n]+" "" ALEXA_EMBEDDED_PATH "${west_project_output}")
      if(${result})
        message(FATAL_ERROR "Failed to find alexa-embedded, cannot build sample")
      endif()
    else()
      message(FATAL_ERROR "west not installed, please provide ALEXA_EMBEDDED_PATH to CMake to build this sample")
    endif()
    
    if(NANOPB_PATH)
      # Do nothing, just use the provided path
    elseif(WEST)
      ## Use Python and west to find the nanopb path
      execute_process(
        COMMAND ${PYTHON_EXECUTABLE} -c
         "from west.manifest import Manifest; manifest = Manifest.from_file(); print(manifest.get_projects(['nanopb'])[0].posixpath)"
        OUTPUT_VARIABLE
        west_project_output
        RESULT_VARIABLE
        result
      )
      string(REGEX REPLACE "[\r\n]+" "" NANOPB_PATH "${west_project_output}")
      if(${result})
        message(FATAL_ERROR "Failed to find nanopb source files, cannot build sample")
      endif()
    else()
      message(FATAL_ERROR "west not installed, please provide NANOPB_PATH to CMake to build this sample")
    endif()
    
    # Protobuf generation setup
    
    set(PROTO_COMPILATION_DIR ${CMAKE_BINARY_DIR}/generated/alexa/protobuf)
    
    # Populate lists of .proto files that should be compiled at build time
    set(BASE_PROTO_FILES
        ${ALEXA_EMBEDDED_PATH}/ConnectionHelpers/BLE/Proto/accessories.proto
        ${ALEXA_EMBEDDED_PATH}/ConnectionHelpers/BLE/Proto/common.proto
        ${ALEXA_EMBEDDED_PATH}/ConnectionHelpers/BLE/Proto/device.proto
        ${ALEXA_EMBEDDED_PATH}/ConnectionHelpers/BLE/Proto/firmware.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/parser/directiveParser.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/common/directiveHeader.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/parser/eventParser.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/common/eventHeader.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Discovery/Discover/alexaDiscoveryDiscoverDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Discovery/Discover/alexaDiscoveryDiscoverDirectivePayload.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Discovery/Discover.Response/alexaDiscoveryDiscoverResponseEvent.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Discovery/Discover.Response/alexaDiscoveryDiscoverResponseEventPayload.proto
    )
    
    set(NOTIFICATIONS_PROTO_FILES
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Notifications/SetIndicator/notificationsSetIndicatorDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Notifications/SetIndicator/notificationsSetIndicatorDirectivePayload.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Notifications/ClearIndicator/notificationsClearIndicatorDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Notifications/ClearIndicator/notificationsClearIndicatorDirectivePayload.proto
    )
    
    set(ALERTS_PROTO_FILES
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alerts/SetAlert/alertsSetAlertDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alerts/SetAlert/alertsSetAlertDirectivePayload.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alerts/DeleteAlert/alertsDeleteAlertDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alerts/DeleteAlert/alertsDeleteAlertDirectivePayload.proto
    )
    
    set(STATELISTENER_PROTO_FILES
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Gadget.StateListener/StateUpdate/alexaGadgetStateListenerStateUpdateDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Gadget.StateListener/StateUpdate/alexaGadgetStateListenerStateUpdateDirectivePayload.proto
    )
    
    set(SPEECHDATA_PROTO_FILES
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Gadget.SpeechData/Speechmarks/alexaGadgetSpeechDataSpeechmarksDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Gadget.SpeechData/Speechmarks/alexaGadgetSpeechDataSpeechmarksDirectivePayload.proto
    )
    
    set(MUSICDATA_PROTO_FILES
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Gadget.MusicData/Tempo/alexaGadgetMusicDataTempoDirective.proto
        ${ALEXA_EMBEDDED_PATH}/AlexaGadgetsProtobuf/Alexa.Gadget.MusicData/Tempo/alexaGadgetMusicDataTempoDirectivePayload.proto
    )
    
    set(CUSTOM_PROTO_FILES
        ${CMAKE_CURRENT_SOURCE_DIR}/proto/custom_event.proto
    )
    
    foreach(GROUP BASE NOTIFICATIONS ALERTS STATELISTENER SPEECHDATA MUSICDATA CUSTOM)
        # Populate list of expected .c files output from protobuf generation
        foreach(file ${${GROUP}_PROTO_FILES})
            get_filename_component(FILE_DIR ${file} DIRECTORY)
            get_filename_component(FILE_BASE_NAME ${file} NAME_WE)
            list(APPEND PROTOC_INC_DIRS "-I.")
            list(APPEND PROTOC_INC_DIRS "-I${FILE_DIR}")
            list(APPEND ${GROUP}_PROTO_OUTPUTS "${PROTO_COMPILATION_DIR}/${FILE_BASE_NAME}.pb.c")
            list(APPEND ${GROUP}_PROTO_DEPENDENCIES "${file}")
        endforeach()
    
        # Each .pb.c file to be compiled by protoc gets its own CMake custom command,
        # with dependencies to all other .proto files in its group and the base files.
        foreach(file ${${GROUP}_PROTO_FILES})
            get_filename_component(FILE_DIR ${file} DIRECTORY)
            get_filename_component(FILE_NAME ${file} NAME)
            get_filename_component(FILE_BASE_NAME ${file} NAME_WE)
    
            set(PROTOC_ARGS "-I."
                            "${PROTOC_INC_DIRS}"
                            "--nanopb_out=${PROTO_COMPILATION_DIR}"
                            "${FILE_NAME}"
            )
    
            add_custom_command(
              OUTPUT "${PROTO_COMPILATION_DIR}/${FILE_BASE_NAME}.pb.c"
              COMMAND ${PROTOC_BIN} ${PROTOC_ARGS}
              WORKING_DIRECTORY ${FILE_DIR}
              MAIN_DEPENDENCY ${file}
              DEPENDS ${${GROUP}_PROTO_DEPENDENCIES} ${BASE_PROTO_DEPENDENCIES}
            )
        endforeach()
    endforeach()
    
    zephyr_library_named(ALEXA_GADGETS_PROFILE)
    
    zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
    zephyr_include_directories(${PROTO_COMPILATION_DIR})
    zephyr_include_directories(${NANOPB_PATH})
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_PROFILE_ENABLE
        ${CMAKE_CURRENT_SOURCE_DIR}/gadgets_profile.c
        ${NANOPB_PATH}/pb_common.c
        ${NANOPB_PATH}/pb_encode.c
        ${NANOPB_PATH}/pb_decode.c
        ${BASE_PROTO_OUTPUTS}
    )
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_CAPABILITY_NOTIFICATIONS_ENABLE
        ${NOTIFICATIONS_PROTO_OUTPUTS}
    )
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_CAPABILITY_ALERTS_ENABLE
        ${ALERTS_PROTO_OUTPUTS}
    )
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_CAPABILITY_STATELISTENER_ENABLE
        ${STATELISTENER_PROTO_OUTPUTS}
    )
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_CAPABILITY_SPEECHDATA_ENABLE
        ${SPEECHDATA_PROTO_OUTPUTS}
    )
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_CAPABILITY_MUSICDATA_ENABLE
        ${MUSICDATA_PROTO_OUTPUTS}
    )
    
    zephyr_library_sources_ifdef(CONFIG_GADGETS_CAPABILITY_CUSTOM_ENABLE
        ${CUSTOM_PROTO_OUTPUTS}
    )
    

Related