creating a macro that dynamically updates a custom target

Hi All,

I’m trying to write a macro that creates a custom target using the source and headers from other targets.

from the build folder I would like to run for example

cmake ..
cmake --build . --target clang-format-dry-run

Add scattered through various folders I would like to add

add_library(<my target>) or add_executable(<my target>)
...
etc
...

# call macro 
ClangFormatTarget(<my target>)

This is what I currently have for the macro. I’m currently stuck trying to use $<TARGET_PROPERTY>

macro(ClangFormatTarget TARGET)
    if( NOT (TARGET clang-format-dry-run))
        add_custom_target(clang-format-dry-run
            COMMAND ${CLANG_FORMAT_EXE} --dry-run --verbose -style=file --Werror $<TARGET_PROPERTY:clang-format-dry-run,SOURCES>
        )
    endif()

# get the source files from the target
    get_target_property(target_dir ${TARGET} SOURCE_DIR)
    get_target_property(target_source_files ${TARGET} SOURCES)
    get_target_property(target_header_files ${TARGET} PUBLIC_HEADER)

    if(target_source_files)
        foreach(file IN LISTS target_source_files)
            list(APPEND files_to_format ${target_dir}/${file})
        endforeach()
    endif()

    if(target_header_files)
        foreach(file IN LISTS target_header_files)
            list(APPEND files_to_format ${target_dir}/${file})
        endforeach()
    endif()

    foreach(file IN LISTS files_to_format)
        message(${TARGET} " file to format " ${file})
    endforeach()

# Append the new files to the existing target
    target_sources(clang-format-dry-run PRIVATE ${files_to_format})
endmacro()

The command it generates is as follows

/usr/bin/clang-format --dry-run --verbose -style=file --Werror /home/brian/code/SimpleLibrary/src/simple_library.cpp;/home/brian/code/SimpleLibrary/src/include/SimpleLibrary/simple_library.h;/home/brian/code/SimpleLibrary/tests/simple_library_tests.cpp;/home/brian/code/SimpleLibrary/build/src/CMakeFiles/clang-format-dry-run;/home/brian/code/SimpleLibrary/build/src/CMakeFiles/clang-format-dry-run.rule

The issue I’m having is that

  1. I need the output of the generator expression to be a string of files separated with spaces instead of semicolons and
  2. Why is it creating the last two list elements?

Cheers

Brian

You can use the $<JOIN> genex for that.

The last two files are part of CMake’s internal dependency tracking for the generator. This looks like one of Makefiles generators due to that.

Thanks Ben,

To fix the problems I was having I first creating a new property to store the list of files rather than using the built in SOURCES property, this removed the extra list items.

Then I used the COMMAND_EXPAND_LISTS option in add_custom_target which fixed issues with semicolons and escaped whitespace characters.

I couldn’t figure out how to append to an existing property so I had to first get the current list and then append the new.

macro(ClangFormatTarget TARGET)
    if( NOT (TARGET clang-format-dry-run))
        add_custom_target(clang-format-dry-run
            COMMAND ${CLANG_FORMAT_EXE} --dry-run --verbose -style=file --Werror $<TARGET_PROPERTY:clang-format-dry-run,FILES_TO_CLANG_FORMAT>
            COMMAND_EXPAND_LISTS
        )
    endif()

    get_target_property(target_dir ${TARGET} SOURCE_DIR)
    get_target_property(target_source_files ${TARGET} SOURCES)
    get_target_property(target_header_files ${TARGET} PUBLIC_HEADER)

    if(target_source_files)
        foreach(file IN LISTS target_source_files)
            list(APPEND files_to_format ${target_dir}/${file})
        endforeach()
    endif()

    if(target_header_files)
        foreach(file IN LISTS target_header_files)
            list(APPEND files_to_format ${target_dir}/${file})
        endforeach()
    endif()

    foreach(file IN LISTS files_to_format)
        message(${TARGET} " file to format " ${file})
    endforeach()

    get_target_property(current_files clang-format-dry-run FILES_TO_CLANG_FORMAT)

    if(NOT current_files)
        set(current_files "")
    endif()

    foreach(file IN LISTS current_files)
        list(APPEND files_to_format ${file})
    endforeach()

    set_target_properties(clang-format-dry-run
        PROPERTIES
            FILES_TO_CLANG_FORMAT "${files_to_format}"
    )
endmacro()

set_property(TARGET … APPEND) is what you’re looking for.