Index: cmake/modules/TableGen.cmake =================================================================== --- cmake/modules/TableGen.cmake +++ cmake/modules/TableGen.cmake @@ -25,7 +25,7 @@ file(RELATIVE_PATH ofn_rel ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}) set(additional_cmdline - -o ${ofn_rel}.tmp + -o ${ofn_rel} -d ${ofn_rel}.d WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d @@ -36,7 +36,7 @@ file(GLOB local_tds "*.td") file(GLOB_RECURSE global_tds "${LLVM_MAIN_INCLUDE_DIR}/llvm/*.td") set(additional_cmdline - -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn} ) endif() @@ -69,9 +69,12 @@ # dependency twice in the result file when # ("${${project}_TABLEGEN_TARGET}" STREQUAL "${${project}_TABLEGEN_EXE}") # but lets us having smaller and cleaner code here. - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - # Generate tablegen output in a temporary file. + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} + # Only update the real output file if there are any differences. + # This prevents recompilation of all the files depending on it if there + # aren't any. + "--write-if-changed" ${LLVM_TABLEGEN_FLAGS} ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} ${additional_cmdline} @@ -83,20 +86,9 @@ ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} COMMENT "Building ${ofn}..." ) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} - # Only update the real output file if there are any differences. - # This prevents recompilation of all the files depending on it if there - # aren't any. - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - ${CMAKE_CURRENT_BINARY_DIR}/${ofn} - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - COMMENT "Updating ${ofn}..." - ) # `make clean' must remove all those generated files: - set_property(DIRECTORY APPEND - PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn}.tmp ${ofn}) + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn}) set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn} PARENT_SCOPE) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} PROPERTIES Index: lib/TableGen/Main.cpp =================================================================== --- lib/TableGen/Main.cpp +++ lib/TableGen/Main.cpp @@ -46,6 +46,9 @@ IncludeDirs("I", cl::desc("Directory of include files"), cl::value_desc("directory"), cl::Prefix); +static cl::opt +WriteIfChanged("write-if-changed", cl::desc("Only write output if it changed")); + static int reportError(const char *ProgName, Twine Msg) { errs() << ProgName << ": " << Msg; errs().flush(); @@ -96,8 +99,22 @@ if (Parser.ParseFile()) return 1; + // Write output to memory. + std::string OutString; + raw_string_ostream Out(OutString); + if (MainFn(Out, Records)) + return 1; + + // See if the output already exists on disk and if so if it's identical to + // what we'd write now. Exit early if not and --write-if-changed was passed. + auto MBOrErr = MemoryBuffer::getFile(OutputFilename); + bool OutputChanged = + MBOrErr.getError() || std::move(MBOrErr.get())->getBuffer() != Out.str(); + if (!OutputChanged && WriteIfChanged) + return 0; + std::error_code EC; - ToolOutputFile Out(OutputFilename, EC, sys::fs::F_Text); + ToolOutputFile OutFile(OutputFilename, EC, sys::fs::F_Text); if (EC) return reportError(argv0, "error opening " + OutputFilename + ":" + EC.message() + "\n"); @@ -105,14 +122,12 @@ if (int Ret = createDependencyFile(Parser, argv0)) return Ret; } - - if (MainFn(Out.os(), Records)) - return 1; + OutFile.os() << Out.str(); if (ErrorsPrinted > 0) return reportError(argv0, Twine(ErrorsPrinted) + " errors.\n"); // Declare success. - Out.keep(); + OutFile.keep(); return 0; }