diff options
Diffstat (limited to 'Source')
105 files changed, 2917 insertions, 1993 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 16b9ea1..ae5b03f 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -327,6 +327,8 @@ set(SRCS cmPropertyDefinitionMap.h cmPropertyMap.cxx cmPropertyMap.h + cmQtAutoGeneratorInitializer.cxx + cmQtAutoGeneratorInitializer.h cmQtAutoGenerators.cxx cmQtAutoGenerators.h cmRST.cxx @@ -502,6 +504,10 @@ if (WIN32) cmGhsMultiGpj.cxx cmGhsMultiGpj.h ) + + # Add a manifest file to executables on Windows to allow for + # GetVersion to work properly on Windows 8 and above. + set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake.version.manifest) endif() endif () @@ -531,7 +537,7 @@ set(SRCS ${SRCS} if(WIN32 AND NOT CYGWIN) set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501) - add_executable(cmcldeps cmcldeps.cxx) + add_executable(cmcldeps cmcldeps.cxx ${MANIFEST_FILE}) target_link_libraries(cmcldeps CMakeLib) install(TARGETS cmcldeps DESTINATION bin) endif() @@ -720,15 +726,15 @@ if(APPLE) endif() # Build CMake executable -add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h) +add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE}) target_link_libraries(cmake CMakeLib) # Build CTest executable -add_executable(ctest ctest.cxx) +add_executable(ctest ctest.cxx ${MANIFEST_FILE}) target_link_libraries(ctest CTestLib) # Build CPack executable -add_executable(cpack CPack/cpack.cxx) +add_executable(cpack CPack/cpack.cxx ${MANIFEST_FILE}) target_link_libraries(cpack CPackLib) # Curses GUI diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index de69a15..fef0b2e 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 3) -set(CMake_VERSION_PATCH 20150911) -#set(CMake_VERSION_RC 1) +set(CMake_VERSION_MINOR 4) +set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_RC 2) diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 58bd947..70de757 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -78,7 +78,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(cmArchiveWrite& archive, std::string rp = filePrefix + *fileIt; cmCPackLogger(cmCPackLog::LOG_DEBUG,"Adding file: " << rp << std::endl); - archive.Add(rp); + archive.Add(rp, 0, 0, false); if (!archive) { cmCPackLogger(cmCPackLog::LOG_ERROR, "ERROR while packaging files: " @@ -284,7 +284,7 @@ int cmCPackArchiveGenerator::PackageFiles() // Get the relative path to the file std::string rp = cmSystemTools::RelativePath(toplevel.c_str(), fileIt->c_str()); - archive.Add(rp); + archive.Add(rp, 0, 0, false); if(!archive) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< " diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index f9dfdf6..04efb71 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -95,6 +95,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string initialTopLevel, std::string findExpr(this->GetOption("GEN_WDIR")); findExpr += "/*"; gl.RecurseOn(); + gl.SetRecurseListDirs(true); if ( !gl.FindFiles(findExpr) ) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -222,6 +223,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne() std::string findExpr(this->GetOption("GEN_WDIR")); findExpr += "/*"; gl.RecurseOn(); + gl.SetRecurseListDirs(true); if ( !gl.FindFiles(findExpr) ) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -524,21 +526,24 @@ int cmCPackDebGenerator::createDeb() packageFiles.begin(); fileIt != packageFiles.end(); ++ fileIt ) { - std::string cmd = "\""; - cmd += cmSystemTools::GetCMakeCommand(); - cmd += "\" -E md5sum \""; - cmd += *fileIt; - cmd += "\""; - - std::string output; - int retval = -1; - int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output, - &retval, toplevel.c_str(), this->GeneratorVerbose, 0); - if ( !res || retval ) + // hash only regular files + if( cmSystemTools::FileIsDirectory(*fileIt) + || cmSystemTools::FileIsSymlink(*fileIt)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running cmake -E md5sum " - << cmd << std::endl); + continue; } + + char md5sum[33]; + if(!cmSystemTools::ComputeFileMD5(*fileIt, md5sum)) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of " + << *fileIt << std::endl); + } + + md5sum[32] = 0; + + std::string output(md5sum); + output += " " + *fileIt + "\n"; // debian md5sums entries are like this: // 014f3604694729f3bf19263bac599765 usr/bin/ccmake // thus strip the full path (with the trailing slash) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 92a4b2b..def9fc7 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -367,6 +367,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install directory: " << top << std::endl); gl.RecurseOn(); + gl.SetRecurseListDirs(true); if ( !gl.FindFiles(findExpr) ) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -379,7 +380,11 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( for ( gfit = files.begin(); gfit != files.end(); ++ gfit ) { bool skip = false; - std::string &inFile = *gfit; + std::string inFile = *gfit; + if(cmSystemTools::FileIsDirectory(*gfit)) + { + inFile += '/'; + } for ( regIt= ignoreFilesRegex.begin(); regIt!= ignoreFilesRegex.end(); ++ regIt) @@ -869,6 +874,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cmsys::Glob glB; findExpr += "/*"; glB.RecurseOn(); + glB.SetRecurseListDirs(true); glB.FindFiles(findExpr); filesBefore = glB.GetFiles(); std::sort(filesBefore.begin(),filesBefore.end()); @@ -908,6 +914,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( { cmsys::Glob glA; glA.RecurseOn(); + glA.SetRecurseListDirs(true); glA.FindFiles(findExpr); std::vector<std::string> filesAfter = glA.GetFiles(); std::sort(filesAfter.begin(),filesAfter.end()); @@ -1074,6 +1081,7 @@ int cmCPackGenerator::DoPackage() std::string findExpr = tempDirectory; findExpr += "/*"; gl.RecurseOn(); + gl.SetRecurseListDirs(true); gl.SetRecurseThroughSymlinks(false); if ( !gl.FindFiles(findExpr) ) { diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index b4c0137..fb6cc00 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -166,6 +166,10 @@ bool cmCTestCurl::UploadFile(std::string const& local_file, curlWriteMemoryCallback); ::curl_easy_setopt(this->Curl, CURLOPT_DEBUGFUNCTION, curlDebugCallback); + // Be sure to set Content-Type to satisfy fussy modsecurity rules + struct curl_slist *headers = ::curl_slist_append(NULL, + "Content-Type: text/xml"); + ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, headers); std::vector<char> responseData; std::vector<char> debugData; ::curl_easy_setopt(this->Curl, CURLOPT_FILE, (void *)&responseData); @@ -174,6 +178,8 @@ bool cmCTestCurl::UploadFile(std::string const& local_file, // Now run off and do what you've been told! ::curl_easy_perform(this->Curl); ::fclose(ftpfile); + ::curl_easy_setopt(this->Curl, CURLOPT_HTTPHEADER, NULL); + ::curl_slist_free_all(headers); if ( responseData.size() > 0 ) { diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 4832186..7c7f5df 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -198,6 +198,10 @@ void cmCTestMultiProcessHandler::UnlockResources(int index) { this->LockedResources.erase(*i); } + if (this->Properties[index]->RunSerial) + { + this->SerialTestRunning = false; + } } //--------------------------------------------------------- @@ -451,11 +455,6 @@ bool cmCTestMultiProcessHandler::CheckOutput() this->WriteCheckpoint(test); this->UnlockResources(test); this->RunningCount -= GetProcessorsUsed(test); - if (this->Properties[test]->RunSerial) - { - this->SerialTestRunning = false; - } - delete p; } return true; diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 1e12f15..833cad6 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -338,6 +338,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, CURLcode res; FILE* ftpfile; char error_buffer[1024]; + struct curl_slist *headers = ::curl_slist_append(NULL, + "Content-Type: text/xml"); /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); @@ -420,6 +422,9 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, ::curl_easy_setopt(curl, CURLOPT_PUT, 1); ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); + // Be sure to set Content-Type to satisfy fussy modsecurity rules + ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + std::string local_file = *file; if ( !cmSystemTools::FileExists(local_file.c_str()) ) { @@ -477,6 +482,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, cmCTestLog(this->CTest, ERROR_MESSAGE, " Cannot find file: " << local_file << std::endl); ::curl_easy_cleanup(curl); + ::curl_slist_free_all(headers); ::curl_global_cleanup(); return false; } @@ -621,6 +627,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, << std::endl); } ::curl_easy_cleanup(curl); + ::curl_slist_free_all(headers); ::curl_global_cleanup(); return false; } @@ -630,6 +637,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, " Uploaded: " + local_file << std::endl, this->Quiet); } } + ::curl_slist_free_all(headers); ::curl_global_cleanup(); return true; } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 14067d5..c635430 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -65,6 +65,11 @@ public: void SetMaxIndex(int n) {this->MaxIndex = n;} int GetMaxIndex() {return this->MaxIndex;} + void SetTestOutputSizePassed(int n) + { this->CustomMaximumPassedTestOutputSize = n; } + void SetTestOutputSizeFailed(int n) + { this->CustomMaximumFailedTestOutputSize = n; } + ///! pass the -I argument down void SetTestsToRunInformation(const char*); diff --git a/Source/Checks/cm_c11_thread_local.c b/Source/Checks/cm_c11_thread_local.c new file mode 100644 index 0000000..ab780f2 --- /dev/null +++ b/Source/Checks/cm_c11_thread_local.c @@ -0,0 +1,2 @@ +_Thread_local int i = 42; +int main(void) { return 0; } diff --git a/Source/Checks/cm_c11_thread_local.cmake b/Source/Checks/cm_c11_thread_local.cmake new file mode 100644 index 0000000..6b8d10b --- /dev/null +++ b/Source/Checks/cm_c11_thread_local.cmake @@ -0,0 +1,33 @@ +set(CMake_C11_THREAD_LOCAL_BROKEN 0) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_C11_STANDARD_COMPILE_OPTION) + if(NOT DEFINED CMake_C11_THREAD_LOCAL_WORKS) + message(STATUS "Checking if compiler supports C11 _Thread_local") + try_compile(CMake_C11_THREAD_LOCAL_WORKS + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/cm_c11_thread_local.c + CMAKE_FLAGS -DCMAKE_C_STANDARD=11 + OUTPUT_VARIABLE OUTPUT + ) + if(CMake_C11_THREAD_LOCAL_WORKS AND "${OUTPUT}" MATCHES "error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'") + set_property(CACHE CMake_C11_THREAD_LOCAL_WORKS PROPERTY VALUE 0) + endif() + if(CMake_C11_THREAD_LOCAL_WORKS) + message(STATUS "Checking if compiler supports C11 _Thread_local - yes") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if compiler supports C11 _Thread_local passed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + else() + message(STATUS "Checking if compiler supports C11 _Thread_local - no") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if compiler supports C11 _Thread_local failed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + endif() + endif() + if(NOT CMake_C11_THREAD_LOCAL_WORKS) + set(CMake_C11_THREAD_LOCAL_BROKEN 1) + endif() +endif() diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 67e4aab..6144ddc 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -80,12 +80,13 @@ void cmCursesLongMessageForm::UpdateStatusBar() sprintf(version+sideSpace, "%s", vertmp); version[width] = '\0'; + char fmt_s[] = "%s"; curses_move(y-4,0); attron(A_STANDOUT); - printw(bar); + printw(fmt_s, bar); attroff(A_STANDOUT); curses_move(y-3,0); - printw(version); + printw(fmt_s, version); pos_form_cursor(this->Form); } @@ -101,8 +102,9 @@ void cmCursesLongMessageForm::PrintKeys() char firstLine[512]; sprintf(firstLine, "Press [e] to exit help"); + char fmt_s[] = "%s"; curses_move(y-2,0); - printw(firstLine); + printw(fmt_s, firstLine); pos_form_cursor(this->Form); } diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index be17a9f..a2fc2c0 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -451,24 +451,25 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) } curses_move(y-4,0); + char fmt_s[] = "%s"; char fmt[512] = "Press [enter] to edit option"; if ( process ) { strcpy(fmt, " "); } - printw(fmt); + printw(fmt_s, fmt); curses_move(y-3,0); - printw(firstLine); + printw(fmt_s, firstLine); curses_move(y-2,0); - printw(secondLine); + printw(fmt_s, secondLine); curses_move(y-1,0); - printw(thirdLine); + printw(fmt_s, thirdLine); if (cw) { sprintf(firstLine, "Page %d of %d", cw->GetPage(), this->NumberOfPages); curses_move(0,65-static_cast<unsigned int>(strlen(firstLine))-1); - printw(firstLine); + printw(fmt_s, firstLine); } // } @@ -612,13 +613,13 @@ void cmCursesMainForm::UpdateStatusBar(const char* message) version[width] = '\0'; // Now print both lines + char fmt_s[] = "%s"; curses_move(y-5,0); attron(A_STANDOUT); - char format[] = "%s"; - printw(format, bar); + printw(fmt_s, bar); attroff(A_STANDOUT); curses_move(y-4,0); - printw(version); + printw(fmt_s, version); pos_form_cursor(this->Form); } diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx index acf262f..6eb15c1 100644 --- a/Source/CursesDialog/cmCursesStringWidget.cxx +++ b/Source/CursesDialog/cmCursesStringWidget.cxx @@ -168,17 +168,16 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm, else if ( key == 127 || key == KEY_BACKSPACE ) { - if ( form->curcol > 0 ) - { + FIELD *cur = current_field(form); form_driver(form, REQ_DEL_PREV); - } + if (current_field(form) != cur) + { + set_current_field(form, cur); + } } else if ( key == ctrl('d') ||key == KEY_DC ) { - if ( form->curcol >= 0 ) - { - form_driver(form, REQ_DEL_CHAR); - } + form_driver(form, REQ_DEL_CHAR); } else { @@ -221,6 +220,7 @@ bool cmCursesStringWidget::PrintKeys() } if (this->InEdit) { + char fmt_s[] = "%s"; char firstLine[512]; // Clean the toolbar for(int i=0; i<512; i++) @@ -229,17 +229,16 @@ bool cmCursesStringWidget::PrintKeys() } firstLine[511] = '\0'; curses_move(y-4,0); - printw(firstLine); + printw(fmt_s, firstLine); curses_move(y-3,0); - printw(firstLine); + printw(fmt_s, firstLine); curses_move(y-2,0); - printw(firstLine); + printw(fmt_s, firstLine); curses_move(y-1,0); - printw(firstLine); + printw(fmt_s, firstLine); - sprintf(firstLine, "Editing option, press [enter] to leave edit."); curses_move(y-3,0); - printw(firstLine); + printw(fmt_s, "Editing option, press [enter] to leave edit."); return true; } else diff --git a/Source/CursesDialog/cmCursesWidget.cxx b/Source/CursesDialog/cmCursesWidget.cxx index e5363f4..a12e4c2 100644 --- a/Source/CursesDialog/cmCursesWidget.cxx +++ b/Source/CursesDialog/cmCursesWidget.cxx @@ -49,7 +49,7 @@ void cmCursesWidget::Move(int x, int y, bool isNewPage) void cmCursesWidget::SetValue(const std::string& value) { this->Value = value; - set_field_buffer(this->Field, 0, value.c_str()); + set_field_buffer(this->Field, 0, const_cast<char *>(value.c_str())); } const char* cmCursesWidget::GetValue() diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index ad6a7fb..66fd18b 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -78,9 +78,12 @@ if (Qt5Widgets_FOUND) endif() endif() - if(WIN32 AND TARGET Qt5::Core) + if(TARGET Qt5::Core) get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION) get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH) + if(APPLE) + get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) + endif() endif() else() set(QT_MIN_VERSION "4.4.0") @@ -94,12 +97,6 @@ else() set(CMake_QT_LIBRARIES ${QT_LIBRARIES}) - if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}") - get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) - if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll") - set(Qt_BIN_DIR ${_Qt_BIN_DIR}) - endif() - endif() endif() set(SRCS @@ -155,11 +152,8 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) -add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS}) +add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE}) target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES}) -if(Qt_BIN_DIR) - set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR}) -endif() if(APPLE) file(STRINGS "${CMake_SOURCE_DIR}/Copyright.txt" copyright_line @@ -223,7 +217,7 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) install(CODE " include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\") set(BU_CHMOD_BUNDLE_ITEMS ON) - fixup_bundle(\"${fixup_exe}\" \"${QT_PLUGINS}\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\") + fixup_bundle(\"${fixup_exe}\" \"${QT_PLUGINS}\" \"${Qt_BIN_DIR};${QT_LIBRARY_DIR};${QT_BINARY_DIR}\") " ${COMPONENT}) endif() diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 11e3f34..dc4db63 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -173,7 +173,7 @@ public: */ DumpSymbols(ObjectHeaderType* ih, - FILE* fout) { + FILE* fout, bool is64) { this->ObjectImageHeader = ih; this->SymbolTable = (SymbolTableType*) ((DWORD_PTR)this->ObjectImageHeader @@ -183,6 +183,7 @@ public: GetSectionHeaderOffset(this->ObjectImageHeader); this->ImportFlag = true; this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols; + this->Is64Bit = is64; } /* @@ -287,7 +288,14 @@ public: symbol.erase(posAt); } } - if (symbol[0] == '_') symbol.erase(0,1); + // For 64 bit builds we don't need to remove _ + if(!this->Is64Bit) + { + if (symbol[0] == '_') + { + symbol.erase(0,1); + } + } if (this->ImportFlag) { this->ImportFlag = false; fprintf(this->FileOut,"EXPORTS \n"); @@ -355,6 +363,7 @@ private: PIMAGE_SECTION_HEADER SectionHeaders; ObjectHeaderType* ObjectImageHeader; SymbolTableType* SymbolTable; + bool Is64Bit; }; bool @@ -406,7 +415,8 @@ DumpFile(const char* filename, FILE *fout) * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0; */ DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> - symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout); + symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout, + (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)); symbolDumper.DumpObjFile(); } else { // check for /bigobj format @@ -414,7 +424,8 @@ DumpFile(const char* filename, FILE *fout) (cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase; if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) { DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX> - symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout); + symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout, + (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64)); symbolDumper.DumpObjFile(); } else { printf("unrecognized file format in '%s'\n", filename); diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h index 8f8038f..47455f8 100644 --- a/Source/cmBuildNameCommand.h +++ b/Source/cmBuildNameCommand.h @@ -23,7 +23,6 @@ public: cmExecutionStatus &status); virtual std::string GetName() const {return "build_name";} virtual bool IsScriptable() const { return true; } - virtual bool IsDiscouraged() const { return true; } }; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index b2ad4a8..6e55d89 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2165,7 +2165,46 @@ bool cmCTest::HandleCommandLineArguments(size_t &i, { this->OutputTestOutputOnTestFailure = true; } - + if (this->CheckArgument(arg, "--test-output-size-passed") && + i < args.size() - 1) + { + i++; + long outputSize; + if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) + { + if (cmCTestTestHandler *pCTestTestHandler = + static_cast<cmCTestTestHandler*>(this->TestingHandlers["test"])) + { + pCTestTestHandler->SetTestOutputSizePassed(int(outputSize)); + } + } + else + { + cmCTestLog(this, WARNING, + "Invalid value for '--test-output-size-passed': " << + args[i] << "\n"); + } + } + if (this->CheckArgument(arg, "--test-output-size-failed") && + i < args.size() - 1) + { + i++; + long outputSize; + if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) + { + if (cmCTestTestHandler *pCTestTestHandler = + static_cast<cmCTestTestHandler*>(this->TestingHandlers["test"])) + { + pCTestTestHandler->SetTestOutputSizeFailed(int(outputSize)); + } + } + else + { + cmCTestLog(this, WARNING, + "Invalid value for '--test-output-size-failed': " << + args[i] << "\n"); + } + } if(this->CheckArgument(arg, "-N", "--show-only")) { this->ShowOnly = true; diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 0548c6b..59bc396 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -102,15 +102,6 @@ public: } /** - * This determines if usage of the method is discouraged or not. - * This is currently only used for generating the documentation. - */ - virtual bool IsDiscouraged() const - { - return false; - } - - /** * This is used to avoid including this command * in documentation. This is mainly used by * cmMacroHelperCommand and cmFunctionHelperCommand diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 4840e89..252e231 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -412,3 +412,20 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories() const } return dirs; } + +std::string cmCommonTargetGenerator::GetManifests() +{ + std::vector<cmSourceFile const*> manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + + std::vector<std::string> manifests; + for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin(); + mi != manifest_srcs.end(); ++mi) + { + manifests.push_back(this->Convert((*mi)->GetFullPath(), + this->WorkingDirectory, + cmOutputConverter::SHELL)); + } + + return cmJoin(manifests, " "); +} diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 0a49e12..a4b2c10 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -88,6 +88,7 @@ protected: ByLanguageMap DefinesByLanguage; std::string GetIncludes(std::string const& l); ByLanguageMap IncludesByLanguage; + std::string GetManifests(); std::vector<std::string> GetLinkedTargetDirectories() const; }; diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 7874803..5330acd 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -11,9 +11,14 @@ ============================================================================*/ #include "cmConditionEvaluator.h" +#include "cmOutputConverter.h" -cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile): +cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile, + const cmListFileContext &context, + const cmListFileBacktrace& bt): Makefile(makefile), + ExecutionContext(context), + Backtrace(bt), Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)), Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)), Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057)), @@ -98,6 +103,25 @@ bool cmConditionEvaluator::IsTrue( errorString, status, true); } +cmListFileContext cmConditionEvaluator::GetConditionContext( + cmMakefile* mf, + const cmCommandContext& command, + const std::string& filePath) +{ + cmListFileContext context = + cmListFileContext::FromCommandContext( + command, + filePath); + + if(!mf->GetCMakeInstance()->GetIsInTryCompile()) + { + cmOutputConverter converter(mf->GetStateSnapshot()); + context.FilePath = converter.Convert(context.FilePath, + cmOutputConverter::HOME); + } + return context; +} + //========================================================================= const char* cmConditionEvaluator::GetDefinitionIfUnquoted( cmExpandedCommandArgument const& argument) const @@ -113,7 +137,8 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( if(def && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { - if(!this->Makefile.HasCMP0054AlreadyBeenReported()) + if(!this->Makefile.HasCMP0054AlreadyBeenReported( + this->ExecutionContext)) { std::ostringstream e; e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) << "\n"; @@ -122,7 +147,9 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; - this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile.GetCMakeInstance() + ->IssueMessage(cmake::AUTHOR_WARNING, e.str(), + this->Backtrace); } } @@ -159,7 +186,8 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword, if(isKeyword && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { - if(!this->Makefile.HasCMP0054AlreadyBeenReported()) + if(!this->Makefile.HasCMP0054AlreadyBeenReported( + this->ExecutionContext)) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) << "\n"; @@ -168,7 +196,9 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword, "when the policy is set to NEW. " "Since the policy is not set the OLD behavior will be used."; - this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + this->Makefile.GetCMakeInstance() + ->IssueMessage(cmake::AUTHOR_WARNING, e.str(), + this->Backtrace); } } diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index c4e2d11..8600825 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -22,7 +22,9 @@ class cmConditionEvaluator public: typedef std::list<cmExpandedCommandArgument> cmArgumentList; - cmConditionEvaluator(cmMakefile& makefile); + cmConditionEvaluator(cmMakefile& makefile, + cmListFileContext const& context, + cmListFileBacktrace const& bt); // this is a shared function for both If and Else to determine if the // arguments were valid, and if so, was the response true. If there is @@ -31,6 +33,9 @@ public: std::string &errorString, cmake::MessageType &status); + static cmListFileContext GetConditionContext(cmMakefile* mf, + const cmCommandContext& command, std::string const& filePath); + private: // Filter the given variable definition based on policy CMP0054. const char* GetDefinitionIfUnquoted( @@ -91,6 +96,8 @@ private: cmake::MessageType &status); cmMakefile& Makefile; + cmListFileContext ExecutionContext; + cmListFileBacktrace Backtrace; cmPolicies::PolicyStatus Policy12Status; cmPolicies::PolicyStatus Policy54Status; cmPolicies::PolicyStatus Policy57Status; diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 9411555..3d9c4bf 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -29,7 +29,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) const char* sourceDirectory = argv[2].c_str(); const char* projectName = 0; std::string targetName; - std::vector<std::string> cmakeFlags; + std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0] std::vector<std::string> compileDefs; std::string outputVariable; std::string copyFile; @@ -53,10 +53,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) if(argv[i] == "CMAKE_FLAGS") { doing = DoingCMakeFlags; - // CMAKE_FLAGS is the first argument because we need an argv[0] that - // is not used, so it matches regular command line parsing which has - // the program name as arg 0 - cmakeFlags.push_back(argv[i]); } else if(argv[i] == "COMPILE_DEFINITIONS") { @@ -481,6 +477,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) fprintf(fout, "set(CMAKE_LINK_SEARCH_END_STATIC \"%s\")\n", lssDef); } + /* Set the appropriate policy information for ENABLE_EXPORTS */ + fprintf(fout, "cmake_policy(SET CMP0065 %s)\n", + this->Makefile->GetPolicyStatus(cmPolicies::CMP0065) == + cmPolicies::NEW ? "NEW" : "OLD"); + if(const char *ee = this->Makefile->GetDefinition( + "CMAKE_ENABLE_EXPORTS")) + { + fprintf(fout, "set(CMAKE_ENABLE_EXPORTS %s)\n", ee); + } + /* Put the executable at a known location (for COPY_FILE). */ fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n", this->BinaryDirectory.c_str()); diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h index 23d10f9..adefdf9 100644 --- a/Source/cmExecProgramCommand.h +++ b/Source/cmExecProgramCommand.h @@ -50,12 +50,6 @@ public: */ virtual bool IsScriptable() const { return true; } - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmExecProgramCommand, cmCommand); private: static bool RunCommand(const char* command, std::string& output, diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h index 2ea4e79..81aa21a 100644 --- a/Source/cmExportLibraryDependenciesCommand.h +++ b/Source/cmExportLibraryDependenciesCommand.h @@ -22,7 +22,6 @@ public: virtual bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus &status); virtual std::string GetName() const { return "export_library_dependencies";} - virtual bool IsDiscouraged() const { return true; } virtual void FinalPass(); virtual bool HasFinalPass() const { return true; } diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 7959ffe..fa9b381 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -207,6 +207,10 @@ void cmFindBase::ExpandPaths() { this->FillCMakeEnvironmentPath(); } + } + this->FillUserHintsPath(); + if(!this->NoDefaultPath) + { if(!this->NoSystemEnvironmentPath) { this->FillSystemEnvironmentPath(); @@ -216,8 +220,6 @@ void cmFindBase::ExpandPaths() this->FillCMakeSystemVariablePath(); } } - - this->FillUserHintsPath(); this->FillUserGuessPath(); } diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 9b9071d..64176e7 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1133,6 +1133,10 @@ void cmFindPackageCommand::ComputePrefixes() { this->FillPrefixesCMakeEnvironment(); } + } + this->FillPrefixesUserHints(); + if(!this->NoDefaultPath) + { if(!this->NoSystemEnvironmentPath) { this->FillPrefixesSystemEnvironment(); @@ -1150,7 +1154,6 @@ void cmFindPackageCommand::ComputePrefixes() this->FillPrefixesSystemRegistry(); } } - this->FillPrefixesUserHints(); this->FillPrefixesUserGuess(); this->ComputeFinalPaths(); diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 31b6766..1c350ab 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -13,6 +13,7 @@ #include "cmGeneratorExpressionNode.h" #include "cmGlobalGenerator.h" #include "cmAlgorithms.h" +#include "cmOutputConverter.h" //---------------------------------------------------------------------------- std::string cmGeneratorExpressionNode::EvaluateDependentExpression( @@ -1792,6 +1793,27 @@ static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> targetPdbNodeGroup; //---------------------------------------------------------------------------- +static const struct ShellPathNode : public cmGeneratorExpressionNode +{ + ShellPathNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const + { + if (!cmSystemTools::FileIsFullPath(parameters.front())) + { + reportError(context, content->GetOriginalExpression(), + "\"" + parameters.front() + "\" is not an absolute path."); + return std::string(); + } + cmOutputConverter converter(context->Makefile->GetStateSnapshot()); + return converter.ConvertDirectorySeparatorsForShell(parameters.front()); + } +} shellPathNode; + +//---------------------------------------------------------------------------- const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(const std::string &identifier) { @@ -1846,6 +1868,7 @@ cmGeneratorExpressionNode::GetNode(const std::string &identifier) nodeMap["JOIN"] = &joinNode; nodeMap["LINK_ONLY"] = &linkOnlyNode; nodeMap["COMPILE_LANGUAGE"] = &languageNode; + nodeMap["SHELL_PATH"] = &shellPathNode; } NodeMap::const_iterator i = nodeMap.find(identifier); if (i == nodeMap.end()) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 09387b7..62598f4 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -75,6 +75,7 @@ struct IDLSourcesTag {}; struct ResxTag {}; struct ModuleDefinitionFileTag {}; struct AppManifestTag{}; +struct ManifestsTag{}; struct CertificatesTag{}; struct XamlTag{}; @@ -216,6 +217,10 @@ struct TagVisitor { DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf); } + else if (ext == "manifest") + { + DoAccept<IsSameTag<Tag, ManifestsTag>::Result>::Do(this->Data, sf); + } else if (ext == "pfx") { DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf); @@ -270,6 +275,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->LocalGenerator = lg; this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); + this->GlobalGenerator->ComputeTargetObjectDirectory(this); + CreatePropertyGeneratorExpressions( t->GetIncludeDirectoriesEntries(), t->GetIncludeDirectoriesBacktraces(), @@ -626,6 +633,15 @@ cmGeneratorTarget //---------------------------------------------------------------------------- void cmGeneratorTarget +::GetManifests(std::vector<cmSourceFile const*>& data, + const std::string& config) const +{ + IMPLEMENT_VISIT(Manifests); +} + +//---------------------------------------------------------------------------- +void +cmGeneratorTarget ::GetCertificates(std::vector<cmSourceFile const*>& data, const std::string& config) const { @@ -2204,7 +2220,7 @@ cmGeneratorTarget::GetIncludeDirectories(const std::string& config, "INCLUDE_DIRECTORIES") != debugProperties.end(); - if (this->Makefile->IsConfigured()) + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugIncludesDone = true; } @@ -2351,7 +2367,7 @@ void cmGeneratorTarget::GetCompileOptions(std::vector<std::string> &result, "COMPILE_OPTIONS") != debugProperties.end(); - if (this->Makefile->IsConfigured()) + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileOptionsDone = true; } @@ -2421,7 +2437,7 @@ void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string> &result, "COMPILE_FEATURES") != debugProperties.end(); - if (this->Makefile->IsConfigured()) + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileFeaturesDone = true; } @@ -2489,7 +2505,7 @@ void cmGeneratorTarget::GetCompileDefinitions(std::vector<std::string> &list, "COMPILE_DEFINITIONS") != debugProperties.end(); - if (this->Makefile->IsConfigured()) + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileDefinitionsDone = true; } @@ -3923,7 +3939,7 @@ cmGeneratorTarget::ReportPropertyOrigin(const std::string &p, p) != debugProperties.end(); - if (this->Target->GetMakefile()->IsConfigured()) + if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompatiblePropertiesDone[p] = true; } @@ -4490,7 +4506,7 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages, std::vector<cmGeneratorTarget*> objectLibraries; std::vector<cmSourceFile const*> externalObjects; - if (!this->Makefile->IsConfigured()) + if (!this->GlobalGenerator->GetConfigureDoneCMP0026()) { std::vector<cmTarget*> objectTargets; this->Target->GetObjectLibrariesCMP0026(objectTargets); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 06d9a1f..916f281 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -71,6 +71,8 @@ public: const std::string& config) const; void GetAppManifest(std::vector<cmSourceFile const*>&, const std::string& config) const; + void GetManifests(std::vector<cmSourceFile const*>&, + const std::string& config) const; void GetCertificates(std::vector<cmSourceFile const*>&, const std::string& config) const; void GetXamlSources(std::vector<cmSourceFile const*>&, diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index ee1b192..4a48b5d 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -22,7 +22,7 @@ #include "cmake.h" #include "cmState.h" #include "cmMakefile.h" -#include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorInitializer.h" #include "cmSourceFile.h" #include "cmVersion.h" #include "cmTargetExport.h" @@ -72,6 +72,8 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm) this->ExtraGenerator = 0; this->CurrentMakefile = 0; this->TryCompileOuterMakefile = 0; + + this->ConfigureDoneCMP0026 = false; } cmGlobalGenerator::~cmGlobalGenerator() @@ -433,19 +435,22 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages, { #if defined(_WIN32) && !defined(__CYGWIN__) /* Windows version number data. */ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + OSVERSIONINFOEXW osviex; + ZeroMemory(&osviex, sizeof(osviex)); + osviex.dwOSVersionInfoSize = sizeof(osviex); + #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # pragma warning (push) # pragma warning (disable:4996) #endif - GetVersionEx (&osvi); + GetVersionExW((OSVERSIONINFOW*)&osviex); #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # pragma warning (pop) #endif std::ostringstream windowsVersionString; - windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion; + windowsVersionString << osviex.dwMajorVersion << "." + << osviex.dwMinorVersion << "." + << osviex.dwBuildNumber; windowsVersionString.str(); mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", windowsVersionString.str().c_str()); @@ -1086,6 +1091,18 @@ void cmGlobalGenerator::ClearEnabledLanguages() return this->CMakeInstance->GetState()->ClearEnabledLanguages(); } +void cmGlobalGenerator::CreateLocalGenerators() +{ + cmDeleteAll(this->LocalGenerators); + this->LocalGenerators.clear(); + this->LocalGenerators.reserve(this->Makefiles.size()); + for (std::vector<cmMakefile*>::const_iterator it = this->Makefiles.begin(); + it != this->Makefiles.end(); ++it) + { + this->LocalGenerators.push_back(this->CreateLocalGenerator(*it)); + } +} + void cmGlobalGenerator::Configure() { this->FirstTimeProgress = 0.0f; @@ -1094,8 +1111,6 @@ void cmGlobalGenerator::Configure() cmMakefile* dirMf = new cmMakefile(this, this->GetCMakeInstance()->GetCurrentSnapshot()); this->Makefiles.push_back(dirMf); - cmLocalGenerator *lg = this->CreateLocalGenerator(dirMf); - this->LocalGenerators.push_back(lg); // set the Start directories dirMf->SetCurrentSourceDirectory @@ -1107,9 +1122,12 @@ void cmGlobalGenerator::Configure() this->CMakeInstance->GetHomeOutputDirectory()); // now do it + this->ConfigureDoneCMP0026 = false; dirMf->Configure(); dirMf->EnforceDirectoryLevelRules(); + this->ConfigureDoneCMP0026 = true; + // Put a copy of each global target in every directory. cmTargets globalTargets; this->CreateDefaultGlobalTargets(&globalTargets); @@ -1167,6 +1185,7 @@ void cmGlobalGenerator::Configure() void cmGlobalGenerator::CreateGenerationObjects(TargetTypes targetTypes) { + this->CreateLocalGenerators(); cmDeleteAll(this->GeneratorTargets); this->GeneratorTargets.clear(); this->CreateGeneratorTargets(targetTypes); @@ -1232,30 +1251,23 @@ bool cmGlobalGenerator::Compute() #ifdef CMAKE_BUILD_WITH_CMAKE // Iterate through all targets and set up automoc for those which have // the AUTOMOC, AUTOUIC or AUTORCC property set - AutogensType autogens; - this->CreateQtAutoGeneratorsTargets(autogens); + std::vector<cmTarget const*> autogenTargets = + this->CreateQtAutoGeneratorsTargets(); #endif unsigned int i; - for (i = 0; i < this->LocalGenerators.size(); ++i) - { - this->LocalGenerators[i]->ComputeObjectMaxPath(); - } - // Add generator specific helper commands for (i = 0; i < this->LocalGenerators.size(); ++i) { this->LocalGenerators[i]->AddHelperCommands(); } - this->InitGeneratorTargets(); - #ifdef CMAKE_BUILD_WITH_CMAKE - for (AutogensType::iterator it = autogens.begin(); it != autogens.end(); - ++it) + for (std::vector<cmTarget const*>::iterator it = autogenTargets.begin(); + it != autogenTargets.end(); ++it) { - it->first.SetupAutoGenerateTarget(it->second); + cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*it); } #endif @@ -1391,8 +1403,11 @@ bool cmGlobalGenerator::ComputeTargetDepends() } //---------------------------------------------------------------------------- -void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) +std::vector<const cmTarget*> +cmGlobalGenerator::CreateQtAutoGeneratorsTargets() { + std::vector<const cmTarget*> autogenTargets; + #ifdef CMAKE_BUILD_WITH_CMAKE for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) { @@ -1407,37 +1422,48 @@ void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) { continue; } + if(ti->second.GetType() != cmTarget::EXECUTABLE && + ti->second.GetType() != cmTarget::STATIC_LIBRARY && + ti->second.GetType() != cmTarget::SHARED_LIBRARY && + ti->second.GetType() != cmTarget::MODULE_LIBRARY && + ti->second.GetType() != cmTarget::OBJECT_LIBRARY) + { + continue; + } + if((!ti->second.GetPropertyAsBool("AUTOMOC") + && !ti->second.GetPropertyAsBool("AUTOUIC") + && !ti->second.GetPropertyAsBool("AUTORCC")) + || ti->second.IsImported()) + { + continue; + } + // don't do anything if there is no Qt4 or Qt5Core (which contains moc): + cmMakefile* mf = ti->second.GetMakefile(); + std::string qtMajorVersion = mf->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajorVersion == "") + { + qtMajorVersion = mf->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + } + if (qtMajorVersion != "4" && qtMajorVersion != "5") + { + continue; + } + + cmQtAutoGeneratorInitializer::InitializeAutogenSources(&ti->second); targetNames.push_back(ti->second.GetName()); } for(std::vector<std::string>::iterator ti = targetNames.begin(); ti != targetNames.end(); ++ti) { - cmTarget& target = *this->LocalGenerators[i] + cmTarget* target = this->LocalGenerators[i] ->GetMakefile()->FindTarget(*ti, true); - if(target.GetType() == cmTarget::EXECUTABLE || - target.GetType() == cmTarget::STATIC_LIBRARY || - target.GetType() == cmTarget::SHARED_LIBRARY || - target.GetType() == cmTarget::MODULE_LIBRARY || - target.GetType() == cmTarget::OBJECT_LIBRARY) - { - if((target.GetPropertyAsBool("AUTOMOC") - || target.GetPropertyAsBool("AUTOUIC") - || target.GetPropertyAsBool("AUTORCC")) - && !target.IsImported()) - { - cmQtAutoGenerators autogen; - if(autogen.InitializeAutogenTarget(this->LocalGenerators[i], - &target)) - { - autogens.push_back(std::make_pair(autogen, &target)); - } - } - } + cmQtAutoGeneratorInitializer::InitializeAutogenTarget( + this->LocalGenerators[i], target); + autogenTargets.push_back(target); } } -#else - (void)autogens; #endif + return autogenTargets; } //---------------------------------------------------------------------------- @@ -1530,19 +1556,6 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes, } //---------------------------------------------------------------------------- -void cmGlobalGenerator::InitGeneratorTargets() -{ - for(cmGeneratorTargetsType::iterator ti = - this->GeneratorTargets.begin(); ti != this->GeneratorTargets.end(); ++ti) - { - if (!ti->second->Target->IsImported()) - { - this->ComputeTargetObjectDirectory(ti->second); - } - } -} - -//---------------------------------------------------------------------------- void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes) { // Construct per-target generator information. @@ -1928,12 +1941,6 @@ void cmGlobalGenerator::AddMakefile(cmMakefile *mf) this->CMakeInstance->UpdateProgress("Configuring", prog); } -//---------------------------------------------------------------------------- -void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg) -{ - this->LocalGenerators.push_back(lg); -} - void cmGlobalGenerator::AddInstallComponent(const char* component) { if(component && *component) diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 9fc2d45..ba74c9e 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -41,7 +41,6 @@ class cmTarget; class cmInstallTargetGenerator; class cmInstallFilesGenerator; class cmExportBuildFileGenerator; -class cmQtAutoGenerators; /** \class cmGlobalGenerator * \brief Responsible for overseeing the generation process for the entire tree @@ -124,7 +123,7 @@ public: /** * Try to determine system information, get it from another generator */ - virtual void EnableLanguagesFromGenerator(cmGlobalGenerator *gen, + void EnableLanguagesFromGenerator(cmGlobalGenerator *gen, cmMakefile* mf); /** @@ -186,7 +185,6 @@ public: {this->CurrentMakefile = mf;} void AddMakefile(cmMakefile *mf); - void AddLocalGenerator(cmLocalGenerator *lg); ///! Set an generator for an "external makefile based project" void SetExternalMakefileProjectGenerator( @@ -363,6 +361,8 @@ public: cmFileLockPool& GetFileLockPool() { return FileLockPool; } #endif + bool GetConfigureDoneCMP0026() const { return this->ConfigureDoneCMP0026; } + std::string MakeSilentFlag; protected: typedef std::vector<cmLocalGenerator*> GeneratorVector; @@ -384,9 +384,7 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; - typedef std::vector<std::pair<cmQtAutoGenerators, - cmTarget const*> > AutogensType; - void CreateQtAutoGeneratorsTargets(AutogensType& autogens); + std::vector<cmTarget const*> CreateQtAutoGeneratorsTargets(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; @@ -464,6 +462,8 @@ private: virtual void ForceLinkerLanguages(); + void CreateLocalGenerators(); + void CheckCompilerIdCompatibility(cmMakefile* mf, std::string const& lang) const; @@ -480,7 +480,6 @@ private: cmGeneratorTargetsType GeneratorTargets; friend class cmake; void CreateGeneratorTargets(TargetTypes targetTypes, cmLocalGenerator* lg); - void InitGeneratorTargets(); void CreateGeneratorTargets(TargetTypes targetTypes); void ClearGeneratorMembers(); @@ -520,6 +519,7 @@ protected: bool ForceUnixPaths; bool ToolSupportsColor; bool InstallTargetEnabled; + bool ConfigureDoneCMP0026; }; #endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 120bb03..9d8193b 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -818,6 +818,17 @@ void cmGlobalNinjaGenerator::CloseRulesFileStream() } } +std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path) +{ + cmLocalNinjaGenerator *ng = + static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]); + std::string convPath = ng->Convert(path, cmOutputConverter::HOME_OUTPUT); +#ifdef _WIN32 + cmSystemTools::ReplaceString(convPath, "/", "\\"); +#endif + return convPath; +} + void cmGlobalNinjaGenerator::AddCXXCompileCommand( const std::string &commandLine, const std::string &sourceFile) @@ -907,8 +918,6 @@ cmGlobalNinjaGenerator { std::string configName = target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmLocalNinjaGenerator *ng = - static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]); // for frameworks, we want the real name, not smple name // frameworks always appear versioned, and the build.ninja @@ -923,13 +932,13 @@ cmGlobalNinjaGenerator case cmTarget::MODULE_LIBRARY: { cmGeneratorTarget *gtgt = this->GetGeneratorTarget(target); - outputs.push_back(ng->ConvertToNinjaPath( + outputs.push_back(this->ConvertToNinjaPath( gtgt->GetFullPath(configName, false, realname))); break; } case cmTarget::OBJECT_LIBRARY: case cmTarget::UTILITY: { - std::string path = ng->ConvertToNinjaPath( + std::string path = this->ConvertToNinjaPath( target->GetMakefile()->GetCurrentBinaryDirectory()); if (path.empty() || path == ".") outputs.push_back(target->GetName()); @@ -1041,8 +1050,6 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) //get the list of files that cmake itself has generated as a //product of configuration. - cmLocalNinjaGenerator *ng = - static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]); for (std::vector<cmLocalGenerator *>::const_iterator i = this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) @@ -1054,7 +1061,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) typedef std::vector<std::string>::const_iterator vect_it; for(vect_it j = files.begin(); j != files.end(); ++j) { - knownDependencies.insert( ng->ConvertToNinjaPath( *j ) ); + knownDependencies.insert( this->ConvertToNinjaPath( *j ) ); } //get list files which are implicit dependencies as well and will be phony //for rebuild manifest @@ -1062,7 +1069,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) typedef std::vector<std::string>::const_iterator vect_it; for(vect_it j = lf.begin(); j != lf.end(); ++j) { - knownDependencies.insert( ng->ConvertToNinjaPath( *j ) ); + knownDependencies.insert( this->ConvertToNinjaPath( *j ) ); } std::vector<cmGeneratorExpressionEvaluationFile*> const& ef = (*i)->GetMakefile()->GetEvaluationFiles(); @@ -1074,7 +1081,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) std::vector<std::string> evaluationFiles = (*li)->GetFiles(); for(vect_it j = evaluationFiles.begin(); j != evaluationFiles.end(); ++j) { - knownDependencies.insert( ng->ConvertToNinjaPath( *j ) ); + knownDependencies.insert( this->ConvertToNinjaPath( *j ) ); } } } @@ -1084,7 +1091,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) i != this->TargetAliases.end(); ++i) { - knownDependencies.insert( ng->ConvertToNinjaPath(i->first) ); + knownDependencies.insert( this->ConvertToNinjaPath(i->first) ); } //remove all source files we know will exist. @@ -1093,7 +1100,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) i != this->AssumedSourceDependencies.end(); ++i) { - knownDependencies.insert( ng->ConvertToNinjaPath(i->first) ); + knownDependencies.insert( this->ConvertToNinjaPath(i->first) ); } //now we difference with CombinedCustomCommandExplicitDependencies to find @@ -1214,8 +1221,6 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) /*restat=*/ "", /*generator=*/ true); - cmLocalNinjaGenerator *ng = static_cast<cmLocalNinjaGenerator *>(lg); - cmNinjaDeps implicitDeps; for(std::vector<cmLocalGenerator*>::const_iterator i = this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) @@ -1224,7 +1229,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) for(std::vector<std::string>::const_iterator fi = lf.begin(); fi != lf.end(); ++fi) { - implicitDeps.push_back(ng->ConvertToNinjaPath(*fi)); + implicitDeps.push_back(this->ConvertToNinjaPath(*fi)); } } implicitDeps.push_back("CMakeCache.txt"); diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index d204a50..292f7c7 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -220,6 +220,19 @@ public: cmGeneratedFileStream* GetRulesFileStream() const { return this->RulesFileStream; } + std::string ConvertToNinjaPath(const std::string& path); + + struct MapToNinjaPathImpl { + cmGlobalNinjaGenerator* GG; + MapToNinjaPathImpl(cmGlobalNinjaGenerator* gg): GG(gg) {} + std::string operator()(std::string const& path) { + return this->GG->ConvertToNinjaPath(path); + } + }; + MapToNinjaPathImpl MapToNinjaPath() { + return MapToNinjaPathImpl(this); + } + void AddCXXCompileCommand(const std::string &commandLine, const std::string &sourceFile); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index cf4fd69..0064713 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -578,23 +578,18 @@ void cmGlobalUnixMakefileGenerator3 if (!targetName.empty()) { cmMakefile* mf; - cmLocalUnixMakefileGenerator3 *lg; - if (!this->LocalGenerators.empty()) + if (!this->Makefiles.empty()) { - lg = static_cast<cmLocalUnixMakefileGenerator3 *> - (this->LocalGenerators[0]); - mf = lg->GetMakefile(); + mf = this->Makefiles[0]; } else { cmState::Snapshot snapshot = this->CMakeInstance->GetCurrentSnapshot(); mf = new cmMakefile(this, snapshot); - lg = static_cast<cmLocalUnixMakefileGenerator3 *> - (this->CreateLocalGenerator(mf)); // set the Start directories - lg->GetMakefile()->SetCurrentSourceDirectory + mf->SetCurrentSourceDirectory (this->CMakeInstance->GetHomeDirectory()); - lg->GetMakefile()->SetCurrentBinaryDirectory + mf->SetCurrentBinaryDirectory (this->CMakeInstance->GetHomeOutputDirectory()); } @@ -603,12 +598,12 @@ void cmGlobalUnixMakefileGenerator3 { tname += "/fast"; } - tname = lg->Convert(tname,cmLocalGenerator::HOME_OUTPUT); + cmOutputConverter conv(mf->GetStateSnapshot()); + tname = conv.Convert(tname,cmOutputConverter::HOME_OUTPUT); cmSystemTools::ConvertToOutputSlashes(tname); makeCommand.push_back(tname); - if (this->LocalGenerators.empty()) + if (this->Makefiles.empty()) { - delete lg; delete mf; } } diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 44d632d..59e8f8c 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -176,7 +176,14 @@ cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts, //---------------------------------------------------------------------------- bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) { - if (this->SystemName == "WindowsCE") + if (this->SystemName == "Windows") + { + if (!this->InitializeWindows(mf)) + { + return false; + } + } + else if (this->SystemName == "WindowsCE") { this->SystemIsWindowsCE = true; if (!this->InitializeWindowsCE(mf)) @@ -184,7 +191,7 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) return false; } } - else if(this->SystemName == "WindowsPhone") + else if (this->SystemName == "WindowsPhone") { this->SystemIsWindowsPhone = true; if(!this->InitializeWindowsPhone(mf)) @@ -192,7 +199,7 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) return false; } } - else if(this->SystemName == "WindowsStore") + else if (this->SystemName == "WindowsStore") { this->SystemIsWindowsStore = true; if(!this->InitializeWindowsStore(mf)) @@ -229,6 +236,12 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) } //---------------------------------------------------------------------------- +bool cmGlobalVisualStudio10Generator::InitializeWindows(cmMakefile*) +{ + return true; +} + +//---------------------------------------------------------------------------- bool cmGlobalVisualStudio10Generator::InitializeWindowsCE(cmMakefile* mf) { if (this->DefaultPlatformName != "Win32") diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 8de7b09..f4861dc 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -74,6 +74,10 @@ public: /** Return the CMAKE_SYSTEM_VERSION. */ std::string const& GetSystemVersion() const { return this->SystemVersion; } + /** Return the Windows version targeted on VS 2015 and above. */ + std::string const& GetWindowsTargetPlatformVersion() const + { return this->WindowsTargetPlatformVersion; } + /** Return true if building for WindowsCE */ bool TargetsWindowsCE() const { return this->SystemIsWindowsCE; } @@ -105,6 +109,7 @@ public: protected: virtual void Generate(); virtual bool InitializeSystem(cmMakefile* mf); + virtual bool InitializeWindows(cmMakefile* mf); virtual bool InitializeWindowsCE(cmMakefile* mf); virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); @@ -119,6 +124,7 @@ protected: std::string GeneratorToolset; std::string DefaultPlatformToolset; + std::string WindowsTargetPlatformVersion; std::string SystemName; std::string SystemVersion; std::string NsightTegraVersion; diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index d73eedf..41825fb 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -111,6 +111,84 @@ cmGlobalVisualStudio14Generator::MatchesGeneratorName( } //---------------------------------------------------------------------------- +bool cmGlobalVisualStudio14Generator::InitializeWindows(cmMakefile* mf) +{ + if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) + { + return this->SelectWindows10SDK(mf); + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio14Generator::InitializeWindowsStore(cmMakefile* mf) +{ + std::ostringstream e; + if(!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) + { + if(this->DefaultPlatformToolset.empty()) + { + e << this->GetName() << " supports Windows Store '8.0', '8.1' and " + "'10.0', but not '" << this->SystemVersion << + "'. Check CMAKE_SYSTEM_VERSION."; + } + else + { + e << "A Windows Store component with CMake requires both the Windows " + << "Desktop SDK as well as the Windows Store '" << this->SystemVersion + << "' SDK. Please make sure that you have both installed"; + } + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) + { + return this->SelectWindows10SDK(mf); + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf) +{ + // Find the default version of the Windows 10 SDK. + this->WindowsTargetPlatformVersion = this->GetWindows10SDKVersion(); + if (this->WindowsTargetPlatformVersion.empty()) + { + std::ostringstream e; + e << "Could not find an appropriate version of the Windows 10 SDK" + << " installed on this machine"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION", + this->WindowsTargetPlatformVersion.c_str()); + return true; +} + +//---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( + std::string& toolset) const +{ + if (cmHasLiteralPrefix(this->SystemVersion, "10.0")) + { + if (this->IsWindowsStoreToolsetInstalled() && + this->IsWindowsDesktopToolsetInstalled()) + { + toolset = "v140"; + return true; + } + else + { + return false; + } + } + return + this->cmGlobalVisualStudio12Generator::SelectWindowsStoreToolset(toolset); +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout) { // Visual Studio 14 writes .sln format 12.00 @@ -137,3 +215,77 @@ cmGlobalVisualStudio14Generator::IsWindowsDesktopToolsetInstalled() const return cmSystemTools::GetRegistrySubKeys(desktop10Key, vc14, cmSystemTools::KeyWOW64_32); } + +//---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const +{ + const char universal10Key[] = + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "VisualStudio\\14.0\\Setup\\Build Tools for Windows 10;SrcPath"; + + std::string win10SDK; + return cmSystemTools::ReadRegistryValue(universal10Key, + win10SDK, cmSystemTools::KeyWOW64_32); +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + // This logic is taken from the vcvarsqueryregistry.bat file from VS2015 + // Try HKLM and then HKCU. + std::string win10Root; + if (!cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot10", win10Root, + cmSystemTools::KeyWOW64_32) && + !cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot10", win10Root, + cmSystemTools::KeyWOW64_32)) + { + return std::string(); + } + + std::vector<std::string> sdks; + std::string path = win10Root + "Include/*"; + // Grab the paths of the different SDKs that are installed + cmSystemTools::GlobDirs(path, sdks); + if (!sdks.empty()) + { + // Only use the filename, which will be the SDK version. + for (std::vector<std::string>::iterator i = sdks.begin(); + i != sdks.end(); ++i) + { + *i = cmSystemTools::GetFilenameName(*i); + } + + // Sort the results to make sure we select the most recent one that + // has a version less or equal to our version of the operating system + std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater); + + // Select a suitable SDK version. + if (this->SystemVersion == "10.0") + { + // Use the latest Windows 10 SDK since no build version was given. + return sdks.at(0); + } + else + { + // Find the SDK less or equal to our specified version + for (std::vector<std::string>::iterator i = sdks.begin(); + i != sdks.end(); ++i) + { + if (!cmSystemTools::VersionCompareGreater(*i, this->SystemVersion)) + { + // This is the most recent SDK that we can run safely + return *i; + } + } + } + } +#endif + // Return an empty string + return std::string(); +} diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 02c6274..76c15d9 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -30,12 +30,23 @@ public: virtual const char* GetToolsVersion() { return "14.0"; } protected: + virtual bool InitializeWindows(cmMakefile* mf); + virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual bool SelectWindowsStoreToolset(std::string& toolset) const; + + // These aren't virtual because we need to check if the selected version + // of the toolset is installed + bool IsWindowsStoreToolsetInstalled() const; + virtual const char* GetIDEVersion() { return "14.0"; } + virtual bool SelectWindows10SDK(cmMakefile* mf); // Used to verify that the Desktop toolset for the current generator is // installed on the machine. virtual bool IsWindowsDesktopToolsetInstalled() const; + std::string GetWindows10SDKVersion(); + private: class Factory; }; diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index df49948..14de698 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -217,7 +217,7 @@ void cmGlobalVisualStudio6Generator TargetDependSet projectTargets; TargetDependSet originalTargets; this->GetTargetSets(projectTargets, originalTargets, root, generators); - OrderedTargetDependSet orderedProjectTargets(projectTargets); + OrderedTargetDependSet orderedProjectTargets(projectTargets, "ALL_BUILD"); for(OrderedTargetDependSet::const_iterator tt = orderedProjectTargets.begin(); diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 607642c..b913afc 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -94,7 +94,7 @@ void cmGlobalVisualStudio71Generator TargetDependSet projectTargets; TargetDependSet originalTargets; this->GetTargetSets(projectTargets, originalTargets, root, generators); - OrderedTargetDependSet orderedProjectTargets(projectTargets); + OrderedTargetDependSet orderedProjectTargets(projectTargets, "ALL_BUILD"); this->WriteTargetsToSolution(fout, root, orderedProjectTargets); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 0175062..05da022 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -568,7 +568,7 @@ void cmGlobalVisualStudio7Generator TargetDependSet projectTargets; TargetDependSet originalTargets; this->GetTargetSets(projectTargets, originalTargets, root, generators); - OrderedTargetDependSet orderedProjectTargets(projectTargets); + OrderedTargetDependSet orderedProjectTargets(projectTargets, "ALL_BUILD"); this->WriteTargetsToSolution(fout, root, orderedProjectTargets); diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 28f0425..70c00e9 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -449,7 +449,7 @@ void cmGlobalVisualStudio8Generator::WriteProjectDepends( { cmGeneratorTarget* gt = this->GetGeneratorTarget(&t); TargetDependSet const& unordered = this->GetTargetDirectDepends(gt); - OrderedTargetDependSet depends(unordered); + OrderedTargetDependSet depends(unordered, std::string()); for(OrderedTargetDependSet::const_iterator i = depends.begin(); i != depends.end(); ++i) { diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 2bf04b4..7552d67 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -192,7 +192,7 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros() cmMakefile* mf = this->LocalGenerators[0]->GetMakefile(); std::string dir = this->GetUserMacrosDirectory(); - if (mf != 0 && dir != "") + if (dir != "") { std::string src = mf->GetRequiredDefinition("CMAKE_ROOT"); src += "/Templates/" CMAKE_VSMACROS_FILENAME; @@ -233,13 +233,12 @@ cmGlobalVisualStudioGenerator std::string dir = this->GetUserMacrosDirectory(); // Only really try to call the macro if: - // - mf is non-NULL // - there is a UserMacrosDirectory // - the CMake vsmacros file exists // - the CMake vsmacros file is registered // - there were .sln/.vcproj files changed during generation // - if (mf != 0 && dir != "") + if (dir != "") { std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME; std::string nextSubkeyName; @@ -864,28 +863,34 @@ bool cmGlobalVisualStudioGenerator::TargetCompare ::operator()(cmGeneratorTarget const* l, cmGeneratorTarget const* r) const { - // Make sure ALL_BUILD is first so it is the default active project. - if(r->GetName() == "ALL_BUILD") + // Make sure a given named target is ordered first, + // e.g. to set ALL_BUILD as the default active project. + // When the empty string is named this is a no-op. + if (r->GetName() == this->First) { return false; } - if(l->GetName() == "ALL_BUILD") + if (l->GetName() == this->First) { return true; } - return strcmp(l->GetName().c_str(), r->GetName().c_str()) < 0; + return l->GetName() < r->GetName(); } //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::OrderedTargetDependSet -::OrderedTargetDependSet(TargetDependSet const& targets) +::OrderedTargetDependSet(TargetDependSet const& targets, + std::string const& first): + derived(TargetCompare(first)) { this->insert(targets.begin(), targets.end()); } //---------------------------------------------------------------------------- cmGlobalVisualStudioGenerator::OrderedTargetDependSet -::OrderedTargetDependSet(TargetSet const& targets) +::OrderedTargetDependSet(TargetSet const& targets, + std::string const& first): + derived(TargetCompare(first)) { for (TargetSet::const_iterator it = targets.begin(); it != targets.end(); ++it) diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 64440ad..c940eb3 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -89,8 +89,11 @@ public: virtual bool TargetsWindowsCE() const { return false; } class TargetSet: public std::set<cmTarget const*> {}; - struct TargetCompare + class TargetCompare { + std::string First; + public: + TargetCompare(std::string const& first): First(first) {} bool operator()(cmGeneratorTarget const* l, cmGeneratorTarget const* r) const; }; @@ -151,11 +154,14 @@ class cmGlobalVisualStudioGenerator::OrderedTargetDependSet: public std::multiset<cmTargetDepend, cmGlobalVisualStudioGenerator::TargetCompare> { + typedef std::multiset<cmTargetDepend, + cmGlobalVisualStudioGenerator::TargetCompare> + derived; public: typedef cmGlobalGenerator::TargetDependSet TargetDependSet; typedef cmGlobalVisualStudioGenerator::TargetSet TargetSet; - OrderedTargetDependSet(TargetDependSet const&); - OrderedTargetDependSet(TargetSet const&); + OrderedTargetDependSet(TargetDependSet const&, std::string const& first); + OrderedTargetDependSet(TargetSet const&, std::string const& first); }; #endif diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 20448c1..9e71d37 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -106,7 +106,14 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmake::MessageType messType; - cmConditionEvaluator conditionEvaluator(mf); + cmListFileContext conditionContext = + cmConditionEvaluator::GetConditionContext( + &mf, this->Functions[c], + this->GetStartingContext().FilePath); + + cmConditionEvaluator conditionEvaluator( + mf, conditionContext, + mf.GetBacktrace(this->Functions[c])); bool isTrue = conditionEvaluator.IsTrue( expandedArguments, errorString, messType); @@ -195,7 +202,16 @@ bool cmIfCommand cmake::MessageType status; - cmConditionEvaluator conditionEvaluator(*(this->Makefile)); + cmListFileContext execContext = this->Makefile->GetExecutionContext(); + + cmCommandContext commandContext; + commandContext.Line = execContext.Line; + commandContext.Name = execContext.Name; + + cmConditionEvaluator conditionEvaluator( + *(this->Makefile), cmConditionEvaluator::GetConditionContext( + this->Makefile, commandContext, execContext.FilePath), + this->Makefile->GetBacktrace()); bool isTrue = conditionEvaluator.IsTrue( expandedArguments, errorString, status); diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index 7593380..78cb5f0 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -12,6 +12,8 @@ #include "cmInstallDirectoryGenerator.h" #include "cmTarget.h" +#include "cmGeneratorExpression.h" +#include "cmLocalGenerator.h" //---------------------------------------------------------------------------- cmInstallDirectoryGenerator @@ -25,10 +27,16 @@ cmInstallDirectoryGenerator const char* literal_args, bool optional): cmInstallGenerator(dest, configurations, component, message), + LocalGenerator(0), Directories(dirs), FilePermissions(file_permissions), DirPermissions(dir_permissions), LiteralArguments(literal_args), Optional(optional) { + // We need per-config actions if destination have generator expressions. + if(cmGeneratorExpression::Find(Destination) != std::string::npos) + { + this->ActionsPerConfig = true; + } } //---------------------------------------------------------------------------- @@ -37,15 +45,43 @@ cmInstallDirectoryGenerator { } +void cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg) +{ + LocalGenerator = lg; +} + //---------------------------------------------------------------------------- void cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os, Indent const& indent) { + if(this->ActionsPerConfig) + { + this->cmInstallGenerator::GenerateScriptActions(os, indent); + } + else + { + this->AddDirectoryInstallRule(os, "", indent); + } +} + +void cmInstallDirectoryGenerator::GenerateScriptForConfig( + std::ostream& os, + const std::string& config, + Indent const& indent) +{ + this->AddDirectoryInstallRule(os, config, indent); +} + +void cmInstallDirectoryGenerator::AddDirectoryInstallRule( + std::ostream& os, + const std::string& config, + Indent const& indent) +{ // Write code to install the directories. const char* no_rename = 0; this->AddInstallRule(os, - this->Destination, + this->GetDestination(config), cmInstallType_DIRECTORY, this->Directories, this->Optional, @@ -54,3 +90,12 @@ cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os, no_rename, this->LiteralArguments.c_str(), indent); } + +//---------------------------------------------------------------------------- +std::string +cmInstallDirectoryGenerator::GetDestination(std::string const& config) const +{ + cmGeneratorExpression ge; + return ge.Parse(this->Destination) + ->Evaluate(this->LocalGenerator->GetMakefile(), config); +} diff --git a/Source/cmInstallDirectoryGenerator.h b/Source/cmInstallDirectoryGenerator.h index 165ab91..04107e1 100644 --- a/Source/cmInstallDirectoryGenerator.h +++ b/Source/cmInstallDirectoryGenerator.h @@ -31,8 +31,19 @@ public: bool optional = false); virtual ~cmInstallDirectoryGenerator(); + void Compute(cmLocalGenerator* lg); + + std::string GetDestination(std::string const& config) const; + protected: virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); + virtual void GenerateScriptForConfig(std::ostream& os, + const std::string& config, + Indent const& indent); + void AddDirectoryInstallRule(std::ostream& os, + const std::string& config, + Indent const& indent); + cmLocalGenerator* LocalGenerator; std::vector<std::string> Directories; std::string FilePermissions; std::string DirPermissions; diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index 4551ab1..8062d11 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -52,12 +52,6 @@ public: virtual void FinalPass(); virtual bool HasFinalPass() const { return !this->IsFilesForm; } - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmInstallFilesCommand, cmCommand); protected: diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index c18b174..e2c16c8 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -34,6 +34,12 @@ cmInstallFilesGenerator Programs(programs), Optional(optional) { + // We need per-config actions if the destination has generator expressions. + if(cmGeneratorExpression::Find(Destination) != std::string::npos) + { + this->ActionsPerConfig = true; + } + // We need per-config actions if any files have generator expressions. for(std::vector<std::string>::const_iterator i = files.begin(); !this->ActionsPerConfig && i != files.end(); ++i) @@ -57,14 +63,25 @@ void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg) } //---------------------------------------------------------------------------- +std::string +cmInstallFilesGenerator::GetDestination(std::string const& config) const +{ + cmGeneratorExpression ge; + return ge.Parse(this->Destination) + ->Evaluate(this->LocalGenerator->GetMakefile(), config); +} + +//---------------------------------------------------------------------------- void cmInstallFilesGenerator::AddFilesInstallRule( - std::ostream& os, Indent const& indent, + std::ostream& os, + const std::string config, + Indent const& indent, std::vector<std::string> const& files) { // Write code to install the files. const char* no_dir_permissions = 0; this->AddInstallRule(os, - this->Destination, + this->GetDestination(config), (this->Programs ? cmInstallType_PROGRAMS : cmInstallType_FILES), @@ -84,7 +101,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, } else { - this->AddFilesInstallRule(os, indent, this->Files); + this->AddFilesInstallRule(os, "", indent, this->Files); } } @@ -102,5 +119,5 @@ void cmInstallFilesGenerator::GenerateScriptForConfig(std::ostream& os, cmSystemTools::ExpandListArgument(cge->Evaluate( this->LocalGenerator->GetMakefile(), config), files); } - this->AddFilesInstallRule(os, indent, files); + this->AddFilesInstallRule(os, config, indent, files); } diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 00b3a79..bfe4039 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -32,12 +32,16 @@ public: void Compute(cmLocalGenerator* lg); + std::string GetDestination(std::string const& config) const; + protected: virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); virtual void GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent const& indent); - void AddFilesInstallRule(std::ostream& os, Indent const& indent, + void AddFilesInstallRule(std::ostream& os, + const std::string config, + Indent const& indent, std::vector<std::string> const& files); cmLocalGenerator* LocalGenerator; diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h index 90c7ba3..524debf 100644 --- a/Source/cmInstallProgramsCommand.h +++ b/Source/cmInstallProgramsCommand.h @@ -53,12 +53,6 @@ public: virtual bool HasFinalPass() const { return true; } - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmInstallProgramsCommand, cmCommand); protected: diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h index e6cbe6e..05160eb 100644 --- a/Source/cmInstallTargetsCommand.h +++ b/Source/cmInstallTargetsCommand.h @@ -44,12 +44,6 @@ public: */ virtual std::string GetName() const { return "install_targets";} - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmInstallTargetsCommand, cmCommand); }; diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h index c572439..1ddefc4 100644 --- a/Source/cmLinkLibrariesCommand.h +++ b/Source/cmLinkLibrariesCommand.h @@ -44,12 +44,6 @@ public: */ virtual std::string GetName() const { return "link_libraries";} - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmLinkLibrariesCommand, cmCommand); }; diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index 4581269..445e167 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -21,7 +21,6 @@ public: virtual bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus &status); virtual std::string GetName() const {return "load_command";} - virtual bool IsDiscouraged() const { return true; } cmTypeMacro(cmLoadCommandCommand, cmCommand); }; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index b360c22..3230403 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -54,6 +54,8 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, this->EmitUniversalBinaryFlags = true; this->BackwardsCompatibility = 0; this->BackwardsCompatibilityFinal = false; + + this->ComputeObjectMaxPath(); } cmLocalGenerator::~cmLocalGenerator() @@ -487,7 +489,7 @@ cmState* cmLocalGenerator::GetState() const cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const { - return this->StateSnapshot; + return this->Makefile->GetStateSnapshot(); } // List of variables that are replaced when @@ -525,6 +527,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, return replaceValues.LinkFlags; } } + if(replaceValues.Manifests) + { + if(variable == "MANIFESTS") + { + return replaceValues.Manifests; + } + } if(replaceValues.Flags) { if(variable == "FLAGS") @@ -1533,13 +1542,49 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR"); // Flags to link an executable to shared libraries. - std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; - linkFlagsVar += linkLanguage; - linkFlagsVar += "_FLAGS"; - if( tgt.GetType() == cmTarget::EXECUTABLE ) + if (tgt.GetType() == cmTarget::EXECUTABLE && + this->StateSnapshot.GetState()-> + GetGlobalPropertyAsBool("TARGET_SUPPORTS_SHARED_LIBS")) { - linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar); - linkLibs += " "; + bool add_shlib_flags = false; + switch(tgt.Target->GetPolicyStatusCMP0065()) + { + case cmPolicies::WARN: + if(!tgt.GetPropertyAsBool("ENABLE_EXPORTS") && + this->Makefile->PolicyOptionalWarningEnabled( + "CMAKE_POLICY_WARNING_CMP0065")) + { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0065) << "\n" + "For compatibility with older versions of CMake, " + "additional flags may be added to export symbols on all " + "executables regardless of thier ENABLE_EXPORTS property."; + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + } + case cmPolicies::OLD: + // OLD behavior is to always add the flags + add_shlib_flags = true; + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065) + ); + case cmPolicies::NEW: + // NEW behavior is to only add the flags if ENABLE_EXPORTS is on + add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS"); + break; + } + + if(add_shlib_flags) + { + std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; + linkFlagsVar += linkLanguage; + linkFlagsVar += "_FLAGS"; + linkLibs = this->Makefile->GetSafeDefinition(linkFlagsVar); + linkLibs += " "; + } } // Append the framework search path flags. @@ -2843,7 +2888,7 @@ cmIML_INT_uint64_t cmLocalGenerator::GetBackwardsCompatibility() } } this->BackwardsCompatibility = CMake_VERSION_ENCODE(major, minor, patch); - this->BackwardsCompatibilityFinal = this->Makefile->IsConfigured(); + this->BackwardsCompatibilityFinal = true; } return this->BackwardsCompatibility; diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b051e5d..6ea414a 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -219,6 +219,7 @@ public: const char* TargetSOName; const char* TargetInstallNameDir; const char* LinkFlags; + const char* Manifests; const char* LanguageCompileFlags; const char* Defines; const char* Includes; @@ -299,7 +300,6 @@ public: void CreateEvaluationFileOutputs(const std::string& config); void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles); - void ComputeObjectMaxPath(); protected: ///! put all the libraries for a target on into the given stream void OutputLinkLibraries(std::string& linkLibraries, @@ -359,6 +359,8 @@ private: bool GetShouldUseOldFlags(bool shared, const std::string &lang) const; void AddPositionIndependentFlags(std::string& flags, std::string const& l, int targetType); + + void ComputeObjectMaxPath(); }; #endif diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 7525bf2..c46adc1 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -284,15 +284,6 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) os << std::endl; } -std::string cmLocalNinjaGenerator::ConvertToNinjaPath(const std::string& path) -{ - std::string convPath = this->Convert(path, cmLocalGenerator::HOME_OUTPUT); -#ifdef _WIN32 - cmSystemTools::ReplaceString(convPath, "/", "\\"); -#endif - return convPath; -} - void cmLocalNinjaGenerator ::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs) @@ -316,7 +307,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps( i != deps.end(); ++i) { std::string dep; if (this->GetRealDependency(*i, this->GetConfigName(), dep)) - ninjaDeps.push_back(ConvertToNinjaPath(dep)); + ninjaDeps.push_back( + this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(dep)); } } @@ -413,9 +405,11 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( at us. How to know which ExternalProject step actually provides it? #endif std::transform(outputs.begin(), outputs.end(), - ninjaOutputs.begin(), MapToNinjaPath()); + ninjaOutputs.begin(), + this->GetGlobalNinjaGenerator()->MapToNinjaPath()); std::transform(byproducts.begin(), byproducts.end(), - ninjaOutputs.begin() + outputs.size(), MapToNinjaPath()); + ninjaOutputs.begin() + outputs.size(), + this->GetGlobalNinjaGenerator()->MapToNinjaPath()); this->AppendCustomCommandDeps(ccg, ninjaDeps); for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end(); diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 8d3d49c..1645a8d 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -50,21 +50,6 @@ public: std::string GetHomeRelativeOutputPath() const { return this->HomeRelativeOutputPath; } - std::string ConvertToNinjaPath(const std::string& path); - - struct map_to_ninja_path { - cmLocalNinjaGenerator *LocalGenerator; - map_to_ninja_path(cmLocalNinjaGenerator *LocalGen) - : LocalGenerator(LocalGen) {} - std::string operator()(const std::string &path) { - return LocalGenerator->ConvertToNinjaPath(path); - } - }; - - map_to_ninja_path MapToNinjaPath() { - return map_to_ninja_path(this); - } - void ExpandRuleVariables(std::string& string, const RuleVariables& replaceValues) { cmLocalGenerator::ExpandRuleVariables(string, replaceValues); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index cf67251..a4bce8a 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -972,25 +972,43 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n"; // end of <Tool Name=VCMIDLTool - // Check if we need the FAT32 workaround. + // Add manifest tool settings. if(targetBuilds && this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) { + const char* manifestTool = "VCManifestTool"; + if (this->FortranProject) + { + manifestTool = "VFManifestTool"; + } + fout << + "\t\t\t<Tool\n" + "\t\t\t\tName=\"" << manifestTool << "\""; + + std::vector<cmSourceFile const*> manifest_srcs; + gt->GetManifests(manifest_srcs, configName); + if (!manifest_srcs.empty()) + { + fout << "\n\t\t\t\tAdditionalManifestFiles=\""; + for (std::vector<cmSourceFile const*>::const_iterator + mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi) + { + std::string m = (*mi)->GetFullPath(); + fout << this->ConvertToXMLOutputPath(m.c_str()) << ";"; + } + fout << "\""; + } + + // Check if we need the FAT32 workaround. // Check the filesystem type where the target will be written. - if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str())) + if (cmLVS6G_IsFAT(target.GetDirectory(configName).c_str())) { // Add a flag telling the manifest tool to use a workaround // for FAT32 file systems, which can cause an empty manifest // to be embedded into the resulting executable. See CMake // bug #2617. - const char* manifestTool = "VCManifestTool"; - if(this->FortranProject) - { - manifestTool = "VFManifestTool"; - } - fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << manifestTool << "\"\n" - << "\t\t\t\tUseFAT32Workaround=\"true\"\n" - << "\t\t\t/>\n"; + fout << "\n\t\t\t\tUseFAT32Workaround=\"true\""; } + fout << "/>\n"; } this->OutputTargetRules(fout, configName, target, libName); diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h index 71b97eb..617f1fe 100644 --- a/Source/cmMakeDirectoryCommand.h +++ b/Source/cmMakeDirectoryCommand.h @@ -51,12 +51,6 @@ public: */ virtual bool IsScriptable() const { return true; } - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmMakeDirectoryCommand, cmCommand); }; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 8a3d197..cb66a75 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -54,7 +54,6 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars(); - this->Configured = false; this->SuppressWatches = false; // Setup the default include file regular expression (match everything). @@ -1658,7 +1657,6 @@ void cmMakefile::Configure() cmParseFileScope pfs(this); if (!listFile.ParseFile(currentStart.c_str(), this->IsRootMakefile(), this)) { - this->SetConfigured(); return; } } @@ -1679,7 +1677,6 @@ void cmMakefile::Configure() } this->AddCMakeDependFilesFromUser(); - this->SetConfigured(); } void cmMakefile::ConfigureSubDirectory(cmMakefile *mf) @@ -1723,7 +1720,6 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile *mf) // NEW behavior prints the error. this->IssueMessage(cmake::FATAL_ERROR, e.str()); } - mf->SetConfigured(); return; } // finally configure the subdir @@ -1756,11 +1752,6 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot); this->GetGlobalGenerator()->AddMakefile(subMf); - // create a new local generator and set its parent - cmLocalGenerator *lg2 = this->GetGlobalGenerator() - ->CreateLocalGenerator(subMf); - this->GetGlobalGenerator()->AddLocalGenerator(lg2); - // set the subdirs start dirs subMf->SetCurrentSourceDirectory(srcPath); subMf->SetCurrentBinaryDirectory(binPath); @@ -3227,7 +3218,7 @@ void cmMakefile::AddDefaultDefinitions() //---------------------------------------------------------------------------- std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs, - bool single) const + bool singleConfig) const { if(this->GetGlobalGenerator()->IsMultiConfig()) { @@ -3241,7 +3232,7 @@ cmMakefile::GetConfigurations(std::vector<std::string>& configs, else { const std::string& buildType = this->GetSafeDefinition("CMAKE_BUILD_TYPE"); - if(single && !buildType.empty()) + if(singleConfig && !buildType.empty()) { configs.push_back(buildType); } @@ -4667,9 +4658,10 @@ bool cmMakefile::SetPolicyVersion(const char *version) } //---------------------------------------------------------------------------- -bool cmMakefile::HasCMP0054AlreadyBeenReported() const +bool cmMakefile::HasCMP0054AlreadyBeenReported( + cmListFileContext const& context) const { - return !this->CMP0054ReportedIds.insert(this->GetExecutionContext()).second; + return !this->CMP0054ReportedIds.insert(context).second; } //---------------------------------------------------------------------------- diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 3cf20a6..111f074 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -336,7 +336,7 @@ public: * Determine if the given context, name pair has already been reported * in context of CMP0054. */ - bool HasCMP0054AlreadyBeenReported() const; + bool HasCMP0054AlreadyBeenReported(const cmListFileContext &context) const; bool IgnoreErrorsCMP0061() const; @@ -750,9 +750,6 @@ public: cmStringRange GetCompileDefinitionsEntries() const; cmBacktraceRange GetCompileDefinitionsBacktraces() const; - bool IsConfigured() const { return this->Configured; } - void SetConfigured(){ this->Configured = true; } - void AddQtUiFileWithOptions(cmSourceFile *sf); std::vector<cmSourceFile*> GetQtUiFilesWithOptions() const; @@ -988,7 +985,6 @@ private: bool WarnUnused; bool CheckSystemVars; bool CheckCMP0000; - bool Configured; bool IsSourceFileTryCompile; mutable bool SuppressWatches; }; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index ccb0974..90f679e 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -353,6 +353,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) useResponseFileForObjects, buildObjs, depends, useWatcomQuote); + std::string manifests = this->GetManifests(); + cmLocalGenerator::RuleVariables vars; vars.RuleLauncher = "RULE_LAUNCH_LINK"; vars.CMTarget = this->Target; @@ -391,6 +393,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.LinkLibraries = linkLibs.c_str(); vars.Flags = flags.c_str(); vars.LinkFlags = linkFlags.c_str(); + vars.Manifests = manifests.c_str(); + // Expand placeholders in the commands. this->LocalGenerator->TargetImplib = targetOutPathImport; for(std::vector<std::string>::iterator i = real_link_commands.begin(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 2f995e8..cd387a0 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -616,6 +616,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } } + std::string manifests = this->GetManifests(); + cmLocalGenerator::RuleVariables vars; vars.TargetPDB = targetOutPathPDB.c_str(); @@ -660,6 +662,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } vars.LinkFlags = linkFlags.c_str(); + vars.Manifests = manifests.c_str(); + // Compute the directory portion of the install_name setting. std::string install_name_dir; if(this->Target->GetType() == cmTarget::SHARED_LIBRARY) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index cf88a74..b278087 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1493,6 +1493,15 @@ void cmMakefileTargetGenerator depends.push_back(this->ModuleDefinitionFile); } + // Add a dependency on user-specified manifest files, if any. + std::vector<cmSourceFile const*> manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin(); + mi != manifest_srcs.end(); ++mi) + { + depends.push_back((*mi)->GetFullPath()); + } + // Add user-specified dependencies. if(const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS")) diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 467555f..2854a82 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -43,19 +43,7 @@ bool cmMessageCommand } else if (*i == "AUTHOR_WARNING") { - if (this->Makefile->IsOn("CMAKE_ERROR_DEVELOPER_WARNINGS")) - { - fatal = true; - type = cmake::AUTHOR_ERROR; - } - else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) - { - type = cmake::AUTHOR_WARNING; - } - else - { - return true; - } + type = cmake::AUTHOR_WARNING; ++i; } else if (*i == "STATUS") diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index b855bea..84c19a3 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -237,6 +237,7 @@ cmNinjaNormalTargetGenerator vars.Flags = "$FLAGS"; vars.LinkFlags = "$LINK_FLAGS"; + vars.Manifests = "$MANIFESTS"; std::string langFlags; if (targetType != cmTarget::EXECUTABLE) @@ -509,6 +510,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["LINK_FLAGS"] = cmGlobalNinjaGenerator ::EncodeLiteral(vars["LINK_FLAGS"]); + vars["MANIFESTS"] = this->GetManifests(); + vars["LINK_PATH"] = frameworkPath + linkPath; // Compute architecture specific link flags. Yes, these go into a different @@ -579,11 +582,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["TARGET_PDB"] = base + suffix + dbg_suffix; } + const std::string objPath = GetTarget()->GetSupportDirectory(); + vars["OBJECT_DIR"] = + this->GetLocalGenerator()->ConvertToOutputFormat( + this->ConvertToNinjaPath(objPath), cmLocalGenerator::SHELL); + EnsureDirectoryExists(objPath); + if (this->GetGlobalGenerator()->IsGCCOnWindows()) { - const std::string objPath = GetTarget()->GetSupportDirectory(); - vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath); - EnsureDirectoryExists(objPath); // ar.exe can't handle backslashes in rsp files (implicitly used by gcc) std::string& linkLibraries = vars["LINK_LIBRARIES"]; std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/'); @@ -627,7 +633,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); - std::string dllname = targetOutput; std::string name_of_def_file = target.GetSupportDirectory(); name_of_def_file += "/" + target.GetName(); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 81fdde2..6e6dc60 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -209,6 +209,15 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const result.push_back(this->ConvertToNinjaPath(this->ModuleDefinitionFile)); } + // Add a dependency on user-specified manifest files, if any. + std::vector<cmSourceFile const*> manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, this->ConfigName); + for (std::vector<cmSourceFile const*>::iterator mi = manifest_srcs.begin(); + mi != manifest_srcs.end(); ++mi) + { + result.push_back(this->ConvertToNinjaPath((*mi)->GetFullPath())); + } + // Add user-specified dependencies. if (const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS")) { @@ -362,7 +371,7 @@ cmNinjaTargetGenerator mf->GetSafeDefinition("CMAKE_C_COMPILER") : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); cldeps = "\""; - cldeps += mf->GetSafeDefinition("CMAKE_CMCLDEPS_EXECUTABLE"); + cldeps += cmSystemTools::GetCMClDepsCommand(); cldeps += "\" " + lang + " $in \"$DEP_FILE\" $out \""; cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"); cldeps += "\" \"" + cl + "\" "; @@ -762,14 +771,14 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( // Get the input file location. std::string input = source.GetFullPath(); input = - this->Generator->GetLocalGenerator()->ConvertToNinjaPath(input); + this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(input); // Get the output file location. std::string output = macdir; output += "/"; output += cmSystemTools::GetFilenameName(input); output = - this->Generator->GetLocalGenerator()->ConvertToNinjaPath(output); + this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output); // Write a build statement to copy the content into the bundle. this->Generator->GetGlobalGenerator()->WriteMacOSXContentBuild(input, diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index a10ceba..0267f63 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -17,11 +17,11 @@ #include "cmStandardIncludes.h" #include "cmNinjaTypes.h" +#include "cmGlobalNinjaGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmOSXBundleGenerator.h" class cmTarget; -class cmGlobalNinjaGenerator; class cmGeneratedFileStream; class cmGeneratorTarget; class cmMakefile; @@ -87,10 +87,10 @@ protected: const std::string& language); std::string ConvertToNinjaPath(const std::string& path) const { - return this->GetLocalGenerator()->ConvertToNinjaPath(path); + return this->GetGlobalGenerator()->ConvertToNinjaPath(path); } - cmLocalNinjaGenerator::map_to_ninja_path MapToNinjaPath() const { - return this->GetLocalGenerator()->MapToNinjaPath(); + cmGlobalNinjaGenerator::MapToNinjaPathImpl MapToNinjaPath() const { + return this->GetGlobalGenerator()->MapToNinjaPath(); } /// @return the list of link dependency for the given target @a target. diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 7be5b3f..5acae2f 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -142,21 +142,7 @@ std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source, } else if(output == SHELL || output == WATCOMQUOTE) { - // For the MSYS shell convert drive letters to posix paths, so - // that c:/some/path becomes /c/some/path. This is needed to - // avoid problems with the shell path translation. - if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) - { - if(result.size() > 2 && result[1] == ':') - { - result[1] = result[0]; - result[0] = '/'; - } - } - if(this->GetState()->UseWindowsShell()) - { - std::replace(result.begin(), result.end(), '/', '\\'); - } + result = this->ConvertDirectorySeparatorsForShell(source); result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE); } else if(output == RESPONSE) @@ -167,6 +153,29 @@ std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source, } //---------------------------------------------------------------------------- +std::string cmOutputConverter::ConvertDirectorySeparatorsForShell( + const std::string& source) const +{ + std::string result = source; + // For the MSYS shell convert drive letters to posix paths, so + // that c:/some/path becomes /c/some/path. This is needed to + // avoid problems with the shell path translation. + if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) + { + if(result.size() > 2 && result[1] == ':') + { + result[1] = result[0]; + result[0] = '/'; + } + } + if(this->GetState()->UseWindowsShell()) + { + std::replace(result.begin(), result.end(), '/', '\\'); + } + return result; +} + +//---------------------------------------------------------------------------- std::string cmOutputConverter::Convert(RelativeRoot remote, const std::string& local, OutputFormat output, diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index ed7739e..852df5d 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -45,6 +45,8 @@ public: std::string Convert(RelativeRoot remote, const std::string& local, OutputFormat output = UNCHANGED, bool optional = false) const; + std::string ConvertDirectorySeparatorsForShell( + const std::string& source) const; /** * Get path for the specified relative root. diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h index 95eba38..6a09673 100644 --- a/Source/cmOutputRequiredFilesCommand.h +++ b/Source/cmOutputRequiredFilesCommand.h @@ -23,7 +23,6 @@ public: virtual bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus &status); virtual std::string GetName() const { return "output_required_files";} - virtual bool IsDiscouraged() const { return true; } void ListDependencies(cmDependInformation const *info, FILE *fout, diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index a791b89..a549d18 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -220,7 +220,11 @@ class cmPolicy; 3, 3, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0064, \ "Support new TEST if() operator.", \ - 3, 3, 0, cmPolicies::WARN) + 3, 4, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0065, \ + "Do not add flags to export symbols from executables without " \ + "the ENABLE_EXPORTS target property.", \ + 3, 4, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -231,7 +235,7 @@ class cmPolicy; * \brief Handles changes in CMake behavior and policies * * See the cmake wiki section on - * <a href="http://www.cmake.org/Wiki/CMake/Policies">policies</a> + * <a href="https://cmake.org/Wiki/CMake/Policies">policies</a> * for an overview of this class's purpose */ class cmPolicies diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx new file mode 100644 index 0000000..24e7ed8 --- /dev/null +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -0,0 +1,1074 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2004-2011 Kitware, Inc. + Copyright 2011 Alexander Neundorf (neundorf@kde.org) + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmQtAutoGeneratorInitializer.h" + +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmSourceFile.h" + +#include <sys/stat.h> + +#include <cmsys/FStream.hxx> + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include "cmGlobalVisualStudioGenerator.h" +#endif + +std::string cmQtAutoGeneratorInitializer::GetAutogenTargetName( + cmTarget const* target) +{ + std::string autogenTargetName = target->GetName(); + autogenTargetName += "_automoc"; + return autogenTargetName; +} + +std::string cmQtAutoGeneratorInitializer::GetAutogenTargetDir( + cmTarget const* target) +{ + cmMakefile* makefile = target->GetMakefile(); + std::string targetDir = makefile->GetCurrentBinaryDirectory(); + targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); + targetDir += "/"; + targetDir += cmQtAutoGeneratorInitializer::GetAutogenTargetName(target); + targetDir += ".dir/"; + return targetDir; +} + +static void copyTargetProperty(cmTarget* destinationTarget, + cmTarget* sourceTarget, + const std::string& propertyName) +{ + const char* propertyValue = sourceTarget->GetProperty(propertyName); + if (propertyValue) + { + destinationTarget->SetProperty(propertyName, propertyValue); + } +} + +static std::string cmQtAutoGeneratorsStripCR(std::string const& line) +{ + // Strip CR characters rcc may have printed (possibly more than one!). + std::string::size_type cr = line.find('\r'); + if (cr != line.npos) + { + return line.substr(0, cr); + } + return line; +} + +static std::string ReadAll(const std::string& filename) +{ + cmsys::ifstream file(filename.c_str()); + std::stringstream stream; + stream << file.rdbuf(); + file.close(); + return stream.str(); +} + +std::string cmQtAutoGeneratorInitializer::ListQt5RccInputs(cmSourceFile* sf, + cmTarget const* target, + std::vector<std::string>& depends) +{ + std::string rccCommand + = cmQtAutoGeneratorInitializer::GetRccExecutable(target); + std::vector<std::string> qrcEntries; + + std::vector<std::string> command; + command.push_back(rccCommand); + command.push_back("-list"); + + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath()); + + command.push_back(absFile); + + std::string rccStdOut; + std::string rccStdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &rccStdOut, &rccStdErr, + &retVal, 0, cmSystemTools::OUTPUT_NONE); + if (!result || retVal) + { + std::cerr << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath() + << " failed:\n" << rccStdOut << "\n" << rccStdErr << std::endl; + return std::string(); + } + + { + std::istringstream ostr(rccStdOut); + std::string oline; + while(std::getline(ostr, oline)) + { + oline = cmQtAutoGeneratorsStripCR(oline); + if(!oline.empty()) + { + qrcEntries.push_back(oline); + } + } + } + + { + std::istringstream estr(rccStdErr); + std::string eline; + while(std::getline(estr, eline)) + { + eline = cmQtAutoGeneratorsStripCR(eline); + if (cmHasLiteralPrefix(eline, "RCC: Error in")) + { + static std::string searchString = "Cannot find file '"; + + std::string::size_type pos = eline.find(searchString); + if (pos == std::string::npos) + { + std::cerr << "AUTOGEN: error: Rcc lists unparsable output " + << eline << std::endl; + return std::string(); + } + pos += searchString.length(); + std::string::size_type sz = eline.size() - pos - 1; + qrcEntries.push_back(eline.substr(pos, sz)); + } + } + } + + depends.insert(depends.end(), qrcEntries.begin(), qrcEntries.end()); + return cmJoin(qrcEntries, "@list_sep@"); +} + +std::string cmQtAutoGeneratorInitializer::ListQt4RccInputs(cmSourceFile* sf, + std::vector<std::string>& depends) +{ + const std::string qrcContents = ReadAll(sf->GetFullPath()); + + cmsys::RegularExpression fileMatchRegex("(<file[^<]+)"); + + std::string entriesList; + const char* sep = ""; + + size_t offset = 0; + while (fileMatchRegex.find(qrcContents.c_str() + offset)) + { + std::string qrcEntry = fileMatchRegex.match(1); + + offset += qrcEntry.size(); + + cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)"); + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + + qrcEntry = qrcEntry.substr(tag.size()); + + if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) + { + qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; + } + + entriesList += sep; + entriesList += qrcEntry; + sep = "@list_sep@"; + depends.push_back(qrcEntry); + } + return entriesList; +} + + +void cmQtAutoGeneratorInitializer::InitializeAutogenSources(cmTarget* target) +{ + cmMakefile* makefile = target->GetMakefile(); + + if (target->GetPropertyAsBool("AUTOMOC")) + { + std::string automocTargetName = + cmQtAutoGeneratorInitializer::GetAutogenTargetName(target); + std::string mocCppFile = makefile->GetCurrentBinaryDirectory(); + mocCppFile += "/"; + mocCppFile += automocTargetName; + mocCppFile += ".cpp"; + makefile->GetOrCreateSource(mocCppFile, true); + makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", + mocCppFile.c_str(), false); + + target->AddSource(mocCppFile); + } +} + +void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( + cmLocalGenerator* lg, + cmTarget* target) +{ + cmMakefile* makefile = target->GetMakefile(); + + std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajorVersion == "") + { + qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + } + + // create a custom target for running generators at buildtime: + std::string autogenTargetName = + cmQtAutoGeneratorInitializer::GetAutogenTargetName(target); + + std::string targetDir = + cmQtAutoGeneratorInitializer::GetAutogenTargetDir(target); + + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autogen"); + currentLine.push_back(targetDir); + currentLine.push_back("$<CONFIGURATION>"); + + cmCustomCommandLines commandLines; + commandLines.push_back(currentLine); + + std::string workingDirectory = cmSystemTools::CollapseFullPath( + "", makefile->GetCurrentBinaryDirectory()); + + std::vector<std::string> depends; + if (const char *autogenDepends = + target->GetProperty("AUTOGEN_TARGET_DEPENDS")) + { + cmSystemTools::ExpandListArgument(autogenDepends, depends); + } + std::vector<std::string> toolNames; + if (target->GetPropertyAsBool("AUTOMOC")) + { + toolNames.push_back("moc"); + } + if (target->GetPropertyAsBool("AUTOUIC")) + { + toolNames.push_back("uic"); + } + if (target->GetPropertyAsBool("AUTORCC")) + { + toolNames.push_back("rcc"); + } + + std::string tools = toolNames[0]; + toolNames.erase(toolNames.begin()); + while (toolNames.size() > 1) + { + tools += ", " + toolNames[0]; + toolNames.erase(toolNames.begin()); + } + if (toolNames.size() == 1) + { + tools += " and " + toolNames[0]; + } + std::string autogenComment = "Automatic " + tools + " for target "; + autogenComment += target->GetName(); + +#if defined(_WIN32) && !defined(__CYGWIN__) + bool usePRE_BUILD = false; + cmGlobalGenerator* gg = lg->GetGlobalGenerator(); + if(gg->GetName().find("Visual Studio") != std::string::npos) + { + cmGlobalVisualStudioGenerator* vsgg = + static_cast<cmGlobalVisualStudioGenerator*>(gg); + // Under VS >= 7 use a PRE_BUILD event instead of a separate target to + // reduce the number of targets loaded into the IDE. + // This also works around a VS 11 bug that may skip updating the target: + // https://connect.microsoft.com/VisualStudio/feedback/details/769495 + usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7; + if(usePRE_BUILD) + { + for (std::vector<std::string>::iterator it = depends.begin(); + it != depends.end(); ++it) + { + if(!makefile->FindTargetToUse(it->c_str())) + { + usePRE_BUILD = false; + break; + } + } + } + } +#endif + + std::vector<std::string> rcc_output; + bool const isNinja = + lg->GetGlobalGenerator()->GetName() == "Ninja"; + if(isNinja +#if defined(_WIN32) && !defined(__CYGWIN__) + || usePRE_BUILD +#endif + ) + { + std::vector<cmSourceFile*> srcFiles; + cmGeneratorTarget* gtgt = + lg->GetGlobalGenerator()->GetGeneratorTarget(target); + gtgt->GetConfigCommonSourceFiles(srcFiles); + for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); + fileIt != srcFiles.end(); + ++fileIt) + { + cmSourceFile* sf = *fileIt; + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath()); + + std::string ext = sf->GetExtension(); + + if (target->GetPropertyAsBool("AUTORCC")) + { + if (ext == "qrc" + && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) + { + std::string basename = cmsys::SystemTools:: + GetFilenameWithoutLastExtension(absFile); + + std::string rcc_output_dir = target->GetSupportDirectory(); + cmSystemTools::MakeDirectory(rcc_output_dir.c_str()); + std::string rcc_output_file = rcc_output_dir; + rcc_output_file += "/qrc_" + basename + ".cpp"; + rcc_output.push_back(rcc_output_file); + + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) + { + if (qtMajorVersion == "5") + { + cmQtAutoGeneratorInitializer::ListQt5RccInputs(sf, target, + depends); + } + else + { + cmQtAutoGeneratorInitializer::ListQt4RccInputs(sf, depends); + } +#if defined(_WIN32) && !defined(__CYGWIN__) + // Cannot use PRE_BUILD because the resource files themselves + // may not be sources within the target so VS may not know the + // target needs to re-build at all. + usePRE_BUILD = false; +#endif + } + } + } + } + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + if(usePRE_BUILD) + { + // Add the pre-build command directly to bypass the OBJECT_LIBRARY + // rejection in cmMakefile::AddCustomCommandToTarget because we know + // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. + std::vector<std::string> no_output; + std::vector<std::string> no_byproducts; + cmCustomCommand cc(makefile, no_output, no_byproducts, depends, + commandLines, autogenComment.c_str(), + workingDirectory.c_str()); + cc.SetEscapeOldStyle(false); + cc.SetEscapeAllowMakeVars(true); + target->AddPreBuildCommand(cc); + } + else +#endif + { + cmTarget* autogenTarget = makefile->AddUtilityCommand( + autogenTargetName, true, + workingDirectory.c_str(), + /*byproducts=*/rcc_output, depends, + commandLines, false, autogenComment.c_str()); + + cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg); + makefile->AddGeneratorTarget(autogenTarget, gt); + + // Set target folder + const char* autogenFolder = makefile->GetState() + ->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); + if (!autogenFolder) + { + autogenFolder = makefile->GetState() + ->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); + } + if (autogenFolder && *autogenFolder) + { + autogenTarget->SetProperty("FOLDER", autogenFolder); + } + else + { + // inherit FOLDER property from target (#13688) + copyTargetProperty(autogenTarget, target, "FOLDER"); + } + + target->AddUtility(autogenTargetName); + } +} + +static void GetCompileDefinitionsAndDirectories(cmTarget const* target, + const std::string& config, + std::string &incs, + std::string &defs) +{ + cmMakefile* makefile = target->GetMakefile(); + cmGlobalGenerator* globalGen = makefile->GetGlobalGenerator(); + std::vector<std::string> includeDirs; + cmGeneratorTarget *gtgt = globalGen->GetGeneratorTarget(target); + cmLocalGenerator *localGen = gtgt->GetLocalGenerator(); + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 + localGen->GetIncludeDirectories(includeDirs, gtgt, "CXX", config, false); + + incs = cmJoin(includeDirs, ";"); + + std::set<std::string> defines; + localGen->AddCompileDefinitions(defines, target, config, "CXX"); + + defs += cmJoin(defines, ";"); +} + +void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( + cmTarget const* target) +{ + cmMakefile* makefile = target->GetMakefile(); + + // forget the variables added here afterwards again: + cmMakefile::ScopePushPop varScope(makefile); + static_cast<void>(varScope); + + // create a custom target for running generators at buildtime: + std::string autogenTargetName = + cmQtAutoGeneratorInitializer::GetAutogenTargetName(target); + + makefile->AddDefinition("_moc_target_name", + cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); + makefile->AddDefinition("_origin_target_name", + cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); + + std::string targetDir = + cmQtAutoGeneratorInitializer::GetAutogenTargetDir(target); + + const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR"); + if (!qtVersion) + { + qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); + } + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + if (const char *targetQtVersion = + gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) + { + qtVersion = targetQtVersion; + } + if (qtVersion) + { + makefile->AddDefinition("_target_qt_version", qtVersion); + } + + std::vector<std::string> skipUic; + std::vector<std::string> skipMoc; + std::vector<std::string> mocSources; + std::vector<std::string> mocHeaders; + std::map<std::string, std::string> configIncludes; + std::map<std::string, std::string> configDefines; + std::map<std::string, std::string> configUicOptions; + + if (target->GetPropertyAsBool("AUTOMOC") + || target->GetPropertyAsBool("AUTOUIC") + || target->GetPropertyAsBool("AUTORCC")) + { + cmQtAutoGeneratorInitializer::SetupSourceFiles(target, skipMoc, + mocSources, mocHeaders, skipUic); + } + makefile->AddDefinition("_cpp_files", + cmOutputConverter::EscapeForCMake(cmJoin(mocSources, ";")).c_str()); + if (target->GetPropertyAsBool("AUTOMOC")) + { + cmQtAutoGeneratorInitializer::SetupAutoMocTarget(target, autogenTargetName, + skipMoc, mocHeaders, + configIncludes, configDefines); + } + if (target->GetPropertyAsBool("AUTOUIC")) + { + cmQtAutoGeneratorInitializer::SetupAutoUicTarget(target, skipUic, + configUicOptions); + } + if (target->GetPropertyAsBool("AUTORCC")) + { + cmQtAutoGeneratorInitializer::SetupAutoRccTarget(target); + } + + const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT"); + std::string inputFile = cmakeRoot; + inputFile += "/Modules/AutogenInfo.cmake.in"; + std::string outputFile = targetDir; + outputFile += "/AutogenInfo.cmake"; + makefile->AddDefinition("_qt_rcc_inputs", + makefile->GetDefinition("_qt_rcc_inputs_" + target->GetName())); + makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), + false, true, false); + + // Ensure we have write permission in case .in was read-only. + mode_t perm = 0; +#if defined(_WIN32) && !defined(__CYGWIN__) + mode_t mode_write = S_IWRITE; +#else + mode_t mode_write = S_IWUSR; +#endif + cmSystemTools::GetPermissions(outputFile, perm); + if (!(perm & mode_write)) + { + cmSystemTools::SetPermissions(outputFile, perm | mode_write); + } + if (!configDefines.empty() + || !configIncludes.empty() + || !configUicOptions.empty()) + { + cmsys::ofstream infoFile(outputFile.c_str(), std::ios::app); + if ( !infoFile ) + { + std::string error = "Internal CMake error when trying to open file: "; + error += outputFile.c_str(); + error += " for writing."; + cmSystemTools::Error(error.c_str()); + return; + } + if (!configDefines.empty()) + { + for (std::map<std::string, std::string>::iterator + it = configDefines.begin(), end = configDefines.end(); + it != end; ++it) + { + infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << + " " << it->second << ")\n"; + } + } + if (!configIncludes.empty()) + { + for (std::map<std::string, std::string>::iterator + it = configIncludes.begin(), end = configIncludes.end(); + it != end; ++it) + { + infoFile << "set(AM_MOC_INCLUDES_" << it->first << + " " << it->second << ")\n"; + } + } + if (!configUicOptions.empty()) + { + for (std::map<std::string, std::string>::iterator + it = configUicOptions.begin(), end = configUicOptions.end(); + it != end; ++it) + { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << + " " << it->second << ")\n"; + } + } + } +} + +void cmQtAutoGeneratorInitializer::SetupSourceFiles(cmTarget const* target, + std::vector<std::string>& skipMoc, + std::vector<std::string>& mocSources, + std::vector<std::string>& mocHeaders, + std::vector<std::string>& skipUic) +{ + cmMakefile* makefile = target->GetMakefile(); + + std::vector<cmSourceFile*> srcFiles; + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + gtgt->GetConfigCommonSourceFiles(srcFiles); + + std::vector<std::string> newRccFiles; + + for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); + fileIt != srcFiles.end(); + ++fileIt) + { + cmSourceFile* sf = *fileIt; + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath()); + bool skipFileForMoc = + cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); + bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")); + + if(cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"))) + { + skipUic.push_back(absFile); + } + + std::string ext = sf->GetExtension(); + + if (target->GetPropertyAsBool("AUTORCC")) + { + if (ext == "qrc" + && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) + { + std::string basename = cmsys::SystemTools:: + GetFilenameWithoutLastExtension(absFile); + + std::string rcc_output_dir = target->GetSupportDirectory(); + cmSystemTools::MakeDirectory(rcc_output_dir.c_str()); + std::string rcc_output_file = rcc_output_dir; + rcc_output_file += "/qrc_" + basename + ".cpp"; + makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", + rcc_output_file.c_str(), false); + makefile->GetOrCreateSource(rcc_output_file, true); + newRccFiles.push_back(rcc_output_file); + } + } + + if (!generated) + { + if (skipFileForMoc) + { + skipMoc.push_back(absFile); + } + else + { + cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat( + ext.c_str()); + if (fileType == cmSystemTools::CXX_FILE_FORMAT) + { + mocSources.push_back(absFile); + } + else if (fileType == cmSystemTools::HEADER_FILE_FORMAT) + { + mocHeaders.push_back(absFile); + } + } + } + } + + for(std::vector<std::string>::const_iterator fileIt = newRccFiles.begin(); + fileIt != newRccFiles.end(); + ++fileIt) + { + const_cast<cmTarget*>(target)->AddSource(*fileIt); + } +} + +void cmQtAutoGeneratorInitializer::SetupAutoMocTarget(cmTarget const* target, + const std::string &autogenTargetName, + std::vector<std::string> const& skipMoc, + std::vector<std::string> const& mocHeaders, + std::map<std::string, std::string> &configIncludes, + std::map<std::string, std::string> &configDefines) +{ + cmMakefile* makefile = target->GetMakefile(); + + const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); + std::string _moc_options = (tmp!=0 ? tmp : ""); + makefile->AddDefinition("_moc_options", + cmOutputConverter::EscapeForCMake(_moc_options).c_str()); + makefile->AddDefinition("_skip_moc", + cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); + makefile->AddDefinition("_moc_headers", + cmOutputConverter::EscapeForCMake(cmJoin(mocHeaders, ";")).c_str()); + bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); + makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); + + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector<std::string> configs; + const std::string& config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, + _moc_incs, _moc_compile_defs); + + makefile->AddDefinition("_moc_incs", + cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); + makefile->AddDefinition("_moc_compile_defs", + cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); + + for (std::vector<std::string>::const_iterator li = configs.begin(); + li != configs.end(); ++li) + { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, *li, + config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) + { + configIncludes[*li] = + cmOutputConverter::EscapeForCMake(config_moc_incs); + if(_moc_incs.empty()) + { + _moc_incs = config_moc_incs; + } + } + if (config_moc_compile_defs != _moc_compile_defs) + { + configDefines[*li] = + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); + if(_moc_compile_defs.empty()) + { + _moc_compile_defs = config_moc_compile_defs; + } + } + } + + const char *qtVersion = makefile->GetDefinition("_target_qt_version"); + if (strcmp(qtVersion, "5") == 0) + { + cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc"); + if (!qt5Moc) + { + cmSystemTools::Error("Qt5::moc target not found ", + autogenTargetName.c_str()); + return; + } + makefile->AddDefinition("_qt_moc_executable", + qt5Moc->ImportedGetLocation("")); + } + else if (strcmp(qtVersion, "4") == 0) + { + cmTarget *qt4Moc = makefile->FindTargetToUse("Qt4::moc"); + if (!qt4Moc) + { + cmSystemTools::Error("Qt4::moc target not found ", + autogenTargetName.c_str()); + return; + } + makefile->AddDefinition("_qt_moc_executable", + qt4Moc->ImportedGetLocation("")); + } + else + { + cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " + "Qt 5 ", autogenTargetName.c_str()); + } +} + +static void GetUicOpts(cmTarget const* target, const std::string& config, + std::string &optString) +{ + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + std::vector<std::string> opts; + gtgt->GetAutoUicOptions(opts, config); + optString = cmJoin(opts, ";"); +} + +void cmQtAutoGeneratorInitializer::SetupAutoUicTarget(cmTarget const* target, + std::vector<std::string> const& skipUic, + std::map<std::string, std::string> &configUicOptions) +{ + cmMakefile *makefile = target->GetMakefile(); + + std::set<std::string> skipped; + skipped.insert(skipUic.begin(), skipUic.end()); + + makefile->AddDefinition("_skip_uic", + cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); + + std::vector<cmSourceFile*> uiFilesWithOptions + = makefile->GetQtUiFilesWithOptions(); + + const char *qtVersion = makefile->GetDefinition("_target_qt_version"); + + std::string _uic_opts; + std::vector<std::string> configs; + const std::string& config = makefile->GetConfigurations(configs); + GetUicOpts(target, config, _uic_opts); + + if (!_uic_opts.empty()) + { + _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); + makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); + } + for (std::vector<std::string>::const_iterator li = configs.begin(); + li != configs.end(); ++li) + { + std::string config_uic_opts; + GetUicOpts(target, *li, config_uic_opts); + if (config_uic_opts != _uic_opts) + { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(config_uic_opts); + if(_uic_opts.empty()) + { + _uic_opts = config_uic_opts; + } + } + } + + std::string uiFileFiles; + std::string uiFileOptions; + const char* sep = ""; + + for(std::vector<cmSourceFile*>::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); + ++fileIt) + { + cmSourceFile* sf = *fileIt; + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath()); + + if (!skipped.insert(absFile).second) + { + continue; + } + uiFileFiles += sep; + uiFileFiles += absFile; + uiFileOptions += sep; + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + uiFileOptions += opts; + sep = ";"; + } + + makefile->AddDefinition("_qt_uic_options_files", + cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); + makefile->AddDefinition("_qt_uic_options_options", + cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); + + std::string targetName = target->GetName(); + if (strcmp(qtVersion, "5") == 0) + { + cmTarget *qt5Uic = makefile->FindTargetToUse("Qt5::uic"); + if (!qt5Uic) + { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + else + { + makefile->AddDefinition("_qt_uic_executable", + qt5Uic->ImportedGetLocation("")); + } + } + else if (strcmp(qtVersion, "4") == 0) + { + cmTarget *qt4Uic = makefile->FindTargetToUse("Qt4::uic"); + if (!qt4Uic) + { + cmSystemTools::Error("Qt4::uic target not found ", + targetName.c_str()); + return; + } + makefile->AddDefinition("_qt_uic_executable", + qt4Uic->ImportedGetLocation("")); + } + else + { + cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " + "Qt 5 ", targetName.c_str()); + } +} + +void cmQtAutoGeneratorInitializer::MergeRccOptions( + std::vector<std::string> &opts, + const std::vector<std::string> &fileOpts, + bool isQt5) +{ + static const char* valueOptions[] = { + "name", + "root", + "compress", + "threshold" + }; + std::vector<std::string> extraOpts; + for(std::vector<std::string>::const_iterator it = fileOpts.begin(); + it != fileOpts.end(); ++it) + { + std::vector<std::string>::iterator existingIt + = std::find(opts.begin(), opts.end(), *it); + if (existingIt != opts.end()) + { + const char *o = it->c_str(); + if (*o == '-') + { + ++o; + } + if (isQt5 && *o == '-') + { + ++o; + } + if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(*it)) != cmArrayEnd(valueOptions)) + { + assert(existingIt + 1 != opts.end()); + *(existingIt + 1) = *(it + 1); + ++it; + } + } + else + { + extraOpts.push_back(*it); + } + } + opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); +} + +void cmQtAutoGeneratorInitializer::SetupAutoRccTarget(cmTarget const* target) +{ + std::string _rcc_files; + const char* sepRccFiles = ""; + cmMakefile *makefile = target->GetMakefile(); + + std::vector<cmSourceFile*> srcFiles; + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + gtgt->GetConfigCommonSourceFiles(srcFiles); + + std::string qrcInputs; + const char* qrcInputsSep = ""; + + std::string rccFileFiles; + std::string rccFileOptions; + const char *optionSep = ""; + + const char *qtVersion = makefile->GetDefinition("_target_qt_version"); + + std::vector<std::string> rccOptions; + if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) + { + cmSystemTools::ExpandListArgument(opts, rccOptions); + } + std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajorVersion == "") + { + qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + } + + for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); + fileIt != srcFiles.end(); + ++fileIt) + { + cmSourceFile* sf = *fileIt; + std::string ext = sf->GetExtension(); + if (ext == "qrc") + { + std::string absFile = cmsys::SystemTools::GetRealPath( + sf->GetFullPath()); + bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); + + if (!skip) + { + _rcc_files += sepRccFiles; + _rcc_files += absFile; + sepRccFiles = ";"; + + if (const char *prop = sf->GetProperty("AUTORCC_OPTIONS")) + { + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + cmQtAutoGeneratorInitializer::MergeRccOptions(rccOptions, optsVec, + strcmp(qtVersion, "5") == 0); + } + + if (!rccOptions.empty()) + { + rccFileFiles += optionSep; + rccFileFiles += absFile; + rccFileOptions += optionSep; + } + const char *listSep = ""; + for(std::vector<std::string>::const_iterator it = rccOptions.begin(); + it != rccOptions.end(); + ++it) + { + rccFileOptions += listSep; + rccFileOptions += *it; + listSep = "@list_sep@"; + } + optionSep = ";"; + + std::vector<std::string> depends; + + std::string entriesList; + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) + { + if (qtMajorVersion == "5") + { + entriesList = cmQtAutoGeneratorInitializer::ListQt5RccInputs(sf, + target, + depends); + } + else + { + entriesList = + cmQtAutoGeneratorInitializer::ListQt4RccInputs(sf, depends); + } + if (entriesList.empty()) + { + return; + } + } + qrcInputs += qrcInputsSep; + qrcInputs += entriesList; + qrcInputsSep = ";"; + } + } + } + makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(), + cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); + + makefile->AddDefinition("_rcc_files", + cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); + + makefile->AddDefinition("_qt_rcc_options_files", + cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); + makefile->AddDefinition("_qt_rcc_options_options", + cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); + + makefile->AddDefinition("_qt_rcc_executable", + cmQtAutoGeneratorInitializer::GetRccExecutable(target).c_str()); +} + +std::string cmQtAutoGeneratorInitializer::GetRccExecutable( + cmTarget const* target) +{ + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + cmMakefile *makefile = target->GetMakefile(); + const char *qtVersion = makefile->GetDefinition("_target_qt_version"); + if (!qtVersion) + { + qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR"); + if (!qtVersion) + { + qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); + } + if (const char *targetQtVersion = + gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) + { + qtVersion = targetQtVersion; + } + } + + std::string targetName = target->GetName(); + if (strcmp(qtVersion, "5") == 0) + { + cmTarget *qt5Rcc = makefile->FindTargetToUse("Qt5::rcc"); + if (!qt5Rcc) + { + cmSystemTools::Error("Qt5::rcc target not found ", + targetName.c_str()); + return std::string(); + } + return qt5Rcc->ImportedGetLocation(""); + } + else if (strcmp(qtVersion, "4") == 0) + { + cmTarget *qt4Rcc = makefile->FindTargetToUse("Qt4::rcc"); + if (!qt4Rcc) + { + cmSystemTools::Error("Qt4::rcc target not found ", + targetName.c_str()); + return std::string(); + } + return qt4Rcc->ImportedGetLocation(""); + } + + cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " + "Qt 5 ", targetName.c_str()); + return std::string(); +} diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h new file mode 100644 index 0000000..c22f172 --- /dev/null +++ b/Source/cmQtAutoGeneratorInitializer.h @@ -0,0 +1,67 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2004-2011 Kitware, Inc. + Copyright 2011 Alexander Neundorf (neundorf@kde.org) + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmQtAutoGeneratorInitializer_h +#define cmQtAutoGeneratorInitializer_h + +#include "cmStandardIncludes.h" + +#include <string> +#include <vector> +#include <map> + +class cmSourceFile; +class cmTarget; +class cmLocalGenerator; + +class cmQtAutoGeneratorInitializer +{ +public: + static void InitializeAutogenSources(cmTarget* target); + static void InitializeAutogenTarget(cmLocalGenerator* lg, cmTarget* target); + static void SetupAutoGenerateTarget(cmTarget const* target); + + static std::string GetAutogenTargetName(cmTarget const* target); + static std::string GetAutogenTargetDir(cmTarget const* target); + +private: + static void SetupSourceFiles(cmTarget const* target, + std::vector<std::string>& skipMoc, + std::vector<std::string>& mocSources, + std::vector<std::string>& mocHeaders, + std::vector<std::string>& skipUic); + + static void SetupAutoMocTarget(cmTarget const* target, + const std::string &autogenTargetName, + const std::vector<std::string>& skipMoc, + const std::vector<std::string>& mocHeaders, + std::map<std::string, std::string> &configIncludes, + std::map<std::string, std::string> &configDefines); + static void SetupAutoUicTarget(cmTarget const* target, + const std::vector<std::string>& skipUic, + std::map<std::string, std::string> &configUicOptions); + static void SetupAutoRccTarget(cmTarget const* target); + + static void MergeRccOptions(std::vector<std::string> &opts, + const std::vector<std::string> &fileOpts, bool isQt5); + + static std::string GetRccExecutable(cmTarget const* target); + + static std::string ListQt5RccInputs(cmSourceFile* sf, cmTarget const* target, + std::vector<std::string>& depends); + + static std::string ListQt4RccInputs(cmSourceFile* sf, + std::vector<std::string>& depends); +}; + +#endif diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index becfeba..bbeb3dc 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -12,17 +12,12 @@ ============================================================================*/ #include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" #include "cmMakefile.h" -#include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmState.h" #include "cmAlgorithms.h" -#if defined(_WIN32) && !defined(__CYGWIN__) -# include "cmGlobalVisualStudioGenerator.h" -#endif - #include <sys/stat.h> #include <cmsys/Terminal.h> @@ -36,7 +31,6 @@ #include "cmQtAutoGenerators.h" - static bool requiresMocing(const std::string& text, std::string ¯oName) { // this simple check is much much faster than the regexp @@ -105,28 +99,6 @@ static std::string extractSubDir(const std::string& absPath, return subDir; } - -static void copyTargetProperty(cmTarget* destinationTarget, - cmTarget* sourceTarget, - const std::string& propertyName) -{ - const char* propertyValue = sourceTarget->GetProperty(propertyName); - if (propertyValue) - { - destinationTarget->SetProperty(propertyName, propertyValue); - } -} - - -static std::string ReadAll(const std::string& filename) -{ - cmsys::ifstream file(filename.c_str()); - std::stringstream stream; - stream << file.rdbuf(); - file.close(); - return stream.str(); -} - cmQtAutoGenerators::cmQtAutoGenerators() :Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != 0) ,ColorOutput(true) @@ -151,692 +123,6 @@ cmQtAutoGenerators::cmQtAutoGenerators() } } -static std::string getAutogenTargetName(cmTarget const* target) -{ - std::string autogenTargetName = target->GetName(); - autogenTargetName += "_automoc"; - return autogenTargetName; -} - -static std::string getAutogenTargetDir(cmTarget const* target) -{ - cmMakefile* makefile = target->GetMakefile(); - std::string targetDir = makefile->GetCurrentBinaryDirectory(); - targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); - targetDir += "/"; - targetDir += getAutogenTargetName(target); - targetDir += ".dir/"; - return targetDir; -} - -static std::string cmQtAutoGeneratorsStripCR(std::string const& line) -{ - // Strip CR characters rcc may have printed (possibly more than one!). - std::string::size_type cr = line.find('\r'); - if (cr != line.npos) - { - return line.substr(0, cr); - } - return line; -} - -std::string cmQtAutoGenerators::ListQt5RccInputs(cmSourceFile* sf, - cmTarget const* target, - std::vector<std::string>& depends) -{ - std::string rccCommand = this->GetRccExecutable(target); - std::vector<std::string> qrcEntries; - - std::vector<std::string> command; - command.push_back(rccCommand); - command.push_back("-list"); - - std::string absFile = cmsys::SystemTools::GetRealPath( - sf->GetFullPath()); - - command.push_back(absFile); - - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &rccStdOut, &rccStdErr, - &retVal, 0, cmSystemTools::OUTPUT_NONE); - if (!result || retVal) - { - std::cerr << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath() - << " failed:\n" << rccStdOut << "\n" << rccStdErr << std::endl; - return std::string(); - } - - { - std::istringstream ostr(rccStdOut); - std::string oline; - while(std::getline(ostr, oline)) - { - oline = cmQtAutoGeneratorsStripCR(oline); - if(!oline.empty()) - { - qrcEntries.push_back(oline); - } - } - } - - { - std::istringstream estr(rccStdErr); - std::string eline; - while(std::getline(estr, eline)) - { - eline = cmQtAutoGeneratorsStripCR(eline); - if (cmHasLiteralPrefix(eline, "RCC: Error in")) - { - static std::string searchString = "Cannot find file '"; - - std::string::size_type pos = eline.find(searchString); - if (pos == std::string::npos) - { - std::cerr << "AUTOGEN: error: Rcc lists unparsable output " - << eline << std::endl; - return std::string(); - } - pos += searchString.length(); - std::string::size_type sz = eline.size() - pos - 1; - qrcEntries.push_back(eline.substr(pos, sz)); - } - } - } - - depends.insert(depends.end(), qrcEntries.begin(), qrcEntries.end()); - return cmJoin(qrcEntries, "@list_sep@"); -} - -std::string cmQtAutoGenerators::ListQt4RccInputs(cmSourceFile* sf, - std::vector<std::string>& depends) -{ - const std::string qrcContents = ReadAll(sf->GetFullPath()); - - cmsys::RegularExpression fileMatchRegex("(<file[^<]+)"); - - std::string entriesList; - const char* sep = ""; - - size_t offset = 0; - while (fileMatchRegex.find(qrcContents.c_str() + offset)) - { - std::string qrcEntry = fileMatchRegex.match(1); - - offset += qrcEntry.size(); - - cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - - if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) - { - qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; - } - - entriesList += sep; - entriesList += qrcEntry; - sep = "@list_sep@"; - depends.push_back(qrcEntry); - } - return entriesList; -} - -bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg, - cmTarget* target) -{ - cmMakefile* makefile = target->GetMakefile(); - // don't do anything if there is no Qt4 or Qt5Core (which contains moc): - std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajorVersion == "") - { - qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); - } - if (qtMajorVersion != "4" && qtMajorVersion != "5") - { - return false; - } - - if (target->GetPropertyAsBool("AUTOMOC")) - { - std::string automocTargetName = getAutogenTargetName(target); - std::string mocCppFile = makefile->GetCurrentBinaryDirectory(); - mocCppFile += "/"; - mocCppFile += automocTargetName; - mocCppFile += ".cpp"; - makefile->GetOrCreateSource(mocCppFile, true); - makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", - mocCppFile.c_str(), false); - - target->AddSource(mocCppFile); - } - // create a custom target for running generators at buildtime: - std::string autogenTargetName = getAutogenTargetName(target); - - std::string targetDir = getAutogenTargetDir(target); - - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autogen"); - currentLine.push_back(targetDir); - currentLine.push_back("$<CONFIGURATION>"); - - cmCustomCommandLines commandLines; - commandLines.push_back(currentLine); - - std::string workingDirectory = cmSystemTools::CollapseFullPath( - "", makefile->GetCurrentBinaryDirectory()); - - std::vector<std::string> depends; - if (const char *autogenDepends = - target->GetProperty("AUTOGEN_TARGET_DEPENDS")) - { - cmSystemTools::ExpandListArgument(autogenDepends, depends); - } - std::vector<std::string> toolNames; - if (target->GetPropertyAsBool("AUTOMOC")) - { - toolNames.push_back("moc"); - } - if (target->GetPropertyAsBool("AUTOUIC")) - { - toolNames.push_back("uic"); - } - if (target->GetPropertyAsBool("AUTORCC")) - { - toolNames.push_back("rcc"); - } - - std::string tools = toolNames[0]; - toolNames.erase(toolNames.begin()); - while (toolNames.size() > 1) - { - tools += ", " + toolNames[0]; - toolNames.erase(toolNames.begin()); - } - if (toolNames.size() == 1) - { - tools += " and " + toolNames[0]; - } - std::string autogenComment = "Automatic " + tools + " for target "; - autogenComment += target->GetName(); - -#if defined(_WIN32) && !defined(__CYGWIN__) - bool usePRE_BUILD = false; - cmGlobalGenerator* gg = lg->GetGlobalGenerator(); - if(gg->GetName().find("Visual Studio") != std::string::npos) - { - cmGlobalVisualStudioGenerator* vsgg = - static_cast<cmGlobalVisualStudioGenerator*>(gg); - // Under VS >= 7 use a PRE_BUILD event instead of a separate target to - // reduce the number of targets loaded into the IDE. - // This also works around a VS 11 bug that may skip updating the target: - // https://connect.microsoft.com/VisualStudio/feedback/details/769495 - usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7; - if(usePRE_BUILD) - { - for (std::vector<std::string>::iterator it = depends.begin(); - it != depends.end(); ++it) - { - if(!makefile->FindTargetToUse(it->c_str())) - { - usePRE_BUILD = false; - break; - } - } - } - } -#endif - - std::vector<std::string> rcc_output; - bool const isNinja = - lg->GetGlobalGenerator()->GetName() == "Ninja"; - if(isNinja -#if defined(_WIN32) && !defined(__CYGWIN__) - || usePRE_BUILD -#endif - ) - { - std::vector<cmSourceFile*> srcFiles; - cmGeneratorTarget* gtgt = - lg->GetGlobalGenerator()->GetGeneratorTarget(target); - gtgt->GetConfigCommonSourceFiles(srcFiles); - for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); - fileIt != srcFiles.end(); - ++fileIt) - { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath( - sf->GetFullPath()); - - std::string ext = sf->GetExtension(); - - if (target->GetPropertyAsBool("AUTORCC")) - { - if (ext == "qrc" - && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) - { - std::string basename = cmsys::SystemTools:: - GetFilenameWithoutLastExtension(absFile); - - std::string rcc_output_dir = target->GetSupportDirectory(); - cmSystemTools::MakeDirectory(rcc_output_dir.c_str()); - std::string rcc_output_file = rcc_output_dir; - rcc_output_file += "/qrc_" + basename + ".cpp"; - rcc_output.push_back(rcc_output_file); - - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) - { - if (qtMajorVersion == "5") - { - this->ListQt5RccInputs(sf, target, depends); - } - else - { - this->ListQt4RccInputs(sf, depends); - } -#if defined(_WIN32) && !defined(__CYGWIN__) - // Cannot use PRE_BUILD because the resource files themselves - // may not be sources within the target so VS may not know the - // target needs to re-build at all. - usePRE_BUILD = false; -#endif - } - } - } - } - } - -#if defined(_WIN32) && !defined(__CYGWIN__) - if(usePRE_BUILD) - { - // Add the pre-build command directly to bypass the OBJECT_LIBRARY - // rejection in cmMakefile::AddCustomCommandToTarget because we know - // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. - std::vector<std::string> no_output; - std::vector<std::string> no_byproducts; - cmCustomCommand cc(makefile, no_output, no_byproducts, depends, - commandLines, autogenComment.c_str(), - workingDirectory.c_str()); - cc.SetEscapeOldStyle(false); - cc.SetEscapeAllowMakeVars(true); - target->AddPreBuildCommand(cc); - } - else -#endif - { - cmTarget* autogenTarget = makefile->AddUtilityCommand( - autogenTargetName, true, - workingDirectory.c_str(), - /*byproducts=*/rcc_output, depends, - commandLines, false, autogenComment.c_str()); - - cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg); - makefile->AddGeneratorTarget(autogenTarget, gt); - - // Set target folder - const char* autogenFolder = makefile->GetState() - ->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); - if (!autogenFolder) - { - autogenFolder = makefile->GetState() - ->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); - } - if (autogenFolder && *autogenFolder) - { - autogenTarget->SetProperty("FOLDER", autogenFolder); - } - else - { - // inherit FOLDER property from target (#13688) - copyTargetProperty(autogenTarget, target, "FOLDER"); - } - - target->AddUtility(autogenTargetName); - } - - return true; -} - -static void GetCompileDefinitionsAndDirectories(cmTarget const* target, - const std::string& config, - std::string &incs, - std::string &defs) -{ - cmMakefile* makefile = target->GetMakefile(); - cmGlobalGenerator* globalGen = makefile->GetGlobalGenerator(); - std::vector<std::string> includeDirs; - cmGeneratorTarget *gtgt = globalGen->GetGeneratorTarget(target); - cmLocalGenerator *localGen = gtgt->GetLocalGenerator(); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 - localGen->GetIncludeDirectories(includeDirs, gtgt, "CXX", config, false); - - incs = cmJoin(includeDirs, ";"); - - std::set<std::string> defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - - defs += cmJoin(defines, ";"); -} - -void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) -{ - cmMakefile* makefile = target->GetMakefile(); - - // forget the variables added here afterwards again: - cmMakefile::ScopePushPop varScope(makefile); - static_cast<void>(varScope); - - // create a custom target for running generators at buildtime: - std::string autogenTargetName = getAutogenTargetName(target); - - makefile->AddDefinition("_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition("_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - - std::string targetDir = getAutogenTargetDir(target); - - const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR"); - if (!qtVersion) - { - qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); - } - cmGeneratorTarget *gtgt = target->GetMakefile() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); - if (const char *targetQtVersion = - gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) - { - qtVersion = targetQtVersion; - } - if (qtVersion) - { - makefile->AddDefinition("_target_qt_version", qtVersion); - } - - std::map<std::string, std::string> configIncludes; - std::map<std::string, std::string> configDefines; - std::map<std::string, std::string> configUicOptions; - - if (target->GetPropertyAsBool("AUTOMOC") - || target->GetPropertyAsBool("AUTOUIC") - || target->GetPropertyAsBool("AUTORCC")) - { - this->SetupSourceFiles(target); - } - makefile->AddDefinition("_cpp_files", - cmOutputConverter::EscapeForCMake(this->Sources).c_str()); - if (target->GetPropertyAsBool("AUTOMOC")) - { - this->SetupAutoMocTarget(target, autogenTargetName, - configIncludes, configDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) - { - this->SetupAutoUicTarget(target, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) - { - this->SetupAutoRccTarget(target); - } - - const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT"); - std::string inputFile = cmakeRoot; - inputFile += "/Modules/AutogenInfo.cmake.in"; - std::string outputFile = targetDir; - outputFile += "/AutogenInfo.cmake"; - makefile->AddDefinition("_qt_rcc_inputs", - makefile->GetDefinition("_qt_rcc_inputs_" + target->GetName())); - makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), - false, true, false); - - // Ensure we have write permission in case .in was read-only. - mode_t perm = 0; -#if defined(_WIN32) && !defined(__CYGWIN__) - mode_t mode_write = S_IWRITE; -#else - mode_t mode_write = S_IWUSR; -#endif - cmSystemTools::GetPermissions(outputFile, perm); - if (!(perm & mode_write)) - { - cmSystemTools::SetPermissions(outputFile, perm | mode_write); - } - if (!configDefines.empty() - || !configIncludes.empty() - || !configUicOptions.empty()) - { - cmsys::ofstream infoFile(outputFile.c_str(), std::ios::app); - if ( !infoFile ) - { - std::string error = "Internal CMake error when trying to open file: "; - error += outputFile.c_str(); - error += " for writing."; - cmSystemTools::Error(error.c_str()); - return; - } - if (!configDefines.empty()) - { - for (std::map<std::string, std::string>::iterator - it = configDefines.begin(), end = configDefines.end(); - it != end; ++it) - { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << - " " << it->second << ")\n"; - } - } - if (!configIncludes.empty()) - { - for (std::map<std::string, std::string>::iterator - it = configIncludes.begin(), end = configIncludes.end(); - it != end; ++it) - { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << - " " << it->second << ")\n"; - } - } - if (!configUicOptions.empty()) - { - for (std::map<std::string, std::string>::iterator - it = configUicOptions.begin(), end = configUicOptions.end(); - it != end; ++it) - { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << - " " << it->second << ")\n"; - } - } - } -} - -void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target) -{ - cmMakefile* makefile = target->GetMakefile(); - - const char* sepFiles = ""; - const char* sepHeaders = ""; - - std::vector<cmSourceFile*> srcFiles; - cmGeneratorTarget *gtgt = target->GetMakefile() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); - gtgt->GetConfigCommonSourceFiles(srcFiles); - - const char *skipMocSep = ""; - const char *skipUicSep = ""; - - std::vector<std::string> newRccFiles; - - for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); - fileIt != srcFiles.end(); - ++fileIt) - { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath( - sf->GetFullPath()); - bool skipMoc = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")); - - if(cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"))) - { - this->SkipUic += skipUicSep; - this->SkipUic += absFile; - skipUicSep = ";"; - } - - std::string ext = sf->GetExtension(); - - if (target->GetPropertyAsBool("AUTORCC")) - { - if (ext == "qrc" - && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) - { - std::string basename = cmsys::SystemTools:: - GetFilenameWithoutLastExtension(absFile); - - std::string rcc_output_dir = target->GetSupportDirectory(); - cmSystemTools::MakeDirectory(rcc_output_dir.c_str()); - std::string rcc_output_file = rcc_output_dir; - rcc_output_file += "/qrc_" + basename + ".cpp"; - makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", - rcc_output_file.c_str(), false); - makefile->GetOrCreateSource(rcc_output_file, true); - newRccFiles.push_back(rcc_output_file); - } - } - - if (!generated) - { - if (skipMoc) - { - this->SkipMoc += skipMocSep; - this->SkipMoc += absFile; - skipMocSep = ";"; - } - else - { - cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat( - ext.c_str()); - if (fileType == cmSystemTools::CXX_FILE_FORMAT) - { - this->Sources += sepFiles; - this->Sources += absFile; - sepFiles = ";"; - } - else if (fileType == cmSystemTools::HEADER_FILE_FORMAT) - { - this->Headers += sepHeaders; - this->Headers += absFile; - sepHeaders = ";"; - } - } - } - } - - for(std::vector<std::string>::const_iterator fileIt = newRccFiles.begin(); - fileIt != newRccFiles.end(); - ++fileIt) - { - const_cast<cmTarget*>(target)->AddSource(*fileIt); - } -} - -void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target, - const std::string &autogenTargetName, - std::map<std::string, std::string> &configIncludes, - std::map<std::string, std::string> &configDefines) -{ - cmMakefile* makefile = target->GetMakefile(); - - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp!=0 ? tmp : ""); - makefile->AddDefinition("_moc_options", - cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition("_skip_moc", - cmOutputConverter::EscapeForCMake(this->SkipMoc).c_str()); - makefile->AddDefinition("_moc_headers", - cmOutputConverter::EscapeForCMake(this->Headers).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector<std::string> configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, - _moc_incs, _moc_compile_defs); - - makefile->AddDefinition("_moc_incs", - cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition("_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector<std::string>::const_iterator li = configs.begin(); - li != configs.end(); ++li) - { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, - config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) - { - configIncludes[*li] = - cmOutputConverter::EscapeForCMake(config_moc_incs); - if(_moc_incs.empty()) - { - _moc_incs = config_moc_incs; - } - } - if (config_moc_compile_defs != _moc_compile_defs) - { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if(_moc_compile_defs.empty()) - { - _moc_compile_defs = config_moc_compile_defs; - } - } - } - - const char *qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) - { - cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc"); - if (!qt5Moc) - { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; - } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } - else if (strcmp(qtVersion, "4") == 0) - { - cmTarget *qt4Moc = makefile->FindTargetToUse("Qt4::moc"); - if (!qt4Moc) - { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; - } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } - else - { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", autogenTargetName.c_str()); - } -} - void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts, const std::vector<std::string> &fileOpts, bool isQt5) @@ -882,332 +168,6 @@ void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts, opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); } -static void GetUicOpts(cmTarget const* target, const std::string& config, - std::string &optString) -{ - cmGeneratorTarget *gtgt = target->GetMakefile() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); - std::vector<std::string> opts; - gtgt->GetAutoUicOptions(opts, config); - optString = cmJoin(opts, ";"); -} - -void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target, - std::map<std::string, std::string> &configUicOptions) -{ - cmMakefile *makefile = target->GetMakefile(); - - std::set<std::string> skipped; - std::vector<std::string> skipVec; - cmSystemTools::ExpandListArgument(this->SkipUic, skipVec); - skipped.insert(skipVec.begin(), skipVec.end()); - - makefile->AddDefinition("_skip_uic", - cmOutputConverter::EscapeForCMake(this->SkipUic).c_str()); - - std::vector<cmSourceFile*> uiFilesWithOptions - = makefile->GetQtUiFilesWithOptions(); - - const char *qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector<std::string> configs; - const std::string& config = makefile->GetConfigurations(configs); - GetUicOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) - { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector<std::string>::const_iterator li = configs.begin(); - li != configs.end(); ++li) - { - std::string config_uic_opts; - GetUicOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) - { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if(_uic_opts.empty()) - { - _uic_opts = config_uic_opts; - } - } - } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for(std::vector<cmSourceFile*>::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); - ++fileIt) - { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath( - sf->GetFullPath()); - - if (!skipped.insert(absFile).second) - { - continue; - } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; - } - - makefile->AddDefinition("_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition("_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) - { - cmTarget *qt5Uic = makefile->FindTargetToUse("Qt5::uic"); - if (!qt5Uic) - { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway - } - else - { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); - } - } - else if (strcmp(qtVersion, "4") == 0) - { - cmTarget *qt4Uic = makefile->FindTargetToUse("Qt4::uic"); - if (!qt4Uic) - { - cmSystemTools::Error("Qt4::uic target not found ", - targetName.c_str()); - return; - } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } - else - { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", targetName.c_str()); - } -} - -void cmQtAutoGenerators::MergeRccOptions(std::vector<std::string> &opts, - const std::vector<std::string> &fileOpts, - bool isQt5) -{ - static const char* valueOptions[] = { - "name", - "root", - "compress", - "threshold" - }; - std::vector<std::string> extraOpts; - for(std::vector<std::string>::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) - { - std::vector<std::string>::iterator existingIt - = std::find(opts.begin(), opts.end(), *it); - if (existingIt != opts.end()) - { - const char *o = it->c_str(); - if (*o == '-') - { - ++o; - } - if (isQt5 && *o == '-') - { - ++o; - } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) - { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; - } - } - else - { - extraOpts.push_back(*it); - } - } - opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); -} - -void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) -{ - std::string _rcc_files; - const char* sepRccFiles = ""; - cmMakefile *makefile = target->GetMakefile(); - - std::vector<cmSourceFile*> srcFiles; - cmGeneratorTarget *gtgt = target->GetMakefile() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); - gtgt->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char *optionSep = ""; - - const char *qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::vector<std::string> rccOptions; - if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) - { - cmSystemTools::ExpandListArgument(opts, rccOptions); - } - std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajorVersion == "") - { - qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); - } - - for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); - fileIt != srcFiles.end(); - ++fileIt) - { - cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") - { - std::string absFile = cmsys::SystemTools::GetRealPath( - sf->GetFullPath()); - bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - - if (!skip) - { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - - if (const char *prop = sf->GetProperty("AUTORCC_OPTIONS")) - { - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - this->MergeRccOptions(rccOptions, optsVec, - strcmp(qtVersion, "5") == 0); - } - - if (!rccOptions.empty()) - { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char *listSep = ""; - for(std::vector<std::string>::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); - ++it) - { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; - } - optionSep = ";"; - - std::vector<std::string> depends; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) - { - if (qtMajorVersion == "5") - { - entriesList = this->ListQt5RccInputs(sf, target, depends); - } - else - { - entriesList = this->ListQt4RccInputs(sf, depends); - } - if (entriesList.empty()) - { - return; - } - } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; - } - } - } - makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(), - cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - - makefile->AddDefinition("_rcc_files", - cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - - makefile->AddDefinition("_qt_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition("_qt_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - - makefile->AddDefinition("_qt_rcc_executable", - this->GetRccExecutable(target).c_str()); -} - -std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) -{ - cmGeneratorTarget *gtgt = target->GetMakefile() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); - cmMakefile *makefile = target->GetMakefile(); - const char *qtVersion = makefile->GetDefinition("_target_qt_version"); - if (!qtVersion) - { - qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR"); - if (!qtVersion) - { - qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); - } - if (const char *targetQtVersion = - gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) - { - qtVersion = targetQtVersion; - } - } - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) - { - cmTarget *qt5Rcc = makefile->FindTargetToUse("Qt5::rcc"); - if (!qt5Rcc) - { - cmSystemTools::Error("Qt5::rcc target not found ", - targetName.c_str()); - return std::string(); - } - return qt5Rcc->ImportedGetLocation(""); - } - else if (strcmp(qtVersion, "4") == 0) - { - cmTarget *qt4Rcc = makefile->FindTargetToUse("Qt4::rcc"); - if (!qt4Rcc) - { - cmSystemTools::Error("Qt4::rcc target not found ", - targetName.c_str()); - return std::string(); - } - return qt4Rcc->ImportedGetLocation(""); - } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", targetName.c_str()); - return std::string(); -} - bool cmQtAutoGenerators::Run(const std::string& targetDirectory, const std::string& config) { @@ -1219,19 +179,18 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, cmState::Snapshot snapshot = cm.GetCurrentSnapshot(); cmsys::auto_ptr<cmMakefile> mf(new cmMakefile(&gg, snapshot)); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator(mf.get())); - lg->GetMakefile()->SetCurrentBinaryDirectory(targetDirectory); - lg->GetMakefile()->SetCurrentSourceDirectory(targetDirectory); - gg.SetCurrentMakefile(lg->GetMakefile()); + mf->SetCurrentBinaryDirectory(targetDirectory); + mf->SetCurrentSourceDirectory(targetDirectory); + gg.SetCurrentMakefile(mf.get()); - this->ReadAutogenInfoFile(lg->GetMakefile(), targetDirectory, config); - this->ReadOldMocDefinitionsFile(lg->GetMakefile(), targetDirectory); + this->ReadAutogenInfoFile(mf.get(), targetDirectory, config); + this->ReadOldMocDefinitionsFile(mf.get(), targetDirectory); this->Init(); if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - success = this->RunAutogen(lg->GetMakefile()); + success = this->RunAutogen(mf.get()); } this->WriteOldMocDefinitionsFile(targetDirectory); @@ -1533,6 +492,14 @@ void cmQtAutoGenerators::Init() } +static std::string ReadAll(const std::string& filename) +{ + cmsys::ifstream file(filename.c_str()); + std::stringstream stream; + stream << file.rdbuf(); + file.close(); + return stream.str(); +} bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) { @@ -2251,7 +1218,8 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& realName, { std::vector<std::string> fileOpts; cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - this->MergeUicOptions(opts, fileOpts, this->QtMajorVersion == "5"); + cmQtAutoGenerators::MergeUicOptions(opts, fileOpts, + this->QtMajorVersion == "5"); } command.insert(command.end(), opts.begin(), opts.end()); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 4f03348..ab7b6ed 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -15,10 +15,11 @@ #define cmQtAutoGenerators_h #include <list> +#include <vector> +#include <string> +#include <map> -class cmGlobalGenerator; class cmMakefile; -class cmLocalGenerator; class cmQtAutoGenerators { @@ -26,18 +27,7 @@ public: cmQtAutoGenerators(); bool Run(const std::string& targetDirectory, const std::string& config); - bool InitializeAutogenTarget(cmLocalGenerator* lg, cmTarget* target); - void SetupAutoGenerateTarget(cmTarget const* target); - void SetupSourceFiles(cmTarget const* target); - private: - void SetupAutoMocTarget(cmTarget const* target, - const std::string &autogenTargetName, - std::map<std::string, std::string> &configIncludes, - std::map<std::string, std::string> &configDefines); - void SetupAutoUicTarget(cmTarget const* target, - std::map<std::string, std::string> &configUicOptions); - void SetupAutoRccTarget(cmTarget const* target); bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, @@ -83,20 +73,9 @@ private: bool EndsWith(const std::string& str, const std::string& with); bool StartsWith(const std::string& str, const std::string& with); - void MergeUicOptions(std::vector<std::string> &opts, - const std::vector<std::string> &fileOpts, bool isQt5); - - void MergeRccOptions(std::vector<std::string> &opts, + static void MergeUicOptions(std::vector<std::string> &opts, const std::vector<std::string> &fileOpts, bool isQt5); - std::string GetRccExecutable(cmTarget const* target); - - std::string ListQt5RccInputs(cmSourceFile* sf, cmTarget const* target, - std::vector<std::string>& depends); - - std::string ListQt4RccInputs(cmSourceFile* sf, - std::vector<std::string>& depends); - bool InputFilesNewerThanQrc(const std::string& qrcFile, const std::string& rccOutput); diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h index 94161f8..410b370 100644 --- a/Source/cmRemoveCommand.h +++ b/Source/cmRemoveCommand.h @@ -47,12 +47,6 @@ public: */ virtual std::string GetName() const {return "remove";} - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmRemoveCommand, cmCommand); }; diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 306276b..1d70ad6 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -48,7 +48,7 @@ bool cmSetCommand return true; } - // if it will be cleared, then clear it if it isn;t already clear + // if it will be cleared, then clear it if it isn't already clear if (currValue) { cmSystemTools::PutEnv(putEnvArg); @@ -59,7 +59,7 @@ bool cmSetCommand // SET (VAR) // Removes the definition of VAR. if (args.size() == 1) { - this->Makefile->RemoveDefinition(args[0]); + this->Makefile->RemoveDefinition(variable); return true; } // SET (VAR PARENT_SCOPE) // Removes the definition of VAR diff --git a/Source/cmState.cxx b/Source/cmState.cxx index b30c10b..ce9ff32 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -1067,7 +1067,8 @@ cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const PositionType parentPos = this->Position->DirectoryParent; if (parentPos != this->State->SnapshotData.Root()) { - snapshot = Snapshot(this->State, parentPos); + snapshot = Snapshot(this->State, + parentPos->BuildSystemDirectory->DirectoryEnd); } return snapshot; @@ -1376,11 +1377,16 @@ cmBacktraceRange GetPropertyBacktraces(T const& content, template <typename T, typename U, typename V> void AppendEntry(T& content, U& backtraces, V& endContentPosition, - const std::string& vec, const cmListFileBacktrace& lfbt) + const std::string& value, const cmListFileBacktrace& lfbt) { + if (value.empty()) + { + return; + } + assert(endContentPosition == content.size()); - content.push_back(vec); + content.push_back(value); backtraces.push_back(lfbt); endContentPosition = content.size(); diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h index 6addd8f..bcefd2c 100644 --- a/Source/cmSubdirCommand.h +++ b/Source/cmSubdirCommand.h @@ -44,12 +44,6 @@ public: */ virtual std::string GetName() const { return "subdirs";} - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmSubdirCommand, cmCommand); }; diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h index 75a5685..3f3507e 100644 --- a/Source/cmSubdirDependsCommand.h +++ b/Source/cmSubdirDependsCommand.h @@ -21,7 +21,6 @@ public: virtual bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus &status); virtual std::string GetName() const { return "subdir_depends";} - virtual bool IsDiscouraged() const { return true; } cmTypeMacro(cmSubdirDependsCommand, cmCommand); }; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 005a803..2c5aa8a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2045,10 +2045,11 @@ bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile) cmSystemToolsWindowsHandle hFrom = CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fromFile).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, - OPEN_EXISTING, 0, 0); + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); cmSystemToolsWindowsHandle hTo = CreateFileW(SystemTools::ConvertToWindowsExtendedPath(toFile).c_str(), - GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0); if(!hFrom || !hTo) { return false; @@ -2100,7 +2101,8 @@ bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t) #if defined(_WIN32) && !defined(__CYGWIN__) cmSystemToolsWindowsHandle h = CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fname).c_str(), - GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0); if(!h) { return false; @@ -2127,7 +2129,8 @@ bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t) #if defined(_WIN32) && !defined(__CYGWIN__) cmSystemToolsWindowsHandle h = CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fname).c_str(), - GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + FILE_WRITE_ATTRIBUTES, 0, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0); if(!h) { return false; @@ -2216,6 +2219,7 @@ static std::string cmSystemToolsCTestCommand; static std::string cmSystemToolsCPackCommand; static std::string cmSystemToolsCMakeCursesCommand; static std::string cmSystemToolsCMakeGUICommand; +static std::string cmSystemToolsCMClDepsCommand; static std::string cmSystemToolsCMakeRoot; void cmSystemTools::FindCMakeResources(const char* argv0) { @@ -2308,6 +2312,13 @@ void cmSystemTools::FindCMakeResources(const char* argv0) { cmSystemToolsCMakeCursesCommand = ""; } + cmSystemToolsCMClDepsCommand = exe_dir; + cmSystemToolsCMClDepsCommand += "/cmcldeps"; + cmSystemToolsCMClDepsCommand += cmSystemTools::GetExecutableExtension(); + if(!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand.c_str())) + { + cmSystemToolsCMClDepsCommand = ""; + } #ifdef CMAKE_BUILD_WITH_CMAKE // Install tree has "<prefix>/bin/cmake" and "<prefix><CMAKE_DATA_DIR>". @@ -2375,6 +2386,12 @@ std::string const& cmSystemTools::GetCMakeGUICommand() } //---------------------------------------------------------------------------- +std::string const& cmSystemTools::GetCMClDepsCommand() +{ + return cmSystemToolsCMClDepsCommand; +} + +//---------------------------------------------------------------------------- std::string const& cmSystemTools::GetCMakeRoot() { return cmSystemToolsCMakeRoot; @@ -2760,6 +2777,14 @@ bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, } //---------------------------------------------------------------------------- +bool cmSystemTools::VersionCompareGreater(std::string const& lhs, + std::string const& rhs) +{ + return cmSystemTools::VersionCompare( + cmSystemTools::OP_GREATER, lhs.c_str(), rhs.c_str()); +} + +//---------------------------------------------------------------------------- bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, bool* removed) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index d14897f..b6b0978 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -294,6 +294,8 @@ public: * Compare versions */ static bool VersionCompare(CompareOp op, const char* lhs, const char* rhs); + static bool VersionCompareGreater(std::string const& lhs, + std::string const& rhs); /** * Determine the file type based on the extension @@ -426,6 +428,7 @@ public: static std::string const& GetCMakeCommand(); static std::string const& GetCMakeGUICommand(); static std::string const& GetCMakeCursesCommand(); + static std::string const& GetCMClDepsCommand(); static std::string const& GetCMakeRoot(); /** Echo a message in color using KWSys's Terminal cprintf. */ diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 3425f34..bb44956 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -347,6 +347,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) { this->SetPropertyDefault("ANDROID_GUI", 0); this->SetPropertyDefault("CROSSCOMPILING_EMULATOR", 0); + this->SetPropertyDefault("ENABLE_EXPORTS", 0); } if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY || this->TargetTypeValue == cmTarget::MODULE_LIBRARY) @@ -636,7 +637,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, { assert(this->GetType() != INTERFACE_LIBRARY); - if (!this->Makefile->IsConfigured()) + if (!this->GetMakefile()->GetGlobalGenerator()->GetConfigureDoneCMP0026()) { // At configure-time, this method can be called as part of getting the // LOCATION property or to export() a file to be include()d. However @@ -682,7 +683,7 @@ void cmTarget::GetSourceFiles(std::vector<std::string> &files, "SOURCES") != debugProperties.end(); - if (this->Makefile->IsConfigured()) + if (this->GetMakefile()->GetGlobalGenerator()->GetConfigureDoneCMP0026()) { this->DebugSourcesDone = true; } @@ -1706,7 +1707,7 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, } else if(prop == "INCLUDE_DIRECTORIES") { - if (value) + if (value && *value) { this->Internal->IncludeDirectoriesEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); @@ -1715,7 +1716,7 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, } else if(prop == "COMPILE_OPTIONS") { - if (value) + if (value && *value) { this->Internal->CompileOptionsEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); @@ -1724,7 +1725,7 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, } else if(prop == "COMPILE_FEATURES") { - if (value) + if (value && *value) { this->Internal->CompileFeaturesEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); @@ -1733,7 +1734,7 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, } else if(prop == "COMPILE_DEFINITIONS") { - if (value) + if (value && *value) { this->Internal->CompileDefinitionsEntries.push_back(value); cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); @@ -1749,7 +1750,7 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, } else if (prop == "LINK_LIBRARIES") { - if (value) + if (value && *value) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); cmValueWithOrigin entry(value, lfbt); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index c86ec24..3e71dbd 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -41,7 +41,8 @@ F(CMP0046) \ F(CMP0052) \ F(CMP0060) \ - F(CMP0063) + F(CMP0063) \ + F(CMP0065) class cmake; class cmMakefile; diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h index da927c7..1af2bfe 100644 --- a/Source/cmUseMangledMesaCommand.h +++ b/Source/cmUseMangledMesaCommand.h @@ -23,7 +23,6 @@ public: cmExecutionStatus &status); virtual std::string GetName() const { return "use_mangled_mesa";} virtual bool IsScriptable() const { return true; } - virtual bool IsDiscouraged() const { return true; } protected: void CopyAndFullPathMesaHeader(const char* source, const char* outdir); diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h index 23afdbe..8863ff5 100644 --- a/Source/cmUtilitySourceCommand.h +++ b/Source/cmUtilitySourceCommand.h @@ -22,7 +22,6 @@ public: virtual bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus &status); virtual std::string GetName() const { return "utility_source";} - virtual bool IsDiscouraged() const { return true; } }; #endif diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h index 7e68de1..5b0477f 100644 --- a/Source/cmVariableRequiresCommand.h +++ b/Source/cmVariableRequiresCommand.h @@ -22,7 +22,6 @@ public: virtual bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus &status); virtual std::string GetName() const { return "variable_requires";} - virtual bool IsDiscouraged() const { return true; } }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 4c380f7..2395ce7 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -9,6 +9,7 @@ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ +#include "windows.h" #include "cmVisualStudio10TargetGenerator.h" #include "cmGlobalVisualStudio10Generator.h" #include "cmGeneratorTarget.h" @@ -462,6 +463,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteString("<Import Project=\"" VS10_USER_PROPS "\"" " Condition=\"exists('" VS10_USER_PROPS "')\"" " Label=\"LocalAppDataPlatform\" />\n", 2); + this->WritePlatformExtensions(); this->WriteString("</ImportGroup>\n", 1); this->WriteString("<PropertyGroup Label=\"UserMacros\" />\n", 1); this->WriteWinRTPackageCertificateKeyFile(); @@ -474,6 +476,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->WriteXamlFilesGroup(); this->WriteWinRTReferences(); this->WriteProjectReferences(); + this->WriteSDKReferences(); this->WriteString( "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\"" " />\n", 1); @@ -871,6 +874,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, fout << "# generated from CMake\n"; fout.flush(); fout.close(); + // Force given file to have a very old timestamp, thus + // preventing dependent rebuilds. + this->ForceOld(sourcePath); } else { @@ -1303,6 +1309,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) { tool = "XML"; } + if(this->NsightTegra) { // Nsight Tegra needs specific file types to check up-to-dateness. @@ -2203,6 +2210,33 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) } } +void cmVisualStudio10TargetGenerator::WriteManifestOptions( + std::string const& config) +{ + if (this->Target->GetType() != cmTarget::EXECUTABLE && + this->Target->GetType() != cmTarget::SHARED_LIBRARY && + this->Target->GetType() != cmTarget::MODULE_LIBRARY) + { + return; + } + + std::vector<cmSourceFile const*> manifest_srcs; + this->GeneratorTarget->GetManifests(manifest_srcs, config); + if (!manifest_srcs.empty()) + { + this->WriteString("<Manifest>\n", 2); + this->WriteString("<AdditionalManifestFiles>", 3); + for (std::vector<cmSourceFile const*>::const_iterator + mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi) + { + std::string m = this->ConvertPath((*mi)->GetFullPath(), false); + this->ConvertToWindowsSlash(m); + (*this->BuildFileStream) << m << ";"; + } + (*this->BuildFileStream) << "</AdditionalManifestFiles>\n"; + this->WriteString("</Manifest>\n", 2); + } +} //---------------------------------------------------------------------------- void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( @@ -2559,7 +2593,8 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) // A Windows Runtime component uses internal .NET metadata, // so does not have an import library. - if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT")) + if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT") && + this->Target->GetType() != cmTarget::EXECUTABLE) { linkOptions.AddFlag("GenerateWindowsMetadata", "true"); } @@ -2630,7 +2665,7 @@ cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config) { this->WriteString("<ProjectReference>\n", 2); this->WriteString( - " <LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 2); + "<LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 3); this->WriteString("</ProjectReference>\n", 2); } } @@ -2740,6 +2775,8 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteLinkOptions(*i); // output lib flags <Lib></Lib> this->WriteLibOptions(*i); + // output manifest flags <Manifest></Manifest> + this->WriteManifestOptions(*i); if(this->NsightTegra && this->Target->GetType() == cmTarget::EXECUTABLE && this->Target->GetPropertyAsBool("ANDROID_GUI")) @@ -2820,7 +2857,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() = this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget); typedef cmGlobalVisualStudioGenerator::OrderedTargetDependSet OrderedTargetDependSet; - OrderedTargetDependSet depends(unordered); + OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET); this->WriteString("<ItemGroup>\n", 1); for( OrderedTargetDependSet::const_iterator i = depends.begin(); i != depends.end(); ++i) @@ -2863,6 +2900,101 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() this->WriteString("</ItemGroup>\n", 1); } +void cmVisualStudio10TargetGenerator::WritePlatformExtensions() +{ + // This only applies to Windows 10 apps + if (this->GlobalGenerator->TargetsWindowsStore() && + cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) + { + const char* desktopExtensionsVersion = + this->Target->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION"); + if (desktopExtensionsVersion) + { + this->WriteSinglePlatformExtension("WindowsDesktop", + desktopExtensionsVersion); + } + const char* mobileExtensionsVersion = + this->Target->GetProperty("VS_MOBILE_EXTENSIONS_VERSION"); + if (mobileExtensionsVersion) + { + this->WriteSinglePlatformExtension("WindowsMobile", + mobileExtensionsVersion); + } + } +} + +void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension( + std::string const& extension, + std::string const& version + ) +{ + this->WriteString("<Import Project=", 2); + (*this->BuildFileStream) + << "\"$([Microsoft.Build.Utilities.ToolLocationHelper]" + << "::GetPlatformExtensionSDKLocation(`" + << extension <<", Version=" << version + << "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, " + << "$(ExtensionSDKDirectoryRoot), null))" + << "\\DesignTime\\CommonConfiguration\\Neutral\\" + << extension << ".props\" " + << "Condition=\"exists('$(" + << "[Microsoft.Build.Utilities.ToolLocationHelper]" + << "::GetPlatformExtensionSDKLocation(`" + << extension << ", Version=" << version + << "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, " + << "$(ExtensionSDKDirectoryRoot), null))" + << "\\DesignTime\\CommonConfiguration\\Neutral\\" + << extension << ".props')\" />\n"; +} + +void cmVisualStudio10TargetGenerator::WriteSDKReferences() +{ + // This only applies to Windows 10 apps + if (this->GlobalGenerator->TargetsWindowsStore() && + cmHasLiteralPrefix(this->GlobalGenerator->GetSystemVersion(), "10.0")) + { + const char* desktopExtensionsVersion = + this->Target->GetProperty("VS_DESKTOP_EXTENSIONS_VERSION"); + const char* mobileExtensionsVersion = + this->Target->GetProperty("VS_MOBILE_EXTENSIONS_VERSION"); + const char* iotExtensionsVersion = + this->Target->GetProperty("VS_IOT_EXTENSIONS_VERSION"); + + if(desktopExtensionsVersion || mobileExtensionsVersion || + iotExtensionsVersion) + { + this->WriteString("<ItemGroup>\n", 1); + if(desktopExtensionsVersion) + { + this->WriteSingleSDKReference("WindowsDesktop", + desktopExtensionsVersion); + } + if(mobileExtensionsVersion) + { + this->WriteSingleSDKReference("WindowsMobile", + mobileExtensionsVersion); + } + if(iotExtensionsVersion) + { + this->WriteSingleSDKReference("WindowsIoT", + iotExtensionsVersion); + } + this->WriteString("</ItemGroup>\n", 1); + } + } +} + +void cmVisualStudio10TargetGenerator::WriteSingleSDKReference( + std::string const& extension, + std::string const& version + ) +{ + this->WriteString("<SDKReference Include=\"", 2); + (*this->BuildFileStream) << extension + << ", Version=" << version << "\" />\n"; +} + + void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile() { if((this->GlobalGenerator->TargetsWindowsStore() || @@ -2973,6 +3105,8 @@ IsXamlSource(const std::string& sourceFile) void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() { + cmGlobalVisualStudio10Generator* gg = + static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator); bool isAppContainer = false; bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone(); bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore(); @@ -2983,13 +3117,27 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() (*this->BuildFileStream) << (isWindowsPhone ? "Windows Phone" : "Windows Store") << "</ApplicationType>\n"; - this->WriteString("<ApplicationTypeRevision>", 2); - (*this->BuildFileStream) << cmVS10EscapeXML(v) - << "</ApplicationTypeRevision>\n"; this->WriteString("<DefaultLanguage>en-US" "</DefaultLanguage>\n", 2); - if(v == "8.1") + if (cmHasLiteralPrefix(v, "10.0")) { + this->WriteString("<ApplicationTypeRevision>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML("10.0") + << "</ApplicationTypeRevision>\n"; + // Visual Studio 14.0 is necessary for building 10.0 apps + this->WriteString("<MinimumVisualStudioVersion>14.0" + "</MinimumVisualStudioVersion>\n", 2); + + if(this->Target->GetType() < cmTarget::UTILITY) + { + isAppContainer = true; + } + } + else if(v == "8.1") + { + this->WriteString("<ApplicationTypeRevision>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(v) + << "</ApplicationTypeRevision>\n"; // Visual Studio 12.0 is necessary for building 8.1 apps this->WriteString("<MinimumVisualStudioVersion>12.0" "</MinimumVisualStudioVersion>\n", 2); @@ -3001,6 +3149,9 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() } else if (v == "8.0") { + this->WriteString("<ApplicationTypeRevision>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(v) + << "</ApplicationTypeRevision>\n"; // Visual Studio 11.0 is necessary for building 8.0 apps this->WriteString("<MinimumVisualStudioVersion>11.0" "</MinimumVisualStudioVersion>\n", 2); @@ -3029,6 +3180,38 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings() this->WriteString("<WindowsSDKDesktopARMSupport>true" "</WindowsSDKDesktopARMSupport>\n", 2); } + std::string const& targetPlatformVersion = + gg->GetWindowsTargetPlatformVersion(); + if (!targetPlatformVersion.empty()) + { + this->WriteString("<WindowsTargetPlatformVersion>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion) << + "</WindowsTargetPlatformVersion>\n"; + } + const char* targetPlatformMinVersion = + this->Target->GetProperty("VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION"); + if(targetPlatformMinVersion) + { + this->WriteString("<WindowsTargetPlatformMinVersion>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformMinVersion) << + "</WindowsTargetPlatformMinVersion>\n"; + } + else if (isWindowsStore && cmHasLiteralPrefix(v, "10.0")) + { + // If the min version is not set, then use the TargetPlatformVersion + if (!targetPlatformVersion.empty()) + { + this->WriteString("<WindowsTargetPlatformMinVersion>", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion) << + "</WindowsTargetPlatformMinVersion>\n"; + } + } + + // Added IoT Startup Task support + if(this->Target->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) + { + this->WriteString("<ContainsStartupTask>true</ContainsStartupTask>\n", 2); + } } void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles() @@ -3081,7 +3264,7 @@ void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles() { this->IsMissingFiles = true; } - else if (v == "8.1") + else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) { this->IsMissingFiles = true; } @@ -3115,6 +3298,10 @@ void cmVisualStudio10TargetGenerator::WriteMissingFiles() { this->WriteMissingFilesWS81(); } + else if (cmHasLiteralPrefix(v, "10.0")) + { + this->WriteMissingFilesWS10_0(); + } } } @@ -3376,6 +3563,64 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81() this->WriteCommonMissingFiles(manifestFile); } +void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0() +{ + std::string manifestFile = + this->DefaultArtifactDir + "/package.appxManifest"; + std::string artifactDir = + this->LocalGenerator->GetTargetDirectory(*this->Target); + this->ConvertToWindowsSlash(artifactDir); + std::string artifactDirXML = cmVS10EscapeXML(artifactDir); + std::string targetNameXML = cmVS10EscapeXML(this->Target->GetName()); + + cmGeneratedFileStream fout(manifestFile.c_str()); + fout.SetCopyIfDifferent(true); + + fout << + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<Package\n\t" + "xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\"" + "\txmlns:mp=\"http://schemas.microsoft.com/appx/2014/phone/manifest\"\n" + "\txmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\"" + "\n\tIgnorableNamespaces=\"uap mp\">\n\n" + "\t<Identity Name=\"" << this->GUID << "\" Publisher=\"CN=CMake\"" + " Version=\"1.0.0.0\" />\n" + "\t<mp:PhoneIdentity PhoneProductId=\"" << this->GUID << + "\" PhonePublisherId=\"00000000-0000-0000-0000-000000000000\"/>\n" + "\t<Properties>\n" + "\t\t<DisplayName>" << targetNameXML << "</DisplayName>\n" + "\t\t<PublisherDisplayName>CMake</PublisherDisplayName>\n" + "\t\t<Logo>" << artifactDirXML << "\\StoreLogo.png</Logo>\n" + "\t</Properties>\n" + "\t<Dependencies>\n" + "\t\t<TargetDeviceFamily Name=\"Windows.Universal\" " + "MinVersion=\"10.0.0.0\" MaxVersionTested=\"10.0.0.0\" />\n" + "\t</Dependencies>\n" + + "\t<Resources>\n" + "\t\t<Resource Language=\"x-generate\" />\n" + "\t</Resources>\n" + "\t<Applications>\n" + "\t\t<Application Id=\"App\"" + " Executable=\"" << targetNameXML << ".exe\"" + " EntryPoint=\"" << targetNameXML << ".App\">\n" + "\t\t\t<uap:VisualElements\n" + "\t\t\t\tDisplayName=\"" << targetNameXML << "\"\n" + "\t\t\t\tDescription=\"" << targetNameXML << "\"\n" + "\t\t\t\tBackgroundColor=\"#336699\"\n" + "\t\t\t\tSquare150x150Logo=\"" << artifactDirXML << "\\Logo.png\"\n" + "\t\t\t\tSquare44x44Logo=\"" << artifactDirXML << + "\\SmallLogo44x44.png\">\n" + "\t\t\t\t<uap:SplashScreen" + " Image=\"" << artifactDirXML << "\\SplashScreen.png\" />\n" + "\t\t\t</uap:VisualElements>\n" + "\t\t</Application>\n" + "\t</Applications>\n" + "</Package>\n"; + + this->WriteCommonMissingFiles(manifestFile); +} + void cmVisualStudio10TargetGenerator ::WriteCommonMissingFiles(const std::string& manifestFile) @@ -3399,6 +3644,14 @@ cmVisualStudio10TargetGenerator (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n"; this->AddedFiles.push_back(smallLogo); + std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png"; + cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", + smallLogo44, false); + this->ConvertToWindowsSlash(smallLogo44); + this->WriteString("<Image Include=\"", 2); + (*this->BuildFileStream) << cmVS10EscapeXML(smallLogo44) << "\" />\n"; + this->AddedFiles.push_back(smallLogo44); + std::string logo = this->DefaultArtifactDir + "/Logo.png"; cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false); @@ -3429,3 +3682,26 @@ cmVisualStudio10TargetGenerator this->WriteString("<None Include=\"", 2); (*this->BuildFileStream) << cmVS10EscapeXML(keyFile) << "\" />\n"; } + +bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const +{ + HANDLE h = CreateFileW( + cmSystemTools::ConvertToWindowsExtendedPath(source).c_str(), + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_WRITE, 0, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, 0); + if (!h) + { + return false; + } + + FILETIME const ftime_20010101 = { 3365781504u, 29389701u }; + if (!SetFileTime(h, &ftime_20010101, &ftime_20010101, &ftime_20010101)) + { + CloseHandle(h); + return false; + } + + CloseHandle(h); + return true; +} diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 451f8b2..15ed9f2 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -78,6 +78,13 @@ private: void WriteMissingFilesWP81(); void WriteMissingFilesWS80(); void WriteMissingFilesWS81(); + void WriteMissingFilesWS10_0(); + void WritePlatformExtensions(); + void WriteSinglePlatformExtension(std::string const& extension, + std::string const& version); + void WriteSDKReferences(); + void WriteSingleSDKReference(std::string const& extension, + std::string const& version); void WriteCommonMissingFiles(const std::string& manifestFile); void WriteTargetSpecificReferences(); @@ -111,6 +118,7 @@ private: void AddLibraries(cmComputeLinkInformation& cli, std::vector<std::string>& libVec); void WriteLibOptions(std::string const& config); + void WriteManifestOptions(std::string const& config); void WriteEvents(std::string const& configName); void WriteEvent(const char* name, std::vector<cmCustomCommand> const& commands, @@ -129,6 +137,8 @@ private: cmIDEFlagTable const* GetLinkFlagTable() const; cmIDEFlagTable const* GetMasmFlagTable() const; + bool ForceOld(const std::string& source) const; + private: typedef cmVisualStudioGeneratorOptions Options; typedef std::map<std::string, Options*> OptionsMap; diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index 012c580..4b7afd8 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -49,7 +49,20 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, mf.ExpandArguments(this->Args, expandedArguments); cmake::MessageType messageType; - cmConditionEvaluator conditionEvaluator(mf); + cmListFileContext execContext = this->GetStartingContext(); + + cmCommandContext commandContext; + commandContext.Line = execContext.Line; + commandContext.Name = execContext.Name; + + cmListFileContext conditionContext = + cmConditionEvaluator::GetConditionContext( + &mf, commandContext, + this->GetStartingContext().FilePath); + + cmConditionEvaluator conditionEvaluator( + mf, conditionContext, + mf.GetBacktrace(commandContext)); bool isTrue = conditionEvaluator.IsTrue( expandedArguments, errorString, messageType); diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h index 0d06878..89dc9ff 100644 --- a/Source/cmWriteFileCommand.h +++ b/Source/cmWriteFileCommand.h @@ -46,12 +46,6 @@ public: */ virtual std::string GetName() const { return "write_file";} - /** This command is kept for compatibility with older CMake versions. */ - virtual bool IsDiscouraged() const - { - return true; - } - cmTypeMacro(cmWriteFileCommand, cmCommand); }; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f069481..386f6a5 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -128,6 +128,8 @@ cmake::cmake() this->WarnUnused = false; this->WarnUnusedCli = true; this->CheckSystemVars = false; + this->SuppressDevWarnings = false; + this->DoSuppressDevWarnings = false; this->DebugOutput = false; this->DebugTryCompile = false; this->ClearBuildSystem = false; @@ -250,70 +252,15 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return false; } } - else if(cmHasLiteralPrefix(arg, "-W")) + else if(arg.find("-Wno-dev",0) == 0) { - std::string entry = arg.substr(2); - if (entry.empty()) - { - ++i; - if (i < args.size()) - { - entry = args[i]; - } - else - { - cmSystemTools::Error( - "-W must be followed with [no-][error=]<name>."); - return false; - } + this->SuppressDevWarnings = true; + this->DoSuppressDevWarnings = true; } - - std::string name; - bool foundNo = false; - bool foundError = false; - unsigned int nameStartPosition = 0; - - if (entry.find("no-", nameStartPosition) == 0) - { - foundNo = true; - nameStartPosition += 3; - } - - if (entry.find("error=", nameStartPosition) == 0) - { - foundError = true; - nameStartPosition += 6; - } - - name = entry.substr(nameStartPosition); - if (name.empty()) - { - cmSystemTools::Error("No warning name provided."); - return false; - } - - if (!foundNo && !foundError) - { - // -W<name> - this->WarningLevels[name] = std::max(this->WarningLevels[name], - WARNING_LEVEL); - } - else if (foundNo && !foundError) - { - // -Wno<name> - this->WarningLevels[name] = IGNORE_LEVEL; - } - else if (!foundNo && foundError) - { - // -Werror=<name> - this->WarningLevels[name] = ERROR_LEVEL; - } - else - { - // -Wno-error=<name> - this->WarningLevels[name] = std::min(this->WarningLevels[name], - WARNING_LEVEL); - } + else if(arg.find("-Wdev",0) == 0) + { + this->SuppressDevWarnings = false; + this->DoSuppressDevWarnings = true; } else if(arg.find("-U",0) == 0) { @@ -645,7 +592,11 @@ void cmake::SetArgs(const std::vector<std::string>& args, // skip for now i++; } - else if(arg.find("-W",0) == 0) + else if(arg.find("-Wno-dev",0) == 0) + { + // skip for now + } + else if(arg.find("-Wdev",0) == 0) { // skip for now } @@ -1232,121 +1183,25 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) int cmake::Configure() { - WarningLevel warningLevel; - - if (this->WarningLevels.count("deprecated") == 1) + if(this->DoSuppressDevWarnings) { - warningLevel = this->WarningLevels["deprecated"]; - if (warningLevel == IGNORE_LEVEL) - { - this->CacheManager-> - AddCacheEntry("CMAKE_WARN_DEPRECATED", "FALSE", - "Whether to issue deprecation warnings for" - " macros and functions.", - cmState::BOOL); - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEPRECATED", "FALSE", - "Whether to issue deprecation errors for macros" - " and functions.", - cmState::BOOL); - } - if (warningLevel == WARNING_LEVEL) - { - this->CacheManager-> - AddCacheEntry("CMAKE_WARN_DEPRECATED", "TRUE", - "Whether to issue deprecation warnings for" - " macros and functions.", - cmState::BOOL); - } - else if (warningLevel == ERROR_LEVEL) - { - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEPRECATED", "TRUE", - "Whether to issue deprecation errors for macros" - " and functions.", - cmState::BOOL); - } - } - - if (this->WarningLevels.count("dev") == 1) - { - bool setDeprecatedVariables = false; - - const char* cachedWarnDeprecated = - this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); - const char* cachedErrorDeprecated = - this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); - - // don't overwrite deprecated warning setting from a previous invocation - if (!cachedWarnDeprecated && !cachedErrorDeprecated) - { - setDeprecatedVariables = true; - } - - warningLevel = this->WarningLevels["dev"]; - if (warningLevel == IGNORE_LEVEL) + if(this->SuppressDevWarnings) { this->CacheManager-> AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "TRUE", "Suppress Warnings that are meant for" " the author of the CMakeLists.txt files.", cmState::INTERNAL); - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEVELOPER_WARNINGS", "FALSE", - "Suppress errors that are meant for" - " the author of the CMakeLists.txt files.", - cmState::INTERNAL); - - if (setDeprecatedVariables) - { - this->CacheManager-> - AddCacheEntry("CMAKE_WARN_DEPRECATED", "FALSE", - "Whether to issue deprecation warnings for" - " macros and functions.", - cmState::BOOL); - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEPRECATED", "FALSE", - "Whether to issue deprecation errors for macros" - " and functions.", - cmState::BOOL); - } } - else if (warningLevel == WARNING_LEVEL) + else { this->CacheManager-> AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", "FALSE", "Suppress Warnings that are meant for" " the author of the CMakeLists.txt files.", cmState::INTERNAL); - - if (setDeprecatedVariables) - { - this->CacheManager-> - AddCacheEntry("CMAKE_WARN_DEPRECATED", "TRUE", - "Whether to issue deprecation warnings for" - " macros and functions.", - cmState::BOOL); - } - } - else if (warningLevel == ERROR_LEVEL) - { - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEVELOPER_WARNINGS", "TRUE", - "Suppress errors that are meant for" - " the author of the CMakeLists.txt files.", - cmState::INTERNAL); - - if (setDeprecatedVariables) - { - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEPRECATED", "TRUE", - "Whether to issue deprecation errors for macros" - " and functions.", - cmState::BOOL); - } } } - int ret = this->ActualConfigure(); const char* delCacheVars = this->State ->GetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_"); @@ -1677,18 +1532,6 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) { this->AddCMakePaths(); } - - // don't turn dev warnings into errors by default, if no value has been - // specified for the flag, disable it - if (!this->State->GetCacheEntryValue("CMAKE_ERROR_DEVELOPER_WARNINGS")) - { - this->CacheManager-> - AddCacheEntry("CMAKE_ERROR_DEVELOPER_WARNINGS", "FALSE", - "Suppress errors that are meant for" - " the author of the CMakeLists.txt files.", - cmState::INTERNAL); - } - // Add any cache args if ( !this->SetCacheArgs(args) ) { @@ -2596,17 +2439,20 @@ bool cmake::PrintMessagePreamble(cmake::MessageType t, std::ostream& msg) { msg << "CMake Deprecation Warning"; } - else if (t == cmake::AUTHOR_WARNING) - { - msg << "CMake Warning (dev)"; - } - else if (t == cmake::AUTHOR_ERROR) - { - msg << "CMake Error (dev)"; - } else { msg << "CMake Warning"; + if(t == cmake::AUTHOR_WARNING) + { + // Allow suppression of these warnings. + const char* suppress = this->State->GetCacheEntryValue( + "CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); + if(suppress && cmSystemTools::IsOn(suppress)) + { + return false; + } + msg << " (dev)"; + } } return true; } @@ -2628,12 +2474,6 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) msg << "This warning is for project developers. Use -Wno-dev to suppress it."; } - else if (t == cmake::AUTHOR_ERROR) - { - msg << - "This error is for project developers. Use -Wno-error=dev to suppress " - "it."; - } // Add a terminating blank line. msg << "\n"; @@ -2657,8 +2497,7 @@ void displayMessage(cmake::MessageType t, std::ostringstream& msg) // Output the message. if(t == cmake::FATAL_ERROR || t == cmake::INTERNAL_ERROR - || t == cmake::DEPRECATION_ERROR - || t == cmake::AUTHOR_ERROR) + || t == cmake::DEPRECATION_ERROR) { cmSystemTools::SetErrorOccured(); cmSystemTools::Message(msg.str().c_str(), "Error"); @@ -2855,18 +2694,3 @@ void cmake::RunCheckForUnusedVariables() } #endif } - -void cmake::SetSuppressDevWarnings(bool b) -{ - // equivalent to -Wno-dev - if (b) - { - this->WarningLevels["dev"] = IGNORE_LEVEL; - } - // equivalent to -Wdev - else - { - this->WarningLevels["dev"] = std::max(this->WarningLevels["dev"], - WARNING_LEVEL); - } -} diff --git a/Source/cmake.h b/Source/cmake.h index 8ac8897..9d28cba 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -59,7 +59,6 @@ class cmake public: enum MessageType { AUTHOR_WARNING, - AUTHOR_ERROR, FATAL_ERROR, INTERNAL_ERROR, MESSAGE, @@ -69,12 +68,6 @@ class cmake DEPRECATION_WARNING }; - enum WarningLevel - { - IGNORE_LEVEL, - WARNING_LEVEL, - ERROR_LEVEL - }; /** \brief Describes the working modes of cmake */ enum WorkingMode @@ -278,7 +271,6 @@ class cmake void SetTrace(bool b) { this->Trace = b;} bool GetTraceExpand() { return this->TraceExpand;} void SetTraceExpand(bool b) { this->TraceExpand = b;} - void SetSuppressDevWarnings(bool b); bool GetWarnUninitialized() { return this->WarnUninitialized;} void SetWarnUninitialized(bool b) { this->WarnUninitialized = b;} bool GetWarnUnused() { return this->WarnUnused;} @@ -299,6 +291,12 @@ class cmake std::string const& GetCMakeEditCommand() const { return this->CMakeEditCommand; } + void SetSuppressDevWarnings(bool v) + { + this->SuppressDevWarnings = v; + this->DoSuppressDevWarnings = true; + } + /** Display a message to the user. */ void IssueMessage(cmake::MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace()); @@ -341,7 +339,8 @@ protected: cmGlobalGenerator *GlobalGenerator; cmCacheManager *CacheManager; - std::map<std::string, WarningLevel> WarningLevels; + bool SuppressDevWarnings; + bool DoSuppressDevWarnings; std::string GeneratorPlatform; std::string GeneratorToolset; @@ -417,15 +416,7 @@ private: {"-T <toolset-name>", "Specify toolset name if supported by generator."}, \ {"-A <platform-name>", "Specify platform name if supported by generator."}, \ {"-Wno-dev", "Suppress developer warnings."},\ - {"-Wdev", "Enable developer warnings."},\ - {"-Werror=dev", "Make developer warnings errors."},\ - {"-Wno-error=dev", "Make developer warnings not errors."},\ - {"-Wdeprecated", "Enable deprecated macro and function warnings."},\ - {"-Wno-deprecated", "Suppress deprecated macro and function warnings."},\ - {"-Werror=deprecated", "Make deprecated macro and function warnings " \ - "errors."},\ - {"-Wno-error=deprecated", "Make deprecated macro and function warnings " \ - "not errors."} + {"-Wdev", "Enable developer warnings."} #define FOR_EACH_C_FEATURE(F) \ F(c_function_prototypes) \ diff --git a/Source/cmake.version.manifest b/Source/cmake.version.manifest new file mode 100644 index 0000000..e7010c9 --- /dev/null +++ b/Source/cmake.version.manifest @@ -0,0 +1,18 @@ +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" + manifestVersion="1.0" + xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- Windows Vista --> + <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> + <!-- Windows 10 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> + </application> + </compatibility> +</assembly> diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index aa70aa0..f44c77d 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1355,6 +1355,35 @@ int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name) return -1; } +class cmVSLink +{ + int Type; + bool Verbose; + bool Incremental; + bool LinkGeneratesManifest; + std::vector<std::string> LinkCommand; + std::vector<std::string> UserManifests; + std::string LinkerManifestFile; + std::string ManifestFile; + std::string ManifestFileRC; + std::string ManifestFileRes; + std::string TargetFile; +public: + cmVSLink(int type, bool verbose) + : Type(type) + , Verbose(verbose) + , Incremental(false) + , LinkGeneratesManifest(true) + {} + bool Parse(std::vector<std::string>::const_iterator argBeg, + std::vector<std::string>::const_iterator argEnd); + int Link(); +private: + int LinkIncremental(); + int LinkNonIncremental(); + int RunMT(std::string const& out, bool notify); +}; + // For visual studio 2005 and newer manifest files need to be embedded into // exe and dll's. This code does that in such a way that incremental linking // still works. @@ -1364,11 +1393,7 @@ int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type) { return -1; } - bool verbose = false; - if(cmSystemTools::GetEnv("VERBOSE")) - { - verbose = true; - } + bool verbose = cmSystemTools::GetEnv("VERBOSE")? true:false; std::vector<std::string> expandedArgs; for(std::vector<std::string>::iterator i = args.begin(); i != args.end(); ++i) @@ -1389,79 +1414,19 @@ int cmcmd::VisualStudioLink(std::vector<std::string>& args, int type) expandedArgs.push_back(*i); } } - bool hasIncremental = false; - bool hasManifest = true; - for(std::vector<std::string>::iterator i = expandedArgs.begin(); - i != expandedArgs.end(); ++i) - { - if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL:YES") == 0) - { - hasIncremental = true; - } - if(cmSystemTools::Strucmp(i->c_str(), "/INCREMENTAL") == 0) - { - hasIncremental = true; - } - if(cmSystemTools::Strucmp(i->c_str(), "/MANIFEST:NO") == 0) - { - hasManifest = false; - } - } - if(hasIncremental && hasManifest) - { - if(verbose) - { - std::cout << "Visual Studio Incremental Link with embedded manifests\n"; - } - return cmcmd::VisualStudioLinkIncremental(expandedArgs, type, verbose); - } - if(verbose) - { - if(!hasIncremental) - { - std::cout << "Visual Studio Non-Incremental Link\n"; - } - else - { - std::cout << "Visual Studio Incremental Link without manifests\n"; - } - } - return cmcmd::VisualStudioLinkNonIncremental(expandedArgs, - type, hasManifest, verbose); -} -int cmcmd::ParseVisualStudioLinkCommand(std::vector<std::string>& args, - std::vector<std::string>& command, - std::string& targetName) -{ - std::vector<std::string>::iterator i = args.begin(); - i++; // skip -E - i++; // skip vs_link_dll or vs_link_exe - command.push_back(*i); - i++; // move past link command - for(; i != args.end(); ++i) - { - command.push_back(*i); - if(i->find("/Fe") == 0) - { - targetName = i->substr(3); - } - if(i->find("/out:") == 0) - { - targetName = i->substr(5); - } - } - if(targetName.empty() || command.empty()) + cmVSLink vsLink(type, verbose); + if (!vsLink.Parse(expandedArgs.begin()+2, expandedArgs.end())) { return -1; } - return 0; + return vsLink.Link(); } -bool cmcmd::RunCommand(const char* comment, +static bool RunCommand(const char* comment, std::vector<std::string>& command, bool verbose, - int* retCodeOut) + int* retCodeOut = 0) { if(verbose) { @@ -1503,8 +1468,134 @@ bool cmcmd::RunCommand(const char* comment, return retCode == 0; } -int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args, - int type, bool verbose) +bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, + std::vector<std::string>::const_iterator argEnd) +{ + // Parse our own arguments. + std::string intDir; + std::vector<std::string>::const_iterator arg = argBeg; + while (arg != argEnd && cmHasLiteralPrefix(*arg, "-")) + { + if (*arg == "--") + { + ++arg; + break; + } + else if (*arg == "--manifests") + { + for (++arg; arg != argEnd && !cmHasLiteralPrefix(*arg, "-"); ++arg) + { + this->UserManifests.push_back(*arg); + } + } + else if (cmHasLiteralPrefix(*arg, "--intdir=")) + { + intDir = arg->substr(9); + ++arg; + } + else + { + std::cerr << "unknown argument '" << *arg << "'\n"; + return false; + } + } + if (intDir.empty()) + { + return false; + } + + // The rest of the arguments form the link command. + if (arg == argEnd) + { + return false; + } + this->LinkCommand.insert(this->LinkCommand.begin(), arg, argEnd); + + // Parse the link command to extract information we need. + for (; arg != argEnd; ++arg) + { + if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL:YES") == 0) + { + this->Incremental = true; + } + else if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0) + { + this->Incremental = true; + } + else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0) + { + this->LinkGeneratesManifest = false; + } + else if (cmHasLiteralPrefix(*arg, "/Fe")) + { + this->TargetFile = arg->substr(3); + } + else if (cmHasLiteralPrefix(*arg, "/out:")) + { + this->TargetFile = arg->substr(5); + } + } + + if (this->TargetFile.empty()) + { + return false; + } + + this->ManifestFile = intDir + "/embed.manifest"; + this->LinkerManifestFile = intDir + "/intermediate.manifest"; + + if (this->Incremental) + { + // We will compile a resource containing the manifest and + // pass it to the link command. + this->ManifestFileRC = intDir + "/manifest.rc"; + this->ManifestFileRes = intDir + "/manifest.res"; + this->LinkCommand.push_back(this->ManifestFileRes); + } + else if (this->UserManifests.empty()) + { + // Prior to support for user-specified manifests CMake placed the + // linker-generated manifest next to the binary (as if it were not to be + // embedded) when not linking incrementally. Preserve this behavior. + this->ManifestFile = this->TargetFile + ".manifest"; + this->LinkerManifestFile = this->ManifestFile; + } + + if (this->LinkGeneratesManifest) + { + this->LinkCommand.push_back("/MANIFEST"); + this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile); + } + + return true; +} + +int cmVSLink::Link() +{ + if (this->Incremental && + (this->LinkGeneratesManifest || !this->UserManifests.empty())) + { + if (this->Verbose) + { + std::cout << "Visual Studio Incremental Link with embedded manifests\n"; + } + return LinkIncremental(); + } + if (this->Verbose) + { + if (!this->Incremental) + { + std::cout << "Visual Studio Non-Incremental Link\n"; + } + else + { + std::cout << "Visual Studio Incremental Link without manifests\n"; + } + } + return LinkNonIncremental(); +} + +int cmVSLink::LinkIncremental() { // This follows the steps listed here: // http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx @@ -1528,161 +1619,118 @@ int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args, // 7. Finally, the Linker does another incremental link, but since the // only thing that has changed is the *.res file that contains the // manifest it is a short link. - std::vector<std::string> linkCommand; - std::string targetName; - if(cmcmd::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1) - { - return -1; - } - std::string manifestArg = "/MANIFESTFILE:"; - std::vector<std::string> rcCommand; - rcCommand.push_back(cmSystemTools::FindProgram("rc.exe")); - std::vector<std::string> mtCommand; - mtCommand.push_back(cmSystemTools::FindProgram("mt.exe")); - std::string tempManifest; - tempManifest = targetName; - tempManifest += ".intermediate.manifest"; - std::string resourceInputFile = targetName; - resourceInputFile += ".resource.txt"; - if(verbose) + + // Create a resource file referencing the manifest. + std::string absManifestFile = + cmSystemTools::CollapseFullPath(this->ManifestFile); + if (this->Verbose) { - std::cout << "Create " << resourceInputFile << "\n"; + std::cout << "Create " << this->ManifestFileRC << "\n"; } - // Create input file for rc command - cmsys::ofstream fout(resourceInputFile.c_str()); - if(!fout) + { + cmsys::ofstream fout(this->ManifestFileRC.c_str()); + if (!fout) { return -1; } - std::string manifestFile = targetName; - manifestFile += ".embed.manifest"; - std::string fullPath= cmSystemTools::CollapseFullPath(manifestFile); - fout << type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID " - "*/ 24 /* RT_MANIFEST */ " << "\"" << fullPath << "\""; - fout.close(); - manifestArg += tempManifest; - // add the manifest arg to the linkCommand - linkCommand.push_back("/MANIFEST"); - linkCommand.push_back(manifestArg); - // if manifestFile is not yet created, create an - // empty one - if(!cmSystemTools::FileExists(manifestFile.c_str())) + fout << this->Type << " /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ " + "24 /* RT_MANIFEST */ \"" << absManifestFile << "\""; + } + + // If we have not previously generated a manifest file, + // generate an empty one so the resource compiler succeeds. + if (!cmSystemTools::FileExists(this->ManifestFile)) { - if(verbose) + if (this->Verbose) { - std::cout << "Create empty: " << manifestFile << "\n"; + std::cout << "Create empty: " << this->ManifestFile << "\n"; } - cmsys::ofstream foutTmp(manifestFile.c_str()); + cmsys::ofstream foutTmp(this->ManifestFile.c_str()); } - std::string resourceFile = manifestFile; - resourceFile += ".res"; - // add the resource file to the end of the link command - linkCommand.push_back(resourceFile); - std::string outputOpt = "/fo"; - outputOpt += resourceFile; - rcCommand.push_back(outputOpt); - rcCommand.push_back(resourceInputFile); - // Run rc command to create resource - if(!cmcmd::RunCommand("RC Pass 1", rcCommand, verbose)) - { - return -1; - } - // Now run the link command to link and create manifest - if(!cmcmd::RunCommand("LINK Pass 1", linkCommand, verbose)) + + // Compile the resource file. + std::vector<std::string> rcCommand; + rcCommand.push_back(cmSystemTools::FindProgram("rc.exe")); + rcCommand.push_back("/fo" + this->ManifestFileRes); + rcCommand.push_back(this->ManifestFileRC); + if (!RunCommand("RC Pass 1", rcCommand, this->Verbose)) { return -1; } - // create mt command - std::string outArg("/out:"); - outArg+= manifestFile; - mtCommand.push_back("/nologo"); - mtCommand.push_back(outArg); - mtCommand.push_back("/notify_update"); - mtCommand.push_back("/manifest"); - mtCommand.push_back(tempManifest); - // now run mt.exe to create the final manifest file - int mtRet =0; - if(!cmcmd::RunCommand("MT", mtCommand, verbose, &mtRet)) + + // Run the link command (possibly generates intermediate manifest). + if (!RunCommand("LINK Pass 1", this->LinkCommand, this->Verbose)) { return -1; } - // if mt returns 0, then the manifest was not changed and - // we do not need to do another link step - if(mtRet == 0) - { - return 0; - } - // check for magic mt return value if mt returns the magic number - // 1090650113 then it means that it updated the manifest file and we need - // to do the final link. If mt has any value other than 0 or 1090650113 - // then there was some problem with the command itself and there was an - // error so return the error code back out of cmake so make can report it. - // (when hosted on a posix system the value is 187) - if(mtRet != 1090650113 && mtRet != 187) + + // Run the manifest tool to create the final manifest. + int mtRet = this->RunMT("/out:" + this->ManifestFile, true); + + // If mt returns 1090650113 (or 187 on a posix host) then it updated the + // manifest file so we need to embed it again. Otherwise we are done. + if (mtRet != 1090650113 && mtRet != 187) { return mtRet; } - // update the resource file with the new manifest from the mt command. - if(!cmcmd::RunCommand("RC Pass 2", rcCommand, verbose)) + + // Compile the resource file again. + if (!RunCommand("RC Pass 2", rcCommand, this->Verbose)) { return -1; } - // Run the final incremental link that will put the new manifest resource - // into the file incrementally. - if(!cmcmd::RunCommand("FINAL LINK", linkCommand, verbose)) + + // Link incrementally again to use the updated resource. + if (!RunCommand("FINAL LINK", this->LinkCommand, this->Verbose)) { return -1; } return 0; } -int cmcmd::VisualStudioLinkNonIncremental(std::vector<std::string>& args, - int type, - bool hasManifest, - bool verbose) +int cmVSLink::LinkNonIncremental() { - std::vector<std::string> linkCommand; - std::string targetName; - if(cmcmd::ParseVisualStudioLinkCommand(args, linkCommand, targetName) == -1) - { - return -1; - } - // Run the link command as given - if (hasManifest) - { - linkCommand.push_back("/MANIFEST"); - } - if(!cmcmd::RunCommand("LINK", linkCommand, verbose)) + // Run the link command (possibly generates intermediate manifest). + if (!RunCommand("LINK", this->LinkCommand, this->Verbose)) { return -1; } - if(!hasManifest) + + // If we have no manifest files we are done. + if (!this->LinkGeneratesManifest && this->UserManifests.empty()) { return 0; } + + // Run the manifest tool to embed the final manifest in the binary. + std::string mtOut = + "/outputresource:" + this->TargetFile + (this->Type == 1? ";#1" : ";#2"); + return this->RunMT(mtOut, false); +} + +int cmVSLink::RunMT(std::string const& out, bool notify) +{ std::vector<std::string> mtCommand; mtCommand.push_back(cmSystemTools::FindProgram("mt.exe")); mtCommand.push_back("/nologo"); mtCommand.push_back("/manifest"); - std::string manifestFile = targetName; - manifestFile += ".manifest"; - mtCommand.push_back(manifestFile); - std::string outresource = "/outputresource:"; - outresource += targetName; - outresource += ";#"; - if(type == 1) + if (this->LinkGeneratesManifest) { - outresource += "1"; + mtCommand.push_back(this->LinkerManifestFile); } - else if(type == 2) + mtCommand.insert(mtCommand.end(), + this->UserManifests.begin(), this->UserManifests.end()); + mtCommand.push_back(out); + if (notify) { - outresource += "2"; + // Add an undocumented option that enables a special return + // code to notify us when the manifest is modified. + mtCommand.push_back("/notify_update"); } - mtCommand.push_back(outresource); - // Now use the mt tool to embed the manifest into the exe or dll - if(!cmcmd::RunCommand("MT", mtCommand, verbose)) + int mtRet = 0; + if (!RunCommand("MT", mtCommand, this->Verbose, &mtRet)) { return -1; } - return 0; + return mtRet; } diff --git a/Source/cmcmd.h b/Source/cmcmd.h index 2bfbae7..64b2406 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -35,20 +35,6 @@ protected: static int WindowsCEEnvironment(const char* version, const std::string& name); static int VisualStudioLink(std::vector<std::string>& args, int type); - static int VisualStudioLinkIncremental(std::vector<std::string>& args, - int type, - bool verbose); - static int VisualStudioLinkNonIncremental(std::vector<std::string>& args, - int type, - bool hasManifest, - bool verbose); - static int ParseVisualStudioLinkCommand(std::vector<std::string>& args, - std::vector<std::string>& command, - std::string& targetName); - static bool RunCommand(const char* comment, - std::vector<std::string>& command, - bool verbose, - int* retCodeOut = 0); }; #endif diff --git a/Source/ctest.cxx b/Source/ctest.cxx index afcbd61..7fa6aed 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -46,6 +46,10 @@ static const char * cmDocumentationOptions[][2] = {"--debug", "Displaying more verbose internals of CTest."}, {"--output-on-failure", "Output anything outputted by the test program " "if the test should fail."}, + {"--test-output-size-passed <size>", "Limit the output for passed tests " + "to <size> bytes"}, + {"--test-output-size-failed <size>", "Limit the output for failed tests " + "to <size> bytes"}, {"-F", "Enable failover."}, {"-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the " "given number of jobs."}, diff --git a/Source/kwsys/CTestCustom.cmake.in b/Source/kwsys/CTestCustom.cmake.in index d6f802e..760221b 100644 --- a/Source/kwsys/CTestCustom.cmake.in +++ b/Source/kwsys/CTestCustom.cmake.in @@ -9,7 +9,6 @@ # resulting memory leaks are not logged by valgrind anyway. Therefore, we # don't have to exclude it. -set(CTEST_CUSTOM_MEMCHECK_IGNORE - ${CTEST_CUSTOM_MEMCHECK_IGNORE} +list(APPEND CTEST_CUSTOM_MEMCHECK_IGNORE kwsys.testProcess-10 ) diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 97a1df8..262af27 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -408,6 +408,7 @@ class SystemToolsPathCaseMap: // adds the elements of the env variable path to the arg passed in void SystemTools::GetPath(std::vector<std::string>& path, const char* env) { + size_t const old_size = path.size(); #if defined(_WIN32) && !defined(__CYGWIN__) const char pathSep = ';'; #else @@ -445,7 +446,7 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env) done = true; } } - for(std::vector<std::string>::iterator i = path.begin(); + for(std::vector<std::string>::iterator i = path.begin() + old_size; i != path.end(); ++i) { SystemTools::ConvertToUnixSlashes(*i); @@ -2365,95 +2366,102 @@ bool SystemTools::CopyFileAlways(const std::string& source, const std::string& d } mode_t perm = 0; bool perms = SystemTools::GetPermissions(source, perm); - - const int bufferSize = 4096; - char buffer[bufferSize]; - - // If destination is a directory, try to create a file with the same - // name as the source in that directory. - std::string real_destination = destination; - std::string destination_dir; - if(SystemTools::FileExists(destination) && - SystemTools::FileIsDirectory(destination)) + + if(SystemTools::FileIsDirectory(source)) { - destination_dir = real_destination; - SystemTools::ConvertToUnixSlashes(real_destination); - real_destination += '/'; - std::string source_name = source; - real_destination += SystemTools::GetFilenameName(source_name); + SystemTools::MakeDirectory(destination); } else { - destination_dir = SystemTools::GetFilenamePath(destination); - } + const int bufferSize = 4096; + char buffer[bufferSize]; - // Create destination directory + // If destination is a directory, try to create a file with the same + // name as the source in that directory. - SystemTools::MakeDirectory(destination_dir); + std::string destination_dir; + if(SystemTools::FileExists(destination) && + SystemTools::FileIsDirectory(destination)) + { + destination_dir = real_destination; + SystemTools::ConvertToUnixSlashes(real_destination); + real_destination += '/'; + std::string source_name = source; + real_destination += SystemTools::GetFilenameName(source_name); + } + else + { + destination_dir = SystemTools::GetFilenamePath(destination); + } + + // Create destination directory - // Open files + SystemTools::MakeDirectory(destination_dir); + + // Open files #if defined(_WIN32) - kwsys::ifstream fin(Encoding::ToNarrow( - SystemTools::ConvertToWindowsExtendedPath(source)).c_str(), - std::ios::in | std::ios::binary); + kwsys::ifstream fin(Encoding::ToNarrow( + SystemTools::ConvertToWindowsExtendedPath(source)).c_str(), + std::ios::in | std::ios::binary); #else - kwsys::ifstream fin(source.c_str(), - std::ios::in | std::ios::binary); + kwsys::ifstream fin(source.c_str(), + std::ios::in | std::ios::binary); #endif - if(!fin) - { - return false; - } + if(!fin) + { + return false; + } - // try and remove the destination file so that read only destination files - // can be written to. - // If the remove fails continue so that files in read only directories - // that do not allow file removal can be modified. - SystemTools::RemoveFile(real_destination); + // try and remove the destination file so that read only destination files + // can be written to. + // If the remove fails continue so that files in read only directories + // that do not allow file removal can be modified. + SystemTools::RemoveFile(real_destination); #if defined(_WIN32) - kwsys::ofstream fout(Encoding::ToNarrow( - SystemTools::ConvertToWindowsExtendedPath(real_destination)).c_str(), + kwsys::ofstream fout(Encoding::ToNarrow( + SystemTools::ConvertToWindowsExtendedPath(real_destination)).c_str(), std::ios::out | std::ios::trunc | std::ios::binary); #else - kwsys::ofstream fout(real_destination.c_str(), + kwsys::ofstream fout(real_destination.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); #endif - if(!fout) - { - return false; - } - - // This copy loop is very sensitive on certain platforms with - // slightly broken stream libraries (like HPUX). Normally, it is - // incorrect to not check the error condition on the fin.read() - // before using the data, but the fin.gcount() will be zero if an - // error occurred. Therefore, the loop should be safe everywhere. - while(fin) - { - fin.read(buffer, bufferSize); - if(fin.gcount()) + if(!fout) { - fout.write(buffer, fin.gcount()); + return false; } - else + + // This copy loop is very sensitive on certain platforms with + // slightly broken stream libraries (like HPUX). Normally, it is + // incorrect to not check the error condition on the fin.read() + // before using the data, but the fin.gcount() will be zero if an + // error occurred. Therefore, the loop should be safe everywhere. + while(fin) { - break; + fin.read(buffer, bufferSize); + if(fin.gcount()) + { + fout.write(buffer, fin.gcount()); + } + else + { + break; + } } - } - // Make sure the operating system has finished writing the file - // before closing it. This will ensure the file is finished before - // the check below. - fout.flush(); + // Make sure the operating system has finished writing the file + // before closing it. This will ensure the file is finished before + // the check below. + fout.flush(); - fin.close(); - fout.close(); + fin.close(); + fout.close(); - if(!fout) - { - return false; + if(!fout) + { + return false; + } } if ( perms ) { @@ -4879,11 +4887,8 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() OSVERSIONINFOEXA osvi; BOOL bOsVersionInfoEx; - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - // If that fails, try using the OSVERSIONINFO structure. - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); + ZeroMemory(&osvi, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # pragma warning (push) @@ -4893,14 +4898,10 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() # pragma warning (disable:4996) # endif #endif - bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi); + bOsVersionInfoEx = GetVersionExA((OSVERSIONINFOA *)&osvi); if (!bOsVersionInfoEx) { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx((OSVERSIONINFO *)&osvi)) - { - return 0; - } + return 0; } #ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx # pragma warning (pop) @@ -4913,10 +4914,56 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() case VER_PLATFORM_WIN32_NT: // Test for the specific product family. + if (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + { + res += "Microsoft Windows 10"; + } + else + { + res += "Microsoft Windows Server 2016 family"; + } + } + + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + { + res += "Microsoft Windows 8.1"; + } + else + { + res += "Microsoft Windows Server 2012 R2 family"; + } + } + + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + { + res += "Microsoft Windows 8"; + } + else + { + res += "Microsoft Windows Server 2012 family"; + } + } + + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) + { + if (osvi.wProductType == VER_NT_WORKSTATION) + { + res += "Microsoft Windows 7"; + } + else + { + res += "Microsoft Windows Server 2008 R2 family"; + } + } if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) { -#if (_MSC_VER >= 1300) if (osvi.wProductType == VER_NT_WORKSTATION) { res += "Microsoft Windows Vista"; @@ -4925,9 +4972,6 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() { res += "Microsoft Windows Server 2008 family"; } -#else - res += "Microsoft Windows Vista or Windows Server 2008"; -#endif } if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) @@ -4956,7 +5000,6 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() { // Test for the workstation type. -#if (_MSC_VER >= 1300) if (osvi.wProductType == VER_NT_WORKSTATION) { if (osvi.dwMajorVersion == 4) @@ -5028,7 +5071,6 @@ std::string SystemTools::GetOperatingSystemNameAndVersion() } } } -#endif // Visual Studio 7 and up } // Test for specific product on Windows NT 4.0 SP5 and earlier diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index e14d2fc..a0f904f 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -28,6 +28,7 @@ #include <testSystemTools.h> #include <iostream> +#include <sstream> #include <string.h> /* strcmp */ #if defined(_WIN32) && !defined(__CYGWIN__) # include <io.h> /* _umask (MSVC) / umask (Borland) */ @@ -790,6 +791,66 @@ static bool CheckCollapsePath() return res; } +static std::string StringVectorToString(const std::vector<std::string>& vec) +{ + std::stringstream ss; + ss << "vector("; + for (std::vector<std::string>::const_iterator i = vec.begin(); + i != vec.end(); ++i) + { + if (i != vec.begin()) + { + ss << ", "; + } + ss << *i; + } + ss << ")"; + return ss.str(); +} + +static bool CheckGetPath() +{ + const char* envName = "S"; +#ifdef _WIN32 + const char* envValue = "C:\\Somewhere\\something;D:\\Temp"; +#else + const char* envValue = "/Somewhere/something:/tmp"; +#endif + const char* registryPath = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MyApp; MyKey]"; + + std::vector<std::string> originalPathes; + originalPathes.push_back(registryPath); + + std::vector<std::string> expectedPathes; + expectedPathes.push_back(registryPath); +#ifdef _WIN32 + expectedPathes.push_back("C:/Somewhere/something"); + expectedPathes.push_back("D:/Temp"); +#else + expectedPathes.push_back("/Somewhere/something"); + expectedPathes.push_back("/tmp"); +#endif + + bool res = true; + res &= CheckPutEnv(std::string(envName) + "=" + envValue, envName, envValue); + + std::vector<std::string> pathes = originalPathes; + kwsys::SystemTools::GetPath(pathes, envName); + + if (pathes != expectedPathes) + { + std::cerr << + "GetPath(" << StringVectorToString(originalPathes) << + ", " << envName << ") yielded " << StringVectorToString(pathes) << + " instead of " << StringVectorToString(expectedPathes) << + std::endl; + res = false; + } + + res &= CheckUnPutEnv(envName, envName); + return res; +} + //---------------------------------------------------------------------------- int testSystemTools(int, char*[]) { @@ -825,5 +886,7 @@ int testSystemTools(int, char*[]) res &= CheckCollapsePath(); + res &= CheckGetPath(); + return res ? 0 : 1; } |