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