Copying script files to bin, checking them, setting execute bit.

I have a project that consist of C/C++/proto/bash.

The C/C++ now works fine. proto works via an add_custom_command.
(The cpp_generate_proto did not work with my protofiles in subdirectories)

But I have not found a satisfying way of copying the script files to
the bin directory.

I have seen from previous answers that configure_file(… COPY_ONLY)
been suggested.

And it kind of works. But the copying of those files are at the
generator phase. So when I change one of those files cmake are
refgenerating build files. Also it will not detect if the files are removed.
So rm bin/*.sh is not detected, and I have to run cmake . again.
And it does not change the execute bit.

I could change the execute bit in the repository, and it will kind of
work, but I do not like it.

It also does not do syntax check on the scripts.

What I would like to happen, when building, and when a script in the
source tree is changed, is:

bash -n $src && cp $src $trg && chmod +x $trg

I have tried with add_custom_command/add_custom_target/add_dependencies
with no luck.

What I have for now ended up with is:

add_custom_target(Scripts ALL
make VPATH=${CMAKE_SOURCE_DIR} -f ${CMAKE_SOURCE_DIR}/MakeShellScripts
)

And let the MakeShellScripts makefile do the work.

But is there really not possible to do this inside CMake ?
Define a target, sources, and how to convert the sources to the target?

I would recommend something like this function. You can add the permission changing logic in there as well.

This issue may also be of interest.

Quite sure that I did miss something of the real problem. Why is a simple custom_command not working?

add_custom_command(
  OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/tool.sh"
  COMMAND bash -n "${CMAKE_CURRENT_SOURCE_DIR}/tool.sh"
  COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/tool.sh" "${CMAKE_CURRENT_BINARY_DIR}/tool.sh"
  COMMAND chmod +x "${CMAKE_CURRENT_BINARY_DIR}/tool.sh"
)
add_custom_target(tool_check_and_copy ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tool.sh)

You did not test this, did you?
But you were right. Just add a
DEPENDS tool.sh
at the end of add_custom_command and it works.

I had tried several variations of your suggestion, but used add_dependencies to the custom_target, which apparently was not the same as DEPENDS.

Thanks.

I have 39 of these targets, so next project is to write a function to generate this.

Still surprised that such a function is not part of standard cmake. Though that it was quite common to have bash scripts or python scripts as part of a C/C++ baseline.

Oh, yes. I forgot the DEPENDS in this example. I just tried out if it does the right thing if the output was deleted.

You should add all relevant dependencies to the add_custom_command itself. This can’t be done with add_dependencies as it is not a target.

I had used add_dependencies to the add_custom_target. Which did not works.

My current implementation:

function(add_bash file)
  get_filename_component(filename ${file} NAME)
  get_filename_component(abspath ${file} ABSOLUTE)
  set(out ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${filename})
  add_custom_command(
    OUTPUT ${out}
    COMMAND bash -n ${abspath}
    COMMAND cp ${abspath} ${out}
    COMMAND chmod +x ${out}
    DEPENDS ${file}
    )
  set(ScriptList ${ScriptList} ${out} PARENT_SCOPE)
  message( ${abspath})
endfunction()

function(add_many_bash target)
  set(ScriptList)
  foreach(i IN LISTS ARGN)
    add_bash(${i})
  endforeach()

  add_custom_target(${target} ALL
    DEPENDS ${ScriptList}
    )
  
endfunction()