# File src/gnuwin32/installer/WiXins.R # # Part of the R package, https://www.R-project.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # A copy of the GNU General Public License is available at # https://www.R-project.org/Licenses/ ## Collection of notes about WiX usage ## for x64 add InstallerVersion="200" Platforms="x64" ## see http://blogs.msdn.com/astebner/archive/2007/08/09/4317654.aspx ## Or something like ##<Condition Message='This application is for x64 Windows.'> ## VersionNT64 ##</Condition> ## Actually seem to need both, and it is 'Platform' in WiX 3.0 ## ALLUSERS = 1 for per-machine, blank for default. ## http://wix.mindcapers.com/wiki/Allusers_Install_vs._Per_User_Install ## For non-elevation see ## http://blogs.msdn.com/astebner/archive/2007/11/18/6385121.aspx ## Also ## http://msdn.microsoft.com/en-us/library/aa367559%28VS.85%29.aspx ## The standard folder names are listed at ## http://msdn.microsoft.com/en-us/library/aa372057.aspx ## http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/64-bit-and-32-bit-Registry-Keys-in-same-MSI-td4439679.html .make_R.wxs <- function(RW, srcdir, personal = "0") { have64bit <- file_test("-d", file.path(srcdir, "bin", "x64")) have32bit <- file_test("-d", file.path(srcdir, "bin", "i386")) personal <- personal == "1" ## need DOS-style paths srcdir0 <- srcdir srcdir <- gsub("/", "\\", srcdir, fixed = TRUE) Rver <- readLines("../../../VERSION")[1L] Rver <- sub("Under .*$", "Pre-release", Rver) SVN <- sub("Revision: ", "", readLines("../../../SVN-REVISION"))[1L] Rver0 <- paste(sub(" .*$", "", Rver), SVN, sep = ".") uuids <- readLines("uuids") nc <- 1 guuids <- function() {x <- uuids[nc]; nc <<- nc + 1L; x} con <- file("R.wxs", "w") cat(file = con, sep = "\n", '<?xml version="1.0" encoding="windows-1252"?>', '<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">', ' <Product Manufacturer="R Core Team" ', ' Id="*"', ' Language="1033"', sprintf(' Name="R%s %s (via msi)"', ifelse(have64bit, " x64", ""), Rver), sprintf(' Version="%s"', Rver0), ' UpgradeCode="309E663C-CA7A-40B9-8822-5D466F1E2AF9">', ' <Package Id="*" ', sprintf(' Keywords="R %s Installer"', Rver), sprintf(' Description="R %s Installer"', Rver), ' Comments="R Language and Environment"', ' Manufacturer="R Core Team"', if (have64bit) ' InstallerVersion="200"' else ' InstallerVersion="100"', if (have64bit) ' Platform="x64"', ' Languages="1033"', ' Compressed="yes"', if (personal) 'InstallPrivileges="limited"', ' SummaryCodepage="1252" />', ' <Media Id=\'1\' Cabinet=\'Sample.cab\' EmbedCab=\'yes\' DiskPrompt="CD-ROM #1" />', ' <Property Id=\'DiskPrompt\' Value="R Installation [1]" />', if(personal)' <Property Id="ALLUSERS"></Property>' else ' <Property Id="ALLUSERS">1</Property>', sprintf(' <Property Id="RVersion">%s</Property>', Rver), ' <Icon Id="icon.ico" SourceFile="..\\front-ends\\R.ico"/>', ' <Property Id="ARPPRODUCTICON" Value="icon.ico" />', '') if (have64bit) { cat(file = con, sep = "\n", "", "<Condition Message='This application is for x64 Windows.'>", " VersionNT64", "</Condition>") } name0 <- paste('Name="', srcdir, '" />', sep = '') ff <- readLines('files.wxs', warn = FALSE) ff <- grep("^ ", ff, value = TRUE) rx1 <- ' *<Component Id="([^"]*)".*' rx2 <- ' *<File Id=\"([^\"]*).* (src|Source)=\"([^\"]*)\".*' rx3 <- paste(".*\\", srcdir, "\\", sep = "") comps <- ids <- nm <- character() rgui <- rgui64 <- rhelp <- 'unknown' comp <- id <- 'unknown' rx3 <- paste(".*", srcdir0, "/", sep="") rx3 <- ".*SourceDir/" for(i in seq_along(ff)) { f <- ff[i] if(grepl(rx1, f)) id <- sub(rx1, "\\1", f) if(grepl(rx2, f)) { fn <- sub(rx2, "\\1", f) src <- sub(rx3, "", sub(rx2, "\\3", f), fixed = TRUE) src <- gsub("\\", "/", src, fixed = TRUE) if(grepl("bin/i386/Rgui.exe$", src)) rgui <- fn if(grepl("bin/x64/Rgui.exe$", src)) rgui64 <- fn if(grepl("doc/html/index.html$", src)) rhelp <- fn ids <- c(ids, id) nm <- c(nm, src) g <- sub(rx3, "", src) component <- if (have64bit && grepl("^Tcl/(bin|lib)64", g)) "x64" else if (have64bit && (grepl("^Tcl/bin", g) || grepl("^Tcl/lib/(dde1.3|reg1.2|Tktable)", g))) "i386" else if (have64bit && grepl("/i386/", g)) "i386" else if (have64bit && grepl("/x64/", g)) "x64" else "main" comps <- c(comps, component) } if(grepl("PUT-GUID-HERE", f)) f <- sub("PUT-GUID-HERE", guuids(), f, fixed = TRUE) f <- sub("SourceDir", srcdir, f, fixed = TRUE) f <- sub("TARGETDIR", "INSTALLDIR", f, fixed = TRUE) f <- sub(name0, "/>", f, fixed = TRUE) cat(" ", f, "\n", file=con, sep="") } if (rgui == "unknown") rgui <- rgui64 cat(file = con, sep = "\n", '', ' <Directory Id=\'TARGETDIR\' Name=\'SourceDir\'>', '', ## empty components to work around bug in Windows Installer ## offering to install components with no features from the network sprintf(' <Component Id="dummyman" Guid="%s"></Component>', guuids()), sprintf(' <Component Id="dummytcl" Guid="%s"></Component>', guuids()), sprintf(' <Component Id="dummystart" Guid="%s"></Component>', guuids()), '', if (have64bit) ' <Directory Id=\'ProgramFiles64Folder\' Name=\'PFiles\'>' else ' <Directory Id=\'ProgramFilesFolder\' Name=\'PFiles\'>', " <Directory Id='Rdir' Name='R'>", sprintf(" <Directory Id='INSTALLDIR' Name='%s'>", srcdir), " </Directory>", " </Directory>", " </Directory>") cat(file = con, sep="\n", ' <Directory Id="PersonalFolder" Name="Personal">', ' <Directory Id="STARTDIR" Name="R"></Directory>', ' </Directory>') cat(file = con, sep="\n", ' <Directory Id="StartMenuFolder" Name="SMenu">', ' <Directory Id="ProgramMenuFolder" Name="Programs">', ' <Directory Id="RMENU" Name="R">') if (have32bit) cat(file = con, sep="\n", sprintf(' <Component Id="shortcut0" Guid="%s">', guuids()), ' <Shortcut Id="RguiStartMenuShortcut" Directory="RMENU"', sprintf(' Name="R i386 %s" Target="[!%s]" ', Rver, rgui), ' WorkingDirectory="STARTDIR" />', ## stop validation errors ' <RegistryValue Root="HKCU" Key="Software\\R-core\\R" Name="installed" Type="integer" Value="1" KeyPath="yes"/>', ' </Component>') if (have64bit) cat(file = con, sep="\n", sprintf(' <Component Id="shortcut64" Guid="%s">', guuids()), ' <Shortcut Id="Rgui64StartMenuShortcut" Directory="RMENU"', sprintf(' Name="R x64 %s" Target="[!%s]" ', Rver, rgui64), ' WorkingDirectory="STARTDIR" />', ## stop validation errors ' <RegistryValue Root="HKCU" Key="Software\\R-core\\R" Name="installed" Type="integer" Value="1" KeyPath="yes"/>', ' </Component>') cat(file = con, sep="\n", sprintf(' <Component Id="shortcut1" Guid="%s">', guuids()), ' <Shortcut Id="HelpStartMenuShortcut" Directory="RMENU"', sprintf(' Name="R %s Help" Target="[!%s]"', Rver, rhelp), ' WorkingDirectory="STARTDIR" />', ## The next two stop validation errors ' <RemoveFolder Id="RMENU" On="uninstall"/>', ' <RegistryValue Root="HKCU" Key="Software\\R-core\\R" Name="installed" Type="integer" Value="1" KeyPath="yes"/>', ' </Component>', ' </Directory>', ' </Directory>', ' </Directory>', ' <Directory Id="DesktopFolder" Name="Desktop">') if (have32bit) cat(file = con, sep="\n", sprintf(' <Component Id="desktopshortcut0" DiskId="1" Guid="%s">', guuids()), sprintf(' <Shortcut Id="RguiDesktopShortcut" Directory="DesktopFolder" Name="R i386 %s"', Rver), sprintf(' WorkingDirectory="STARTDIR" Target="[!%s]" />', rgui), ' <RegistryValue Root="HKCU" Key="Software\\R-core\\R" Name="installed" Type="integer" Value="1" KeyPath="yes"/>', ' </Component>') if (have64bit) cat(file = con, sep="\n", sprintf(' <Component Id="desktopshortcut64" DiskId="1" Guid="%s">', guuids()), sprintf(' <Shortcut Id="Rgui64DesktopShortcut" Directory="DesktopFolder" Name="R x64 %s"', Rver), sprintf(' WorkingDirectory="STARTDIR" Target="[!%s]" />', rgui64), ' <RegistryValue Root="HKCU" Key="Software\\R-core\\R" Name="installed" Type="integer" Value="1" KeyPath="yes"/>', ' </Component>') cat(file = con, sep="\n", ' </Directory>', '', ' <Directory Id="AppDataFolder" Name="AppData">', ' <Directory Id="Microsoft" Name="Microsoft">', ' <Directory Id="InternetExplorer" Name="Internet Explorer">', ' <Directory Id="QuickLaunch" Name="Quick Launch">', sprintf(' <Component Id="quickshortcut0" DiskId="1" Guid="%s">', guuids()), sprintf(' <Shortcut Id="RguiQuickShortcut" Directory="QuickLaunch" Name="R %s"', Rver), sprintf(' WorkingDirectory="STARTDIR" Target="[!%s]" />', rgui), ' <RegistryValue Root="HKCU" Key="Software\\R-core\\R" Name="installed" Type="integer" Value="1" KeyPath="yes"/>', ' </Component>', ' </Directory>', ' </Directory>', ' </Directory>', ' </Directory>', '', '' ) if(have32bit) { # go in 32-bit registry cat(file = con, sep="\n", sprintf(' <Component Id="registry32" Guid="%s">', guuids()), ' <RegistryKey Id="RInstallPath" Root="HKMU" Key="Software\\R-core\\R" Action="create">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' <RegistryValue Name="Current Version" Type="string" Value="[RVersion]"/>', ' </RegistryKey>', ' <RegistryKey Id="RCurrentVerInstallPath" Root="HKMU" Key="Software\\R-core\\R\\[RVersion]" Action="createAndRemoveOnUninstall">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' </RegistryKey>', ' <RegistryKey Id="R32InstallPath" Root="HKMU" Key="Software\\R-core\\R32" Action="create">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' <RegistryValue Name="Current Version" Type="string" Value="[RVersion]"/>', ' </RegistryKey>', ' <RegistryKey Id="R32CurrentVerInstallPath" Root="HKMU" Key="Software\\R-core\\R32\\[RVersion]" Action="createAndRemoveOnUninstall">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' </RegistryKey>', ' </Component>', '') } if(have64bit) { # go in 64-bit registry cat(file = con, sep="\n", sprintf(' <Component Id="registry64" Guid="%s" Win64="yes">', guuids()), ' <RegistryKey Id="Rx64InstallPath" Root="HKMU" Key="Software\\R-core\\R" Action="create">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' <RegistryValue Name="Current Version" Type="string" Value="[RVersion]"/>', ' </RegistryKey>', ' <RegistryKey Id="Rx64CurrentVerInstallPath" Root="HKMU" Key="Software\\R-core\\R\\[RVersion]" Action="createAndRemoveOnUninstall">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' </RegistryKey>', ' <RegistryKey Id="R64InstallPath" Root="HKMU" Key="Software\\R-core\\R64" Action="create">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' <RegistryValue Name="Current Version" Type="string" Value="[RVersion]"/>', ' </RegistryKey>', ' <RegistryKey Id="R64CurrentVerInstallPath" Root="HKMU" Key="Software\\R-core\\R64\\[RVersion]" Action="createAndRemoveOnUninstall">', ' <RegistryValue Name="InstallPath" Type="string" Value="[INSTALLDIR]"/>', ' </RegistryKey>', ' </Component>', '') } ## file associations cat(file = con, sep="\n", sprintf(' <Component Id="registry3" Guid="%s">', guuids()), " <ProgId Id='RWorkspace' Description='R Workspace'>", " <Extension Id='RData'>", sprintf(" <Verb Id='open' Command='Open' TargetFile='%s' Argument='\"%%1\"'/>", rgui), " </Extension>", " </ProgId>", ' </Component>') cat(file = con, sep="\n", ' </Directory>') ## the features. cat(file = con, sep="\n", '', ' <Feature Id="main" Title="Main Files" Description="Main Files" Level="1"', ' ConfigurableDirectory="INSTALLDIR"', ' InstallDefault="local" AllowAdvertise="no"', ' Absent="disallow">') for(id in ids[comps == 'main']) cat(file = con, " <ComponentRef Id='", id, "' />\n", sep="") cat(file = con, ' </Feature>\n') cat(file = con, sep="\n", '', ' <Feature Id="startup" Title="Starting Directory" Description="Set starting directory for R shortcuts" Level="1"', ' ConfigurableDirectory="STARTDIR"', ' InstallDefault="local" AllowAdvertise="no"', ' Absent="disallow">', ' <ComponentRef Id="dummystart" />', ' </Feature>\n') if (have64bit && have32bit) { cat(file = con, sep="\n", '', ' <Feature Id="i386" Title="32-bit Files" Description="32-bit binary files" Level="1"', ' InstallDefault="local" AllowAdvertise="no">') for(id in ids[comps == 'i386']) cat(file = con, " <ComponentRef Id='", id, "' />\n", sep="") cat(file = con, ' </Feature>\n') } if (have64bit) { cat(file = con, sep="\n", '', ' <Feature Id="x64" Title="64-bit Files" Description="64-bit binary files" Level="1"', if (!have32bit) ' Absent="disallow"', ' InstallDefault="local" AllowAdvertise="no">') for(id in ids[comps == 'x64']) cat(file = con, " <ComponentRef Id='", id, "' />\n", sep="") cat(file = con, ' </Feature>\n') } cat(file = con, sep="\n", '', ' <Feature Id="shortcuts" Title="Shortcuts" Description="Shortcut install options" Level="1" InstallDefault="local"', ' AllowAdvertise="no" Display="expand">', " <Feature Id='sshortcuts' Title='Start Menu Shortcuts' Description='Install Start menu shortcuts' Level='1'", " ConfigurableDirectory='RMENU' InstallDefault='local' AllowAdvertise='no'>", if (have32bit) " <ComponentRef Id='shortcut0' />", if (have64bit) " <ComponentRef Id='shortcut64' />", " <ComponentRef Id='shortcut1' />", " </Feature>", " <Feature Id='dshortcut' Title='Desktop Shortcut' Description='Install Desktop shortcut' Level='1'", " InstallDefault='local' AllowAdvertise='no'>", if (have32bit) " <ComponentRef Id='desktopshortcut0' />", if (have64bit) " <ComponentRef Id='desktopshortcut64' />", " </Feature>", ' <Feature Id="qshortcut" Title="Quicklaunch Shortcut" Description="Install Quick Launch shortcut" Level="1000"', ' InstallDefault="local" AllowAdvertise="no">', " <ComponentRef Id='quickshortcut0' />", " </Feature>", " </Feature>") cat(file = con, sep="\n", ' <Feature Id="registryversion" Title="Save Version in Registry"', ' Description="Save the R version and install path in the Registry" Level="1" InstallDefault="local" AllowAdvertise="no">', if (have32bit) " <ComponentRef Id='registry32' />", if (have64bit) " <ComponentRef Id='registry64' />", " </Feature>", ' <Feature Id="associate" Title="Associate with .RData files"', ' Description="Associate R with .RData files" Level="1" InstallDefault="local" AllowAdvertise="no">', " <ComponentRef Id='registry3' />", " </Feature>") cat(file = con, sep="\n", "", ' <UIRef Id="WixUI_FeatureTree" />', ' <UIRef Id="WixUI_ErrorProgressText" />', ' <WixVariable Id="WixUILicenseRtf" Value="License.rtf" />', '', # ' <Icon Id="shell32.dll" SourceFile="C:\\Windows\\system32\\shell32.dll" />', '', " </Product>", "</Wix>") close(con) } args <- commandArgs(TRUE) do.call(".make_R.wxs", as.list(args))