add_custom_command() does not work in each cases but there is no error!

I have a CMake Project with following code snipped

find_program(DOT dot REQUIRED)

find_program(
  IDL_COMPILER
  NAMES idl2cpp idl2cpp.sh idl2cpp.cmd
  HINTS $ENV{OE_HOME}/host/$ENV{OE_HOST_PLATFORM}/bin REQUIRED
)

# create a long text
set(TEXT 0123456789ABCDEF)
foreach(I RANGE 7)
  list(APPEND TEXT ${TEXT})
endforeach()

add_custom_command(
  OUTPUT generate
  COMMAND ${CMAKE_COMMAND} --graphviz=${GENERATED_DIR}/${CMAKE_PROJECT_NAME}.dot ${CMAKE_CURRENT_BINARY_DIR}
  COMMAND ${DOT} -Tsvg ${GENERATED_DIR}/${CMAKE_PROJECT_NAME}.dot -o ${GENERATED_DIR}/${CMAKE_PROJECT_NAME}.svg
  COMMAND ${CMAKE_COMMAND} -E echo ${TEXT} > generate
  COMMAND ${IDL_COMPILER} -help || echo ignored
  COMMAND ${CMAKE_COMMAND} -E echo OK
  COMMENT "generates generate"
)

add_custom_target(gen DEPENDS generate)

If the command are longer than an unknown limit (about 8k) a batch file is generated from CMake.
But the IDL_COMPILER program may be a program, a bat, or a shell wrapper depending on the build host.

following happens on windows:

$ ninja generate -v
[1/1] CMakeFiles\generate-24cacf5.bat 769e14510ca1803e
-- Configuring done
-- Generating done
Generate graphviz: C:/Users/klein_cl/Workspace/CmakeCustomTargetExamples/build/ppcIntegrity178BOrbExpressD/.generated/MyProj.dot
Reading GraphViz options file: C:/Users/klein_cl/Workspace/CmakeCustomTargetExamples/CMakeGraphVizOptions.cmake
-- Build files have been written to: C:/Users/klein_cl/Workspace/CmakeCustomTargetExamples/build/ppcIntegrity178BOrbExpressD
Usage is: idl2cpp [-help | options] input-file

  -a        Generate typecodes & type Any support for user-defined IDL types [default=false]
  -bm       Generate MSVC++ V6 and prior bug-compatible code (not for V7 and later) [default=false]
  -bo       Generate g++ 2.7 bug-compatible code [default=false]
  -d<sym>   Define pre-processor symbol <sym>
  -ea       Generate servant to require only impls with _env arg [default=true]
  -ee       Generate servant to allow impls both with and without _env arg [default=false]
  -ex       Generate servant to require only impls without _env arg [default=false]
  -fi<n>    Set formatting indent to <n> spaces [default=4]
  -fm<n>    Set formatting margin to column <n> [default=80]
  -fc<sfx>  Set client file suffix to <sfx> [default=]
  -fs<sfx>  Set server file suffix to <sfx> [default=_s]
  -fh<ext>  Set C++ header file extension to <ext> [default=h]
  -fx<ext>  Set C++ source file extension to <ext> [default=cxx]
  -i<dir>   Search <dir> for #included files
  -m        Map IDL modules to C++ namespaces [default=false]
  -n        Generate code for #included files [default=false]
  -pl       Use POA policies on local invocations [default=false]
  -q        Don't generate model _impl files [default=false]
  -r        Generate client code only, implies -q [default=false]
  -s        Syntax and semantic check only [default=false]
  -ts<size> Allocate temporaries larger than size on heap instead of stack [default=1000000]
  -u<sym>   Undefine pre-processor symbol <sym>
  -od<dir>  Specify the output directory
  -v        Print version number and license info
  -help     Print this message

ignored

NO OK? This is an error in the generated batch file because call to cmd file is not used!

Q: Any idea how this can be solved a portable way?
Q: What is the MAX command length, after that, a batch file is generated?
Q: Is this a windows specifically problem or a general ninja generator problem?

Write a CMake script that does execute_process on its own (configured with the paths you need passed in as -D or via configure_file) and then call it with cmake -P ….

Platform dependent.

How each generator deals with over-long command lines is probably unique. make generators have a line per command while ninja will do cmd1 && cmd2 (or other ways of concatenating them, I don’t remember off hand), so make won’t hit the limit so easily.

I can use

on windows, than it works. But this is NOT portable!

My problem was the changed behaviour as I needed to add more include path arguments.
The next commend was not longer executed and I saw not why?

Why do you need call? What does the compiler do that is modifying the parent process environment? If it is a bat script itself, the command should itself be cmd;path/to/idlc.bat, no (just like a Python script would be ${Python_EXECUTABLE};path/to/idlc.py)? Sure, non-Windows support shebang lines for such things, but Windows has mechanisms for that too AFAIK.

What changed behavior? CMake? If so, what version worked and what version is not working anymore? If there are any versions in between, knowing which version started to break things would be useful in tracking down this change. Additionally, can you provide a small self-contained example that demonstrates the problem so that we can test it and fix it?

The ninja rule is something like this:

cmd /c path/to/cmake/generated.bat

But the batch file need to use:

call idl2cpp.cmd && do some post processing

It is not changed with CMake version. It was changed by me!

My project in development and on Windows, you needs much more path entries and include_directories then on other build host OS environments. :woozy_face:

sure, see

I would just write my own batch script and have CMake use cmd /c on that. CMake has no idea that your tool uses cmd and requires call (and there’s no way to tell it to do so because there’s no guarantee that cmd is even used by the build tool; nmake just calls CreateProcess AFAIK).

Ah, yep :slight_smile: . Welcome to cross platform development :slight_smile: .