From fe0c8f9216fbc607578054ac34b0161976ba72d7 Mon Sep 17 00:00:00 2001 From: nigredo-tori Date: Thu, 29 Nov 2018 19:33:27 +0700 Subject: [PATCH] WindowsPlugin: support multiple wxs sources (#1176) (#1177) * Implement building from multiple WiX sources * Add a test for custom WiX sources in WindowsPlugin * Fix code formatting * Remove unnecessary overwrite flag * Fix for SBT 0.13 --- .../typesafe/sbt/packager/windows/Keys.scala | 4 +- .../sbt/packager/windows/WindowsPlugin.scala | 34 ++++++++++---- src/sbt-test/windows/custom-wix/build.sbt | 14 ++++++ .../windows/custom-wix/project/plugins.sbt | 1 + .../windows/custom-wix/src/wix/main.wsx | 47 +++++++++++++++++++ .../windows/custom-wix/src/wix/ui.wsx | 7 +++ src/sbt-test/windows/custom-wix/test | 3 ++ src/sphinx/formats/windows.rst | 8 ++-- 8 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 src/sbt-test/windows/custom-wix/build.sbt create mode 100644 src/sbt-test/windows/custom-wix/project/plugins.sbt create mode 100644 src/sbt-test/windows/custom-wix/src/wix/main.wsx create mode 100644 src/sbt-test/windows/custom-wix/src/wix/ui.wsx create mode 100644 src/sbt-test/windows/custom-wix/test diff --git a/src/main/scala/com/typesafe/sbt/packager/windows/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/windows/Keys.scala index 9f276cfbe..5e2fa74b9 100644 --- a/src/main/scala/com/typesafe/sbt/packager/windows/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/windows/Keys.scala @@ -19,7 +19,9 @@ trait WindowsKeys { TaskKey[xml.Node]("wix-product-xml", "The WIX XML configuration for a product (nested in Wix/Product elements).") val wixConfig = TaskKey[xml.Node]("wix-xml", "The WIX XML configuration for this package.") - val wixFile = TaskKey[File]("wix-file", "The WIX XML file to package with.") + @deprecated("Use wixFiles task instead", "1.3.15") + val wixFile = TaskKey[File]("wix-file", "The generated WIX XML file.") + val wixFiles = TaskKey[Seq[File]]("wix-files", "WIX XML sources (*.wxs) to package with") val candleOptions = SettingKey[Seq[String]]("candle-options", "Options to pass to the candle.exe program.") val lightOptions = SettingKey[Seq[String]]("light-options", "Options to pass to the light.exe program.") val wixMajorVersion = diff --git a/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala index 21ab54bf3..711b4c8ac 100644 --- a/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/windows/WindowsPlugin.scala @@ -96,27 +96,45 @@ object WindowsPlugin extends AutoPlugin { val wixConfigFile = (target in Windows).value / ((name in Windows).value + ".wxs") IO.write(wixConfigFile, config.toString) wixConfigFile - } + }, + wixFiles := Seq(wixFile.value) ) ++ inConfig(Windows)(Seq(packageBin := { - val wixFileValue = wixFile.value + val wsxSources = wixFiles.value val msi = target.value / (name.value + ".msi") - // First we have to move everything (including the wix file) to our target directory. - val wix = target.value / (name.value + ".wix") - if (wixFileValue.getAbsolutePath != wix.getAbsolutePath) IO.copyFile(wixFileValue, wix) + + // First we have to move everything (including the WIX scripts) + // to our target directory. + val targetFlat: Path.FileMap = Path.flat(target.value) + val wsxFiles = wsxSources.map(targetFlat(_).get) + val wsxCopyPairs = wsxSources.zip(wsxFiles).filter { + case (src, dest) => src.getAbsolutePath != dest.getAbsolutePath + } + IO.copy(wsxCopyPairs) IO.copy(for ((f, to) <- mappings.value) yield (f, target.value / to)) + // Now compile WIX val wixdir = Option(System.getenv("WIX")) getOrElse sys.error( "WIX environment not found. Please ensure WIX is installed on this computer." ) - val candleCmd = Seq(wixdir + "\\bin\\candle.exe", wix.getAbsolutePath) ++ candleOptions.value + val candleCmd = (wixdir + "\\bin\\candle.exe") +: + wsxFiles.map(_.getAbsolutePath) ++: + candleOptions.value + val wixobjFiles = wsxFiles.map { wsx => + wsx.getParentFile / (wsx.base + ".wixobj") + } + streams.value.log.debug(candleCmd mkString " ") sys.process.Process(candleCmd, Some(target.value)) ! streams.value.log match { case 0 => () case exitCode => sys.error(s"Unable to run WIX compilation to wixobj. Exited with ${exitCode}") } + // Now create MSI - val wixobj = target.value / (name.value + ".wixobj") - val lightCmd = Seq(wixdir + "\\bin\\light.exe", wixobj.getAbsolutePath) ++ lightOptions.value + val lightCmd = List(wixdir + "\\bin\\light.exe", "-out", msi.getAbsolutePath) ++ wixobjFiles.map( + _.getAbsolutePath + ) ++ + lightOptions.value + streams.value.log.debug(lightCmd mkString " ") sys.process.Process(lightCmd, Some(target.value)) ! streams.value.log match { case 0 => () diff --git a/src/sbt-test/windows/custom-wix/build.sbt b/src/sbt-test/windows/custom-wix/build.sbt new file mode 100644 index 000000000..a4ee3fc17 --- /dev/null +++ b/src/sbt-test/windows/custom-wix/build.sbt @@ -0,0 +1,14 @@ +enablePlugins(WindowsPlugin) + +name := "custom-wix" +version := "0.1.0" + +// make sure we don't somehow use the generated script +wixFile in Windows := { + sys.error("wixFile shouldn't have been called") +} + +wixFiles := List( + sourceDirectory.value / "wix" / "main.wsx", + sourceDirectory.value / "wix" / "ui.wsx" +) diff --git a/src/sbt-test/windows/custom-wix/project/plugins.sbt b/src/sbt-test/windows/custom-wix/project/plugins.sbt new file mode 100644 index 000000000..b53de154c --- /dev/null +++ b/src/sbt-test/windows/custom-wix/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version")) diff --git a/src/sbt-test/windows/custom-wix/src/wix/main.wsx b/src/sbt-test/windows/custom-wix/src/wix/main.wsx new file mode 100644 index 000000000..d0efaa29b --- /dev/null +++ b/src/sbt-test/windows/custom-wix/src/wix/main.wsx @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/sbt-test/windows/custom-wix/src/wix/ui.wsx b/src/sbt-test/windows/custom-wix/src/wix/ui.wsx new file mode 100644 index 000000000..dad5dd637 --- /dev/null +++ b/src/sbt-test/windows/custom-wix/src/wix/ui.wsx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/sbt-test/windows/custom-wix/test b/src/sbt-test/windows/custom-wix/test new file mode 100644 index 000000000..edbc455c5 --- /dev/null +++ b/src/sbt-test/windows/custom-wix/test @@ -0,0 +1,3 @@ +# Run the windows packaging. +> windows:packageBin +$ exists target/windows/custom-wix.msi diff --git a/src/sphinx/formats/windows.rst b/src/sphinx/formats/windows.rst index b30ce00e0..02bcd0c84 100644 --- a/src/sphinx/formats/windows.rst +++ b/src/sphinx/formats/windows.rst @@ -8,7 +8,7 @@ it's important to understand how WIX works. http://wix.tramontana.co.hu/ is an to how to create packages using wix. However, the native-packager provides a simple layer on top of wix that *may* be enough for most projects. -If it is not enough, just override ``wixConfig`` or ``wixFile`` settings. Let's look at the layer above direct +If it is not enough, just override ``wixConfig`` or ``wixFiles`` tasks. Let's look at the layer above direct xml configuration. .. note:: The windows plugin depends on the :ref:`universal-plugin`. @@ -109,10 +109,10 @@ Settings inline XML to use for wix configuration. This is everything nested inside the ```` element. ``wixConfig`` - inline XML to use for wix configuration. This is used if the ``wixFile`` setting is not specified. + inline XML to use for wix configuration. This is used if the ``wixFiles`` task is not specified. - ``wixFile`` - The file containing WIX xml that defines the build. + ``wixFiles`` + WIX xml source files (``wxs``) that define the build. ``mappings in packageMsi in Windows`` A list of file->location pairs. This list is used to move files into a location where WIX can pick up the files and generate a ``cab`` or embedded ``cab`` for the ``msi``.