From 90e81e6b5ae0b77312c61ccfa051d3a0b8a713ba Mon Sep 17 00:00:00 2001 From: Philippe Renon Date: Sun, 15 Nov 2015 16:45:13 +0100 Subject: [PATCH] LP-2 install Qt using a silent install script tested on windows and linux 64. --- make/tool_install/qt-install.qs | 253 ++++++++++++++++++++++++++++++++ make/tools.mk | 48 ++---- 2 files changed, 265 insertions(+), 36 deletions(-) create mode 100644 make/tool_install/qt-install.qs diff --git a/make/tool_install/qt-install.qs b/make/tool_install/qt-install.qs new file mode 100644 index 000000000..7987ee533 --- /dev/null +++ b/make/tool_install/qt-install.qs @@ -0,0 +1,253 @@ +/* +silent installer script + +known not work with Qt 5.5.1 and QtIFW 2.0.2 + +known issues: +- silent but not headless (QtIFW 2.0.3 should support installer.setSilent(true)) +- cannot disable forced components (QtCreator, ...) + - cannot disable virtual components (doc, examples, ...) + - cannot disable shortcuts creation + - if user presses the 'Show Details' button then the installer does not end automatically +*/ +function Controller() +{ + console.log("*** Silent Installer ***"); + console.log("Installing on " + installer.value("os")); + //installer.setSilent(true); + + var qtInstallTargetDir = installer.environmentVariable("QT_INSTALL_TARGET_DIR"); + if (qtInstallTargetDir == "") { + qtInstallTargetDir = installer.environmentVariable("PWD") + "/tools/qt-5.5.1"; + console.log("Environment variable QT_INSTALL_TARGET_DIR not set, using default " + qtInstallTargetDir); + } + installer.setValue("TargetDir", qtInstallTargetDir); + console.log("Installing to " + installer.value("TargetDir")); + + installer.autoRejectMessageBoxes(); + installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes); + installer.setMessageBoxAutomaticAnswer("stopProcessesForUpdates", QMessageBox.Ignore); + + // pages that are not visible are actually removed from the wizard + // some pages must not be removed otherwise the installer starts to mishbehave + installer.setDefaultPageVisible(QInstaller.Welcome, false); + installer.setDefaultPageVisible(QInstaller.Credentials, false); // QInstaller.Credentials is 0... so this is a NOP! + //installer.setDefaultPageVisible(QInstaller.Introduction, false); // Fails to skip Credentials if Introduction is removed? + installer.setDefaultPageVisible(QInstaller.TargetDirectory, false); + //installer.setDefaultPageVisible(QInstaller.ComponentSelection, false); + //installer.setDefaultPageVisible(QInstaller.LicenseAgreementCheck, false); + //installer.setDefaultPageVisible(QInstaller.StartMenuSelection, false); + installer.setDefaultPageVisible(QInstaller.ReadyForInstallation, false); + //installer.setDefaultPageVisible(QInstaller.PerformInstallation, false); + installer.setDefaultPageVisible(QInstaller.FinishedPage, false); + + installer.componentAdded.connect(onComponentAdded); + installer.aboutCalculateComponentsToInstall.connect(onAboutCalculateComponentsToInstall); + installer.finishedCalculateComponentsToInstall.connect(onFinishedCalculateComponentsToInstall); +} + +// installer callbacks + +onComponentAdded = function(component) +{ + console.log("Component added: " + component.name); + dumpComponents(); +} + +onAboutCalculateComponentsToInstall = function() +{ + console.log("onAboutCalculateComponentsToInstall"); + //dumpComponents(); +} + +onFinishedCalculateComponentsToInstall = function() +{ + console.log("onFinishedCalculateComponentsToInstall"); + //dumpComponents(); +} + +// page callbacks +// used to setup wizard pages and move the wizard forward + +Controller.prototype.WelcomePageCallback = function() +{ + logCallback(); + + gui.clickButton(buttons.NextButton); +} + +Controller.prototype.CredentialsPageCallback = function() +{ + logCallback(); + + gui.clickButton(buttons.NextButton); +} + +Controller.prototype.IntroductionPageCallback = function() +{ + logCallback(); + + gui.clickButton(buttons.NextButton); +} + +Controller.prototype.ComponentSelectionPageCallback = function() +{ + logCallback(); + + var page = gui.currentPageWidget(); + page.deselectAll() + if (installer.value("os") == "win") { + selectComponent(page, "qt.55.win32_mingw492"); + selectComponent(page, "qt.tools.win32_mingw492"); + } + else if (installer.value("os") == "x11") { + selectComponent(page, "qt.55.gcc"); + selectComponent(page, "qt.55.gcc_64"); + } + else if (installer.value("os") == "mac") { + selectComponent(page, "qt.55.clang_64"); + } + selectComponent(page, "qt.55.qtquickcontrols"); + selectComponent(page, "qt.55.qtscript"); + + //installer.componentByName("qt.tools.qtcreator").setValue("ForcedInstallation", "false"); + + gui.clickButton(buttons.NextButton); +} + + +function selectComponent(page, name) +{ + component = installer.componentByName(name); + if (component) { + console.log("component " + name + " : " + component); + page.selectComponent(name); + } + else { + console.log("Failed to find component " + name + "!"); + } +} + +Controller.prototype.LicenseAgreementPageCallback = function() +{ + logCallback(); + + setChecked("AcceptLicenseRadioButton", true); + + gui.clickButton(buttons.NextButton); +} + +Controller.prototype.StartMenuDirectoryPageCallback = function() +{ + logCallback(); + + gui.clickButton(buttons.NextButton); +} + +Controller.prototype.PerformInstallationPageCallback = function() +{ + logCallback(); + + // show details and hide button + click("DetailsButton"); + setVisible("DetailsButton", false); + + // showing details will disable automated page switch, so re-enable it + installer.setAutomatedPageSwitchEnabled(true); +} + +Controller.prototype.FinishedPageCallback = function() +{ + logCallback(); + + setChecked("launchQtCreatorCheckBox", false); + + gui.clickButton(buttons.FinishButton); +} + +// utilities + +function logCallback() +{ + var page = gui.currentPageWidget(); + console.log(">>> " + page.objectName + "Callback"); +} + +function dumpComponents() +{ + dumpComponentsArray(installer.components()); +} + +function dumpComponentsArray(components) +{ + var arrayLength = components.length; + for (var i = 0; i < arrayLength; i++) { + dumpComponent(components[i]); + } +} + +function dumpComponent(component) +{ + console.log(component.name + " (" + component.displayName + ")"); + console.log(" Virtual: " + component.value("Virtual", "false")); + console.log(" ForcedInstallation: " + component.value("ForcedInstallation", "false")); + console.log(" Default: " + component.default); + console.log(" Enabled: " + component.enabled); +} + +// UI utilities + +function click(name) +{ + var page = gui.currentPageWidget(); + var button = gui.findChild(page, name); + if (button) { + console.log("button " + name + " : " + button); + button.click(); + } + else { + console.log("Failed to find button " + name + "!"); + } +} + +function setVisible(name, visible) +{ + var page = gui.currentPageWidget(); + var button = gui.findChild(page, name); + if (button) { + console.log("button " + name + " : " + button); + button.visible = visible; + console.log("button " + name + " visible : " + button.visible); + } + else { + console.log("Failed to find button " + name + "!"); + } +} + +function setEnabled(name, enabled) +{ + var page = gui.currentPageWidget(); + var button = gui.findChild(page, name); + if (button) { + console.log("button " + name + " : " + button); + button.enabled = enabled; + console.log("button " + name + " enabled : " + button.enabled); + } + else { + console.log("Failed to find button " + name + "!"); + } +} + +function setChecked(name, checked) +{ + var page = gui.currentPageWidget(); + var button = gui.findChild(page, name); + if (button) { + console.log("button " + name + " : " + button); + button.checked = checked; + console.log("button " + name + " checked : " + button.checked); + } + else { + console.log("Failed to find button " + name + "!"); + } +} diff --git a/make/tools.mk b/make/tools.mk index 7a4a212a0..2e515fa26 100644 --- a/make/tools.mk +++ b/make/tools.mk @@ -397,43 +397,29 @@ endef ############################## # -# Windows QT install template +# Qt install template # $(1) = tool install directory # $(2) = tool distribution URL # $(3) = tool distribution .md5 URL # $(4) = tool distribution file -# $(5) = QT architecture +# $(5) = Qt architecture # $(6) = optional extra build recipes template # $(7) = optional extra clean recipes template # ############################## -# notes: -# - missing installer --dump-binary-data option : https://bugreports.qt.io/browse/QTIFW-734 -# - devtool can not run QtPatch operation : https://bugreports.qt.io/browse/QTIFW-792 -# developper tips: -# - install Qt manually and look at the install log for needed operations (install log is in root of install) -# - use devtool.exe --dump to check package names and install scripts -############################## -define WIN_QT_INSTALL_TEMPLATE +define QT_INSTALL_TEMPLATE .PHONY: $(addprefix qt_sdk_, install clean distclean) qt_sdk_install: qt_sdk_clean | $(DL_DIR) $(TOOLS_DIR) $(call DOWNLOAD_TEMPLATE,$(2),$(4),"$(3)") -# Extract packages under tool directory - @$(ECHO) $(MSG_EXTRACTING) $$(call toprel, $(DL_DIR)/$(4)) to $$(call toprel, $(1)) - $(V1) $(MKDIR) -p $$(call toprel, $(dir $(1))) - $(V1) devtool --operation DO,Extract,"installer://qt.55.win32_mingw492/5.5.1-0qt5_essentials.7z","$(1)" "$(DL_DIR)/$(4)" > NUL - $(V1) devtool --operation DO,Extract,"installer://qt.55.win32_mingw492/5.5.1-0i686-4.9.2-release-posix-dwarf-rt_v3-rev1-runtime.7z","$(1)" "$(DL_DIR)/$(4)" > NUL - $(V1) devtool --operation DO,Extract,"installer://qt.55.win32_mingw492/5.5.1-0icu-win-MinGW4.9.2-Windows7-x86.7z","$(1)" "$(DL_DIR)/$(4)" > NUL - $(V1) devtool --operation DO,Extract,"installer://qt.55.win32_mingw492/5.5.1-0qt5_addons.7z","$(1)" "$(DL_DIR)/$(4)" > NUL - $(V1) devtool --operation DO,Extract,"installer://qt.55.qtquickcontrols.win32_mingw492/5.5.1-0qt5_qtquickcontrols.7z","$(1)" "$(DL_DIR)/$(4)" > NUL - $(V1) devtool --operation DO,Extract,"installer://qt.tools.win32_mingw492/4.9.2-0i686-4.9.2-release-posix-dwarf-rt_v3-rev1.7z","$(1)" "$(DL_DIR)/$(4)" > NUL -# Run patcher - @$(ECHO) "Executing QtPatch in" $$(call toprel, $(QT_SDK_PREFIX)) - #$(V1) devtool --operation DO,QtPatch,"windows","$(QT_SDK_PREFIX)","qt5" "$(DL_DIR)/$(4)" - $(V1) devtool --operation DO,LineReplace,"$(QT_SDK_PREFIX)/mkspecs/qconfig.pri","QT_EDITION =","QT_EDITION = OpenSource" "$(DL_DIR)/$(4)" +# Silently install Qt under tools directory + @$(ECHO) $(MSG_EXTRACTING) $(4) to $$(call toprel, $(1)) + $(V1) ( export QT_INSTALL_TARGET_DIR=$(1) && \ + chmod +x $(DL_DIR)/$(4) && \ + $(DL_DIR)/$(4) --script $(ROOT_DIR)/make/tool_install/qt-install.qs ; \ + ) # Execute post build templates $(6) @@ -623,27 +609,17 @@ ifeq ($(UNAME), Windows) QT_SDK_PREFIX := $(QT_SDK_DIR)/5.5/$(QT_SDK_ARCH) -# This additional configuration step should not be necessary -# but it is needed as a workaround to https://bugreports.qt-project.org/browse/QTBUG-33254 -define QT_SDK_CONFIGURE_TEMPLATE - @$(ECHO) $(MSG_CONFIGURING) $(call toprel, $(QT_SDK_DIR)) - $(V1) $(ECHO) $(QUOTE)[Paths]$(QUOTE) > $(QT_SDK_PREFIX)/bin/qt.conf - $(V1) $(ECHO) $(QUOTE)Prefix = $(QT_SDK_PREFIX)$(QUOTE) >> $(QT_SDK_PREFIX)/bin/qt.conf -endef - - $(eval $(call WIN_QT_INSTALL_TEMPLATE,$(QT_SDK_DIR),$(QT_SDK_URL),$(QT_SDK_MD5_URL),$(notdir $(QT_SDK_URL)),$(QT_SDK_ARCH),$(QT_SDK_CONFIGURE_TEMPLATE))) + $(eval $(call QT_INSTALL_TEMPLATE,$(QT_SDK_DIR),$(QT_SDK_URL),$(QT_SDK_MD5_URL),$(notdir $(QT_SDK_URL)),$(QT_SDK_ARCH))) else ifeq ($(UNAME), Linux) QT_SDK_PREFIX := "$(QT_SDK_DIR)/5.5/$(QT_SDK_ARCH)" -QT_BUILD_DIR := $(BUILD_DIR)/QT_BUILD - $(eval $(call LINUX_QT_INSTALL_TEMPLATE,$(QT_BUILD_DIR),$(QT_SDK_DIR),$(QT_SDK_URL),$(QT_SDK_MD5_URL),$(notdir $(QT_SDK_URL)),$(QT_SDK_ARCH))) + $(eval $(call QT_INSTALL_TEMPLATE,$(QT_SDK_DIR),$(QT_SDK_URL),$(QT_SDK_MD5_URL),$(notdir $(QT_SDK_URL)),$(QT_SDK_ARCH))) else ifeq ($(UNAME), Darwin) QT_SDK_PREFIX := "$(QT_SDK_DIR)/5.5/$(QT_SDK_ARCH)" -QT_BUILD_DIR := $(BUILD_DIR)/QT_BUILD - $(eval $(call MAC_QT_INSTALL_TEMPLATE,$(QT_BUILD_DIR),$(QT_SDK_DIR),$(QT_SDK_URL),$(QT_SDK_MD5_URL),$(notdir $(QT_SDK_URL)),$(QT_SDK_ARCH))) + $(eval $(call QT_INSTALL_TEMPLATE,$(QT_SDK_DIR),$(QT_SDK_URL),$(QT_SDK_MD5_URL),$(notdir $(QT_SDK_URL)),$(QT_SDK_ARCH))) else