From 126c6ead7707ac29f3b2fa779752025c7cc0da32 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Tue, 9 Aug 2011 09:18:37 +0200 Subject: Add the cmake module required currently for automoc Alex --- Modules/Automoc.cmake | 158 ++++++++++++++++++++++++++++++++++++++ Modules/AutomocInfo.cmake.in | 13 ++++ Source/cmAddExecutableCommand.cxx | 30 +++++++- Source/cmQtAutomoc.cxx | 126 ++++++++++++++++++++++++++++++ Source/cmQtAutomoc.h | 6 ++ Source/cmake.cxx | 7 ++ Source/cmake.h | 1 + 7 files changed, 340 insertions(+), 1 deletion(-) create mode 100644 Modules/Automoc.cmake create mode 100644 Modules/AutomocInfo.cmake.in diff --git a/Modules/Automoc.cmake b/Modules/Automoc.cmake new file mode 100644 index 0000000..1e77c96 --- /dev/null +++ b/Modules/Automoc.cmake @@ -0,0 +1,158 @@ + +# AUTOMOC4_MOC_HEADERS( header1.h header2.h ...) +# Use this to add more header files to be processed with automoc4. +# +# AUTOMOC4_ADD_EXECUTABLE( src1 src2 ...) +# This macro does the same as ADD_EXECUTABLE, but additionally +# adds automoc4 handling for all source files. +# +# AUTOMOC4_ADD_LIBRARY( src1 src2 ...) +# This macro does the same as ADD_LIBRARY, but additionally +# adds automoc4 handling for all source files. + +# Internal helper macro, may change or be removed anytime: +# _ADD_AUTOMOC4_TARGET( ) +# +# Since version 0.9.88: +# The following two macros are only to be used for KDE4 projects +# and do something which makes sure automoc4 works for KDE. Don't +# use them anywhere else. See kdelibs/cmake/modules/KDE4Macros.cmake. +# _AUTOMOC4_KDE4_PRE_TARGET_HANDLING( ) +# _AUTOMOC4_KDE4_POST_TARGET_HANDLING() + +# Copyright (C) 2007 Matthias Kretz +# Copyright (C) 2008-2009 Alexander Neundorf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +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_.cpp file using automoc4 + # and add it to the target + if(_headers_to_moc) + set(_automoc4_headers_${_target_NAME} "${_headers_to_moc}") + endif(_headers_to_moc) +endmacro (AUTOMOC4_MOC_HEADERS) + + +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_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" OR _suffix STREQUAL ".mm") + list(APPEND _moc_files ${_abs_current_FILE}) + endif(_suffix STREQUAL ".cpp" OR _suffix STREQUAL ".cc" OR _suffix STREQUAL ".cxx" OR _suffix STREQUAL ".C" OR _suffix STREQUAL ".mm") + endif(NOT _generated AND NOT _skip) + endforeach (_current_FILE) + + if(_moc_files OR _moc_headers) + set(_automoc_source "${CMAKE_CURRENT_BINARY_DIR}/${_target_NAME}.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 + set(_automocTargetDir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_target_NAME}.dir/" ) + set(AM_TARGET_NAME ${_target_NAME}) + configure_file(${CMAKE_ROOT}/Modules/AutomocInfo.cmake.in ${_automocTargetDir}/AutomocInfo.cmake @ONLY) + + add_custom_target(${_target_NAME} + COMMAND ${CMAKE_COMMAND} -E cmake_automoc "${_automocTargetDir}" ) + + set_source_files_properties(${_automoc_source} PROPERTIES GENERATED TRUE) + get_directory_property(_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES) + list(APPEND _extra_clean_files "${_automoc_source}") + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${_extra_clean_files}") + set(${_SRCS} ${_automoc_source} ${${_SRCS}}) + endif(_moc_files OR _moc_headers) +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) + + _add_automoc4_target("${_target_NAME}_automoc" _SRCS) + add_executable(${_target_NAME} ${_add_executable_param} ${_SRCS}) + add_dependencies(${_target_NAME} "${_target_NAME}_automoc") + +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) + + _add_automoc4_target("${_target_NAME}_automoc" _SRCS) + add_library(${_target_NAME} ${_add_executable_param} ${_SRCS}) + add_dependencies(${_target_NAME} "${_target_NAME}_automoc") +endmacro(AUTOMOC4_ADD_LIBRARY) + + +macro(_AUTOMOC4_KDE4_PRE_TARGET_HANDLING _target _srcs) + _add_automoc4_target("${_target}_automoc" ${_srcs}) +endmacro(_AUTOMOC4_KDE4_PRE_TARGET_HANDLING) + + +macro(_AUTOMOC4_KDE4_POST_TARGET_HANDLING _target) + add_dependencies(${_target} "${_target}_automoc") +endmacro(_AUTOMOC4_KDE4_POST_TARGET_HANDLING) diff --git a/Modules/AutomocInfo.cmake.in b/Modules/AutomocInfo.cmake.in new file mode 100644 index 0000000..2dc3aa2 --- /dev/null +++ b/Modules/AutomocInfo.cmake.in @@ -0,0 +1,13 @@ +set(AM_SOURCES "@_moc_files@" ) +set(AM_HEADERS "@_moc_headers@" ) +set(AM_MOC_COMPILE_DEFINITIONS "@_moc_compile_defs@") +set(AM_MOC_DEFINITIONS "@_moc_defs@") +set(AM_MOC_INCLUDES "@_moc_incs@") +set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") +set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") +set(AM_QT_MOC_EXECUTABLE "@QT_MOC_EXECUTABLE@") +set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") +set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") +set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" ) +set(AM_TARGET_NAME "@_moc_target_name@") diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index a625c47..9710d20 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -10,6 +10,7 @@ See the License for more information. ============================================================================*/ #include "cmAddExecutableCommand.h" +#include "cmQtAutomoc.h" // cmExecutableCommand bool cmAddExecutableCommand @@ -29,6 +30,7 @@ bool cmAddExecutableCommand bool use_macbundle = false; bool excludeFromAll = false; bool importTarget = false; + bool doAutomoc = false; while ( s != args.end() ) { if (*s == "WIN32") @@ -41,6 +43,11 @@ bool cmAddExecutableCommand ++s; use_macbundle = true; } + else if ( *s == "AUTOMOC" ) + { + ++s; + doAutomoc = true; + } else if(*s == "EXCLUDE_FROM_ALL") { ++s; @@ -58,12 +65,18 @@ bool cmAddExecutableCommand } // Special modifiers are not allowed with IMPORTED signature. - if(importTarget && (use_win32 || use_macbundle || excludeFromAll)) + if(importTarget + && (use_win32 || use_macbundle || excludeFromAll || doAutomoc)) { if(use_win32) { this->SetError("may not be given WIN32 for an IMPORTED target."); } + else if(doAutomoc) + { + this->SetError( + "may not be given AUTOMOC for an IMPORTED target."); + } else if(use_macbundle) { this->SetError( @@ -113,6 +126,14 @@ bool cmAddExecutableCommand } std::vector srclists(s, args.end()); + cmQtAutomoc* automoc = 0; + if ( doAutomoc ) + { + automoc = new cmQtAutomoc; + automoc->SetupAutomocTarget(this->Makefile, exename.c_str(), srclists); + } + + cmTarget* tgt = this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll); if ( use_win32 ) @@ -124,5 +145,12 @@ bool cmAddExecutableCommand tgt->SetProperty("MACOSX_BUNDLE", "ON"); } + if ( automoc ) + { + automoc->AddTargetDependency(this->Makefile, tgt); + delete automoc; + automoc = 0; + } + return true; } diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index 5494b2a..1431551 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -1,6 +1,7 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmQtAutomoc.h" @@ -16,6 +17,131 @@ cmQtAutomoc::cmQtAutomoc() } +void cmQtAutomoc::SetupAutomocTarget(cmMakefile* makefile, + const char* targetName, + std::vector& srcs) +{ + // don't do anything if there is no Qt4: + std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajorVersion != "4") + { + return; + } + + std::string automocTargetName = targetName; + automocTargetName += "_automoc"; + + std::string targetDir = makefile->GetCurrentOutputDirectory(); + targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); + targetDir += "/"; + targetDir += automocTargetName; + targetDir += ".dir/"; + + cmCustomCommandLine currentLine; + currentLine.push_back(makefile->GetCMakeInstance()->GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_automoc"); + currentLine.push_back(targetDir); + + cmCustomCommandLines commandLines; + commandLines.push_back(currentLine); + + std::string workingDirectory = cmSystemTools::CollapseFullPath( + "", makefile->GetCurrentOutputDirectory()); + + std::vector depends; + + cmTarget* target = makefile->AddUtilityCommand(automocTargetName.c_str(), + true, + workingDirectory.c_str(), depends, + commandLines, false, "Automoc target"); + + std::string _moc_files; + std::string _moc_headers; + const char* sepFiles = ""; + const char* sepHeaders = ""; + for(std::vector::const_iterator fileIt = srcs.begin(); + fileIt != srcs.end(); + ++fileIt) + { + std::string absFile = cmSystemTools::CollapseFullPath( + fileIt->c_str(), makefile->GetCurrentDirectory()); + + bool skip = false; + bool generated = false; + cmSourceFile* sf = makefile->GetSource(absFile.c_str()); + if (sf) + { + skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); + generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")); + } + + if ((skip==false) && (generated == false)) + { + std::string ext = cmSystemTools::GetFilenameExtension(fileIt->c_str()); + cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat(ext.c_str()); + if (fileType == cmSystemTools::CXX_FILE_FORMAT) + { + _moc_files += sepFiles; + _moc_files += absFile; + sepFiles = ";"; + } + else if (fileType == cmSystemTools::HEADER_FILE_FORMAT) + { + _moc_headers += sepHeaders; + _moc_headers += absFile; + sepHeaders = ";"; + } + } + } + + std::string _moc_incs = makefile->GetProperty("INCLUDE_DIRECTORIES"); + std::string _moc_defs = makefile->GetProperty("DEFINITIONS"); + std::string _moc_compile_defs = makefile->GetProperty("COMPILE_DEFINITIONS"); + // forget the variables added here afterwards again: + cmMakefile::ScopePushPop varScope(makefile); + static_cast(varScope); + + makefile->AddDefinition("_moc_target_name", automocTargetName.c_str()); + makefile->AddDefinition("_moc_incs", _moc_incs.c_str()); + makefile->AddDefinition("_moc_defs", _moc_defs.c_str()); + makefile->AddDefinition("_moc_compile_defs", _moc_compile_defs.c_str()); + makefile->AddDefinition("_moc_files", _moc_files.c_str()); + makefile->AddDefinition("_moc_headers", _moc_headers.c_str()); + + const char* cmakeRoot = makefile->GetDefinition("CMAKE_ROOT"); + std::string inputFile = cmakeRoot; + inputFile += "/Modules/AutomocInfo.cmake.in"; + std::string outputFile = targetDir; + outputFile += "/AutomocInfo.cmake"; + makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), + false, true, false); + + std::string mocCppFile = makefile->GetCurrentOutputDirectory(); + mocCppFile += "/"; + mocCppFile += automocTargetName; + mocCppFile += ".cpp"; + makefile->GetOrCreateSource(mocCppFile.c_str(), true); + srcs.push_back(mocCppFile); + +} + + +void cmQtAutomoc::AddTargetDependency(cmMakefile* makefile, cmTarget* target) +{ + // don't do anything if there is no Qt4: + std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajorVersion != "4") + { + return; + } + + std::string automocTargetName = target->GetName(); + automocTargetName += "_automoc"; + target->AddUtility(automocTargetName.c_str()); +} + + bool cmQtAutomoc::Run(const char* targetDirectory) { cmake cm; diff --git a/Source/cmQtAutomoc.h b/Source/cmQtAutomoc.h index 891b47a..e573610 100644 --- a/Source/cmQtAutomoc.h +++ b/Source/cmQtAutomoc.h @@ -10,6 +10,12 @@ public: cmQtAutomoc(); bool Run(const char* targetDirectory); + void SetupAutomocTarget(cmMakefile* makefile, + const char* targetName, + std::vector& srcs); + + void AddTargetDependency(cmMakefile* makefile, cmTarget* target); + private: cmGlobalGenerator* CreateGlobalGenerator(cmake* cm, const char* targetDirectory); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 06229e0..c5eff1c 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2927,6 +2927,13 @@ const char* cmake::GetCPackCommand() return this->CPackCommand.c_str(); } + +const char* cmake::GetCMakeCommand() +{ + return this->CMakeCommand.c_str(); +} + + void cmake::MarkCliAsUsed(const std::string& variable) { this->UsedCliVariables[variable] = true; diff --git a/Source/cmake.h b/Source/cmake.h index f2a2ae3..09f6c37 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -301,6 +301,7 @@ class cmake */ const char* GetCTestCommand(); const char* GetCPackCommand(); + const char* GetCMakeCommand(); // Do we want debug output during the cmake run. bool GetDebugOutput() { return this->DebugOutput; } -- cgit v0.12