CMake target shema with multiple targets

Sysprogs forums Forums VisualGDB CMake target shema with multiple targets

This topic contains 5 replies, has 2 voices, and was last updated by  support 4 months, 2 weeks ago.

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
  • #33114



    in one of our embedded project using the advanced cmake system we are trying to unify the definition of static libraries and unit tests. I have already achieved to have only one cmake statement which defines library, test executable and manages necessary dependencies. However I am not able to figure out how to define custom cmake target schema to get UI support for editing this statements.

    A simplified version of what I have done so far can be reproduced by this steps: (this example project is also attached)

    1. Create a new embedded project using advanced cmake (e.g. LEDBlink example for STM32F303)
    2. Place a “functions.cmake” file with following content inside the project directory
      function(register_static_library NAME)
      set(multiValueArgs SOURCES TESTSOURCES)
      cmake_parse_arguments(ARG "" "" "${multiValueArgs}" ${ARGN})

      add_bsp_based_library(NAME Static${NAME} SOURCES ${ARG_SOURCES})
      register_static_test(${NAME} ${ARG_TESTSOURCES})

      function(register_static_test NAME)
      add_bsp_based_executable(NAME Static${NAME}Test SOURCES ${NAME}_test.c ${ARGN} BUILD_UNIT_TESTS)
      target_link_libraries(Static${NAME}Test PRIVATE Static${NAME})
    3. Add include(functions.cmake) to CMakeLists.txt
    4. Define two libraries by adding
      register_static_library(Library1 SOURCES Library1.c)
      register_static_library(Library2 SOURCES Library2.c)
      to CMakeLists.txt
    5. Create the required source files “Library1.c”, “Library2.c”, “Library1_test.c” and “Library2_test.c”
    6. Create a “TargetDefinitions” directory inside the project directory and place the following files into it:
      1. library.tgt
        match register_static_library()
        priority 1000
        props library.prop
        statements library.stmt
      2. library.prop
        target.decl: register_static_library() =
        target.sources = target.decl.sources
      3. library.stmt
        from: register_static_library()
        format: register_static_library(@*)
        subformat: %name @sources
      4. test.tgt
        match register_static_test()
        priority 1001
        props test.prop
        statements test.stmt
      5. test.prop
        target.decl: register_static_test() =
        target.sources = target.decl.sources
      6. test.stmt
        from: register_static_test()
        format: register_static_test(@*)
        subformat: %name @sources
    7. In the VisualGDB project properties set the custom target definitions directory
    8. Restart visual studio
    9. Adding a new file to StaticLibrary1 from the UI works
    10. Adding a new file to StaticLibrary1Test from the UI still gives a error

    How do I tell VisualGDB that for adding a file to the StaticLibarary1Test the “TESTSOURCES” from the “register_static_library” statement must be edited?
    Is there any additional documentation for the .tgt .prop and .stmt files beside the toturial?

    You must be logged in to view attached files.



    No problem, we can clarify what is going on. Your project structure defines the libraries as shown below (the levels correspond to the CMake call stack):

    1. register_static_library(StaticLibrary1)
      1. add_bsp_based_library(StaticLibrary1)
      2. register_static_test(StaticLibrary1)
        1. add_bsp_based_executable(StaticLibrary1Test)
    2. register_static_library(StaticLibrary2)
      1. add_bsp_based_library(StaticLibrary2)
      2. register_static_test(StaticLibrary2)
        1. add_bsp_based_executable(StaticLibrary2Test)

    You have manually defined that register_static_library is the primary statement for the library and register_static_test is the primary statement for the test.

    When you try to add sources to StaticLibrary1, VisualGDB walks the definition stack until it finds the register_static_library  statement (1.a => 1) and edits it as expected. This works because StaticLibrary1  (1) and StaticLibrary2 (2) have two physically different register_static_library() statements.

    When you try doing the same with StaticLibrary1Test, VisualGDB walks the call stack until register_static_test (1.b.i => 1.b). However both StaticLibrary1Test and StaticLibrary2Test call register_static_test (1.b and 2.b) from the same source location within register_static_library (in functions.cmake).

    You can try commenting out the second library definition (register_static_library(Library2 SOURCES Library2.c)) and adding the sources via Solution Explorer. They will be added to the call of register_static_test() exactly as you defined in the test.prop file. However when having 2 libraries, this edit would simultaneously affect both of them, so VisualGDB refuses to do so.

    In order for Solution Explorer functionality to work, each target needs to have one unique statement that defines this target and only this target (anywhere on the call stack). E.g. you can refactor your CMake functions so that the call stacks will look like this:

    1. register_static_library(StaticLibrary1)
      1. add_bsp_based_library(StaticLibrary1)
    2. register_static_test(StaticLibrary1)
      1. add_bsp_based_executable(StaticLibrary1Test)
    3. register_static_library(StaticLibrary2)
      1. add_bsp_based_library(StaticLibrary2)
    4. register_static_test(StaticLibrary2)
      1. add_bsp_based_executable(StaticLibrary2Test)

    You would need 2x the statements in the main CMakeLists.txt file, however as each statement is now uniquely associated with a target, solution explorer logic will work just fine. If you would like to minimize redundancy, the register_static_library() function can set some custom properties on the created target, and register_static_test() can query them so you wouldn’t need to specify them twice. You can search the VisualGDB CMake files for get_target_property() to get the basic idea.

    You can also keep the current layout and export the TESTSOURCES parameter of register_static_library() as a custom property (e.g. see bsp.hwregister_list_file in bsp.prop). It will be editable via the VS properties window, but not via the add/remove files commands.




    thanks for the explanation. I managed to come up with a solution using multiple statements which looks feasible for us.

    To make our life even more convenient I tried to create a target template. Here is what I have tried:

    1. Create a new embedded project using CMake
    2. Copy the TargetDefinitions directory from this tutorial into the project directory
    3. In the VisualGDB project properties set the custom target definitions directory to the copied directory
    4. Add a new item to the project
    5. In the “Add New Project Item” dialogue the “Sample Custom Target Template” is not listed

    When using a different project type (e.g. MinGW) the “Sample Custom Target Template” is listed in the “Add New Project Item” dialogue.

    Any idea what is going on?



    It is hard to say why it would not be working. Please try opening the CustomCMakeTargetDemo.sln solution from the tutorial directly. If it doesn’t work, please let us know and we will recheck. If it works, please try comparing your .vgdbcmake file against the one that works. If you find multiple different settings, you can try copying half of them at a time into the broken project and reloading it to see if it fixes the issue.

    If you can pinpoint a specific setting that is breaking the template functionality, feel free to let us know and we will help you get it working.




    the specific setting which breaks the template functionality is the project type. It is only not working for embedded projects.



    Thanks, we have reproduced the issue and fixed it in the following build: VisualGDB-

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.