Skip to content

cmake build fails if more than one build_sketch definition is used #2282

Description

@ddowling

I am trying to build multiple sketches using a project wide CMakeLists.txt file. If I call the build_sketch() function with each of the targets then cmake reports an error about duplicated targets:

...
Make Error at /home/dpd/.arduino15/packages/STMicroelectronics/hardware/stm32/2.7.1/variants/STM32F1xx/F103C8T_F103CB(T-U)/CMakeLists.txt:5 (add_library):
  add_library cannot create target "variant" because another target with the
  same name already exists.  The existing target is an interface library
  created in source directory
  "/home/dpd/.arduino15/packages/STMicroelectronics/hardware/stm32/2.7.1/variants/STM32F1xx/F103C8T_F103CB(T-U)".
  See documentation for policy CMP0002 for more details.
...

I have tried various cmake property settings but the error persists. I was able to get the builds to work by putting an if (NOT TARGET variant) guard around the add_subdirectory calls in build_sketch.cmake.

*** build_sketch.cmake.orig	2024-02-21 17:32:23.290460959 +1100
--- build_sketch.cmake	2024-02-21 17:33:09.851221766 +1100
***************
*** 6,14 ****
  include(set_base_arduino_config)
  
  function(build_sketch)
!   add_subdirectory(${BUILD_VARIANT_PATH} ./variant)
!   add_subdirectory(${BUILD_CORE_PATH} ./cores/arduino)
!   add_subdirectory(${BUILD_LIB_PATH} ./libraries)
  
    cmake_parse_arguments(PARSE_ARGV 0 SKBD "" "TARGET" "SOURCES;DEPENDS")
  
--- 6,17 ----
  include(set_base_arduino_config)
  
  function(build_sketch)
!   if (NOT TARGET variant)
!     add_subdirectory(${BUILD_VARIANT_PATH} ./variant)
!     add_subdirectory(${BUILD_CORE_PATH} ./cores/arduino)
!     add_subdirectory(${BUILD_LIB_PATH} ./libraries)
!   endif()
! 
  
    cmake_parse_arguments(PARSE_ARGV 0 SKBD "" "TARGET" "SOURCES;DEPENDS")

If there is a better solution then I would love to know otherwise I can submit a pull request.

Activity

  1. fpistm commented on Feb 21, 2024

    @fpistm
    Member

    @massonal any input for this? Did you try build with several sketches? Thanks.

  2. massonal commented on Feb 21, 2024

    @massonal
    Contributor

    Hello,

    IIRC build_sketch() creates build targets with specific names to handle the Arduino workflow.
    These targets always have the same conventional name, so that they can be more easily integrated into the rest of the project. (variant is one, there are others.)

    Unfortunately, this means than no more than one sketch is supported per CMake project.

    I think it's possible to change the name of the conventional targets to include some sketch-specific prefix. If you're interested in developing this, please feel free! - assuming @fpistm agrees on the idea ;)

  3. ddowling commented on Feb 21, 2024

    @ddowling
    ContributorAuthor

    The targets that cause a clash seem to be more dependant on the variant selected and this is controlled by set_board and should not really change on a per sketch basis. I thin redefining them in each sketch is the issue.

  4. massonal commented on Feb 21, 2024

    @massonal
    Contributor

    You're right. I have studied the issue in a bit more depth, and the limitation you're running into is that each variant has its own CMakeLists.txt file which defines a target named variant.

    The simplest solution is, I think, to move the add_subdirectory() calls you pointed out earlier outside of build_sketch() (directly at file level, under include(set_base_arduino_config)).
    This would have to be thoroughly documented in the wiki, however:

    • importing build_sketch.cmake has side-effects
    • importing build_sketch.cmake should only happen once
    • having several sketches with different targets / configs is not supported.

    What do you think about this, @ddowling @fpistm ?

  5. ddowling commented on Feb 21, 2024

    @ddowling
    ContributorAuthor

    Moving the add_subdirectory() calls out of the function definition works in my use-case. If we are concerned about importing build_sketch.cmake more than once the we could use include_guard() on the file. I understand having different configs is not supported but I don't think this would be a very common case. If you were building for different boards or settings this can be handled by having different build directories where cmake is run with different defines.
    The case I am trying to address is a library with multiple small programs to unit test the functionality and to provide some user examples. When doing embedded development I like to keep a few very small and simple test programs around for when the whole board just starts misbehaving. You need this to determine if you are fighting a software or hardware issue.

  6. massonal commented on Feb 21, 2024

    @massonal
    Contributor

    Hey, I'm glad this solution works for you. Also, I did not know about include_guard(); it would definitely be a good addition in most files in stm32duino's CMake framework.

    Do you want to implement these changes and propose a pull request?

  7. ddowling commented on Feb 21, 2024

    @ddowling
    ContributorAuthor

    @massonal I just noticed another issue in sketch_preprocess_sources.cmake. If you have an .ino file in a subdirectory the dependency fails. Everything is setup correctly but the filename without the flattened ${CMAKE_CURRENT_BINARY_DIR} path is added to the SRCLIST.

    I will get a pull request together with these changes.

    *** sketch_preprocess_sources.cmake.orig	2024-02-21 20:52:30.297138663 +1100
    --- sketch_preprocess_sources.cmake	2024-02-21 21:02:28.738043288 +1100
    ***************
    *** 27,33 ****
              COMPILE_OPTIONS "-include;Arduino.h;-include;${SRCFILE}.h"
              OBJECT_DEPENDS "${SRCFILE}.h"
            )
    !       list(APPEND SRCLIST ${SRCFILE}.cpp)
          else()
            list(APPEND SRCLIST ${SRCFILE})
          endif()
    --- 27,33 ----
              COMPILE_OPTIONS "-include;Arduino.h;-include;${SRCFILE}.h"
              OBJECT_DEPENDS "${SRCFILE}.h"
            )
    !       list(APPEND SRCLIST ${CMAKE_CURRENT_BINARY_DIR}/${SRC_BASE_NAME}.cpp)
          else()
            list(APPEND SRCLIST ${SRCFILE})
          endif()
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions