wildcards in DEPENDS

Alexander Neundorf neundorf at kde.org
Sun Nov 30 20:55:02 CET 2008


On Wednesday 26 November 2008, Matthias Kretz wrote:
> On Tuesday 25 November 2008 22:35:34 Alexander Neundorf wrote:
> > The macro macro_add_file_dependencies() is only available in kdelibs/ and
> > projects using kdelibs/, i.e. it shouldn't be used in automoc. The macro
> > is in kdelibs/cmake/modules/MacroAddFileDependencies.cmake, you can just
> > copy it.
>
> Hmm, I found the macro also in the cmake installation dir as the FindQt4
> shipping with cmake also uses it.
>
> > But, why is this dependency required now ? Currently the source files
> > don't depend on the automoc-generated file and it works ?
>
> Yes it works most of the time except for make target/fast there's a race
> and it breaks sometimes.
> So actually this part of the patch is not directly related to the
> automoc4_init change.

I had a closer look at the automoc4 stuff now.
I think there are some issues:
the change to one global target alone isn't enough, additionally it needs the 
add_dependencies() calls in the kde4_add_executable/library() etc. calls 
added.

automoc4 is still called twice for every target. The problem is here:
      add_custom_command(OUTPUT ${_automoc_source}
         COMMAND ${AUTOMOC4_EXECUTABLE}
         ${_automoc_source}
         ${CMAKE_CURRENT_SOURCE_DIR}
         ${CMAKE_CURRENT_BINARY_DIR}
         ${QT_MOC_EXECUTABLE}
         ${CMAKE_COMMAND}
         --touch
         DEPENDS ${_automoc_source}.files ${_AUTOMOC4_EXECUTABLE_DEP}
         COMMENT ""
         VERBATIM
         )

This says that the command will regenerate ${_automoc_source} if 
${_automoc_source}.files changes. But it doesn't do that, it only does it if 
${_automoc_source} would change (which makes sense). 
But due to this it is always considered out-of-date by make.

OTOH if it would be regenerated, then it would have to be compiled every time 
and the targets would have to be linked every time, which would be much 
worse.

I measured the times again on my (new) system:

make plasma (when there is nothing to do) now takes 5.1 seconds (was 11 sec on 
my old machine).
cmake time for kdelibs (time make rebuild_cache): 6.9 sec

With your patch (and the dependencies to automoc4_init added in 
KDE4Macros.cmake, but without the add_file_dependencies()), time for make 
goes up a little bit: 5.3 seconds 
This was surprising, since I expected it to be less due to the removed sleep() 
calls.

I then had a look at the Windows version, i.e. an additional _automoc target 
for each target. It was actually a bit faster here (build time): 4.7 seconds

With the attached slightly modified Autmoc4Config.cmake that time went down to 
4.4 sec (that's already 10% from the original). automoc4 is called only once 
per target. 
The modification excludes the _automoc targets from ALL (not necessary if the 
add_dependencies() are added) and removes the dependencies of the target, so 
it is executed always without checking the date of so many files, which 
brings the speed up).
And it's IMO much easier to understand.

cmake time for kdelibs (time make rebuild_cache): 7.6 sec
So this is 0.7 sec slower (but this happens less often than building)

So, what do we see ?
Hmm.
Doubling the number of targets increases cmake time. 
Executing automoc4 only half as often reduced make time. Also no surprise.

With these numbers I'm slightly in favor of using the one-automoc-target per 
target approach (with a bit of cmake logic we could do this without requiring 
the newer automoc4 version).

Alex

P.S. some time ago you removed some code in automoc which did something in 
multiple parallel processes. Was this for running multiple moc's at once ?
Hmm, now that I have 4 cores I could make good use of that :-)
We could try to figure out the number of CPUs (e.g. using sysconfig()), and 
then run that much mocs. Do you know whether the problem might be fixed in 
current Qt ?
-------------- next part --------------


get_filename_component(_AUTOMOC4_CURRENT_DIR  "${CMAKE_CURRENT_LIST_FILE}" PATH)

# set the automoc version number
include(${_AUTOMOC4_CURRENT_DIR}/Automoc4Version.cmake)

# are we in the source tree or already installed ?
if(EXISTS ${_AUTOMOC4_CURRENT_DIR}/kde4automoc.cpp)
   get_target_property(AUTOMOC4_EXECUTABLE automoc4 LOCATION)
   # this dependency is required to make parallel builds of kdesupport work:
   set(_AUTOMOC4_EXECUTABLE_DEP automoc4)
else(EXISTS ${_AUTOMOC4_CURRENT_DIR}/kde4automoc.cpp)
   get_filename_component(_AUTOMOC4_BIN_DIR  "${_AUTOMOC4_CURRENT_DIR}" PATH)
   get_filename_component(_AUTOMOC4_BIN_DIR  "${_AUTOMOC4_BIN_DIR}" PATH)
   find_program(AUTOMOC4_EXECUTABLE automoc4 PATHS  "${_AUTOMOC4_BIN_DIR}/bin" NO_DEFAULT_PATH)
   set(_AUTOMOC4_EXECUTABLE_DEP)
   mark_as_advanced(AUTOMOC4_EXECUTABLE)
endif(EXISTS ${_AUTOMOC4_CURRENT_DIR}/kde4automoc.cpp)


macro (AUTOMOC4_MOC_HEADERS _target_NAME)
   set (_headers_to_moc)
   foreach (_current_FILE ${ARGN})
      get_filename_component(_suffix "${_current_FILE}" EXT)
      if (".h" STREQUAL "${_suffix}" OR ".hpp" STREQUAL "${_suffix}" OR ".hxx" STREQUAL "${_suffix}" OR ".H" STREQUAL "${_suffix}")
         list(APPEND _headers_to_moc ${_current_FILE})
      else (".h" STREQUAL "${_suffix}" OR ".hpp" STREQUAL "${_suffix}" OR ".hxx" STREQUAL "${_suffix}" OR ".H" STREQUAL "${_suffix}")
         message(STATUS "AUTOMOC4_MOC_HEADERS: ignoring non-header file ${_current_FILE}")
      endif (".h" STREQUAL "${_suffix}" OR ".hpp" STREQUAL "${_suffix}" OR ".hxx" STREQUAL "${_suffix}" OR ".H" STREQUAL "${_suffix}")
   endforeach (_current_FILE)
   # need to create moc_<filename>.cpp file using automoc4
   # and add it to the target
   if(_headers_to_moc)
       set(_automoc4_headers_${_target_NAME} "${_headers_to_moc}")
       set(_automoc4_headers_${_target_NAME}_automoc "${_headers_to_moc}")
   endif(_headers_to_moc)
endmacro (AUTOMOC4_MOC_HEADERS)


macro(AUTOMOC4 _target_NAME _SRCS)
   set(_moc_files)

   # first list all explicitly set headers
   foreach(_header_to_moc ${_automoc4_headers_${_target_NAME}} )
      get_filename_component(_abs_header ${_header_to_moc} ABSOLUTE)
      list(APPEND _moc_files ${_abs_header})
   endforeach(_header_to_moc)

   # now add all the sources for the automoc
   foreach (_current_FILE ${${_SRCS}})
      get_filename_component(_abs_current_FILE "${_current_FILE}" ABSOLUTE)
      get_source_file_property(_skip      "${_abs_current_FILE}" SKIP_AUTOMOC)
      get_source_file_property(_generated "${_abs_current_FILE}" GENERATED)

      if(NOT  _generated  AND NOT  _skip)
         get_filename_component(_suffix "${_current_FILE}" EXT)
         # skip every source file that's not C++
         if(_suffix STREQUAL ".cpp" OR _suffix STREQUAL ".cc" OR _suffix STREQUAL ".cxx" OR _suffix STREQUAL ".C")
             list(APPEND _moc_files ${_abs_current_FILE})
         endif(_suffix STREQUAL ".cpp" OR _suffix STREQUAL ".cc" OR _suffix STREQUAL ".cxx" OR _suffix STREQUAL ".C")
      endif(NOT  _generated  AND NOT  _skip)
   endforeach (_current_FILE)

   if(_moc_files)
      set(_automoc_source "${CMAKE_CURRENT_BINARY_DIR}/${_target_NAME}_automoc.cpp")
      get_directory_property(_moc_incs INCLUDE_DIRECTORIES)
      get_directory_property(_moc_defs DEFINITIONS)
      get_directory_property(_moc_cdefs COMPILE_DEFINITIONS)

      # configure_file replaces _moc_files, _moc_incs, _moc_cdefs and _moc_defs
      configure_file(${_AUTOMOC4_CURRENT_DIR}/automoc4.files.in ${_automoc_source}.files)

      add_custom_command(OUTPUT ${_automoc_source}
         COMMAND ${AUTOMOC4_EXECUTABLE}
         ${_automoc_source}
         ${CMAKE_CURRENT_SOURCE_DIR}
         ${CMAKE_CURRENT_BINARY_DIR}
         ${QT_MOC_EXECUTABLE}
         ${CMAKE_COMMAND}
         --touch
         DEPENDS ${_automoc_source}.files ${_AUTOMOC4_EXECUTABLE_DEP}
         COMMENT ""
         VERBATIM
         )
      set(${_SRCS} ${_automoc_source} ${${_SRCS}})
   endif(_moc_files)
endmacro(AUTOMOC4)

macro(ADD_AUTOMOC4_TARGET _target_NAME _SRCS)
   set(_moc_files)
   set(_moc_headers)

   # first list all explicitly set headers
   foreach(_header_to_moc ${_automoc4_headers_${_target_NAME}} )
      get_filename_component(_abs_header ${_header_to_moc} ABSOLUTE)
      list(APPEND _moc_files ${_abs_header})
      list(APPEND _moc_headers ${_abs_header})
   endforeach(_header_to_moc)

   # now add all the sources for the automoc
   foreach (_current_FILE ${${_SRCS}})
      get_filename_component(_abs_current_FILE "${_current_FILE}" ABSOLUTE)
      get_source_file_property(_skip      "${_abs_current_FILE}" SKIP_AUTOMOC)
      get_source_file_property(_generated "${_abs_current_FILE}" GENERATED)

      if(NOT  _generated  AND NOT  _skip)
         get_filename_component(_suffix "${_current_FILE}" EXT)
         # skip every source file that's not C++
         if(_suffix STREQUAL ".cpp" OR _suffix STREQUAL ".cc" OR _suffix STREQUAL ".cxx" OR _suffix STREQUAL ".C")
             get_filename_component(_basename "${_current_FILE}" NAME_WE)
             get_filename_component(_abs_path "${_abs_current_FILE}" PATH)
             set(_header "${_abs_path}/${_basename}.h")
             if(EXISTS "${_header}")
                list(APPEND _moc_headers ${_header})
             endif(EXISTS "${_header}")
             set(_pheader "${_abs_path}/${_basename}_p.h")
             if(EXISTS "${_pheader}")
                list(APPEND _moc_headers ${_pheader})
             endif(EXISTS "${_pheader}")
             list(APPEND _moc_files ${_abs_current_FILE})
         endif(_suffix STREQUAL ".cpp" OR _suffix STREQUAL ".cc" OR _suffix STREQUAL ".cxx" OR _suffix STREQUAL ".C")
      endif(NOT  _generated  AND NOT  _skip)
   endforeach (_current_FILE)

   if(_moc_files)
      set(_automoc_source "${CMAKE_CURRENT_BINARY_DIR}/${_target_NAME}.cpp")
      set(_automoc_dotFiles "${CMAKE_CURRENT_BINARY_DIR}/${_target_NAME}.cpp.files")
      get_directory_property(_moc_incs INCLUDE_DIRECTORIES)
      get_directory_property(_moc_defs DEFINITIONS)
      get_directory_property(_moc_cdefs COMPILE_DEFINITIONS)

      # configure_file replaces _moc_files, _moc_incs, _moc_cdefs and _moc_defs
      configure_file(${_AUTOMOC4_CURRENT_DIR}/automoc4.files.in ${_automoc_dotFiles})

      add_custom_target(${_target_NAME}
#         ALL
         COMMAND ${AUTOMOC4_EXECUTABLE}
         ${_automoc_source}
         ${CMAKE_CURRENT_SOURCE_DIR}
         ${CMAKE_CURRENT_BINARY_DIR}
         ${QT_MOC_EXECUTABLE}
         ${CMAKE_COMMAND}
#         DEPENDS ${_automoc_dotFiles} ${_AUTOMOC4_EXECUTABLE_DEP} ${_moc_headers} ${${_SRCS}}
         COMMENT ""
         VERBATIM
         )
      set_source_files_properties(${_automoc_source} PROPERTIES GENERATED TRUE)
      set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${_automoc_source})
      set(${_SRCS} ${_automoc_source} ${${_SRCS}})
   endif(_moc_files)
endmacro(ADD_AUTOMOC4_TARGET)

macro(AUTOMOC4_ADD_EXECUTABLE _target_NAME)
   set(_SRCS ${ARGN})

   set(_add_executable_param)
   foreach(_argName "WIN32" "MACOSX_BUNDLE" "EXCLUDE_FROM_ALL")
      list(FIND _SRCS ${_argName} _index)
      if(_index GREATER -1)
         list(APPEND _add_executable_param ${_argName})
         list(REMOVE_AT _SRCS ${_index})
      endif(_index GREATER -1)
   endforeach(_argName)

   if(MSVC)
      add_automoc4_target("${_target_NAME}_automoc" _SRCS)
   else(MSVC)
      automoc4(${_target_NAME} _SRCS)
   endif(MSVC)
   add_executable(${_target_NAME} ${_add_executable_param} ${_SRCS})
   if(MSVC)
      add_dependencies(${_target_NAME} "${_target_NAME}_automoc")
   endif(MSVC)
endmacro(AUTOMOC4_ADD_EXECUTABLE)

macro(AUTOMOC4_ADD_LIBRARY _target_NAME)
   set(_SRCS ${ARGN})

   set(_add_executable_param)
   foreach(_argName "STATIC" "SHARED" "MODULE" "EXCLUDE_FROM_ALL")
      list(FIND _SRCS ${_argName} _index)
      if(_index GREATER -1)
         list(APPEND _add_executable_param ${_argName})
         list(REMOVE_AT _SRCS ${_index})
      endif(_index GREATER -1)
   endforeach(_argName)

   if(MSVC)
      add_automoc4_target("${_target_NAME}_automoc" _SRCS)
   else(MSVC)
      automoc4(${_target_NAME} _SRCS)
   endif(MSVC)
   add_library(${_target_NAME} ${_add_executable_param} ${_SRCS})
   if(MSVC)
      add_dependencies(${_target_NAME} "${_target_NAME}_automoc")
   endif(MSVC)
endmacro(AUTOMOC4_ADD_LIBRARY)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: KDE4Macros.cmake.automoc.patch
Type: text/x-diff
Size: 3062 bytes
Desc: not available
Url : http://mail.kde.org/pipermail/kde-buildsystem/attachments/20081130/640647c5/attachment.bin 


More information about the Kde-buildsystem mailing list