blob: 615ca201ded809a35047b7a45c482c161b2e0f61 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import scala.xml.Attribute
import scala.xml.transform.RewriteRule
import scala.xml.transform.RuleTransformer
enablePlugins(JavaAppPackaging)
enablePlugins(RpmPlugin)
enablePlugins(WindowsPlugin)
// need 'sbt stage' to build the CLI for cli integration tests
(test in IntegrationTest) := (test in IntegrationTest).dependsOn(stage in Compile).value
(testOnly in IntegrationTest) := (testOnly in IntegrationTest).dependsOn(stage in Compile).evaluated
(testQuick in IntegrationTest) := (testQuick in IntegrationTest).dependsOn(stage in Compile).evaluated
executableScriptName := "daffodil"
packageName in Universal := "apache-daffodil-" + version.value + "-incubating-bin" //tarball name
packageName in Linux := executableScriptName.value
packageName in Rpm := "apache-" + executableScriptName.value
packageName in Windows := executableScriptName.value
mappings in Universal ++= Seq(
baseDirectory.value / "bin.LICENSE" -> "LICENSE",
baseDirectory.value / "bin.NOTICE" -> "NOTICE",
baseDirectory.value / ".." / "DISCLAIMER" -> "DISCLAIMER",
baseDirectory.value / "README.md" -> "README.md",
)
//
// RPM configuration
//
rpmVendor := "Apache Daffodil"
maintainer in Rpm := "Apache Daffodil <dev@daffodil.apache.org>"
packageArchitecture in Rpm := "noarch"
packageSummary in Rpm := "Open source implementation of the Data Format Description Language (DFDL)"
packageDescription in Rpm := """
Apache Daffodil (incubating) is the open source implementation of the Data
Format Description Language (DFDL), a specification created by the Open Grid
Forum. DFDL is capable of describing many data formats, including textual and
binary, commercial record-oriented, scientific and numeric, modern and legacy,
and many industry standards. It leverages XML technology and concepts, using a
subset of W3C XML schema type system and annotations to describe such data.
Daffodil uses this description to parse data into an XML infoset for ingestion
and validation.
""".trim
version in Rpm := {
val parts = version.value.split("-", 2)
val ver = parts(0) // removes snapshot if it exists
ver + ".incubating"
}
rpmRelease := {
val parts = version.value.split("-", 2) // parts(0) is the version, parse(1) is snapshot if it exists
if (parts.length > 1) "0." + parts(1).toLowerCase else "1"
}
rpmLicense := Some(licenses.value.map { case (n: String, _) => n }.mkString(" and "))
rpmPrefix := Some(defaultLinuxInstallLocation.value)
//
// Windows configuration
//
//
// Here we set the variables that are supported by the SBT Native Packager plug-in.
// We also get fairly aggressive in editing/modifying the XML in order
// to control and use some specific features that are supported by WiX
// but which are not properly suported by the SBT plug-in.
//
// Force the correct installation directory name. This overwrites
// 'daffodil-cli', which is the directory that we invoke sbt in.
// The SBT WiX plug-in incorrectly assumes that the directory of
// invocation is the same name as the direcotry you eventually
// want to install into.
name in Windows := "Daffodil"
// The Windows packager SBT plug-in maps the maintainer variable into
// the WiX ManufacturerFullName field which is displayed in the properties
// dialog box for the executable.
maintainer in Windows := "Apache Daffodil Developers <dev@daffodil.apache.org>"
// The Windows packager SBT plug-in maps the packageSummary variable
// into the WiX productName field. Another strange choice.
packageSummary in Windows := "Daffodil"
// The Windows packager SBT plug-in limits the length of the
// packageDescription field to a single line. Originally this was a
// full paragraph, as seen in the RPM section, above.
packageDescription in Windows := """Apache Daffodil (incubating) is the open source implementation of the Data Format Description Language (DFDL)""".trim
// Calculate the version number dynamically and pass it in.
// Windows permits up to four numeric values (e.g. 2.1.5.1820)
// where the numbers represent major, minor, patch and build
// respectively. In RPM packaging we add 'incubating', but
// Windows will barf on this. Here we suffix a zero (0) build
// number for snapshot/development/debug builds. A one (1)
// in the build number could be used to differentiate official
// production builds that are destined for release.
version in Windows := {
val parts = version.value.split("-", 2)
val ver = parts(0) // removes snapshot if it exists
ver + ".0"
}
// Required and critical GUIDs. Ironically the ProductId is unique
// to a given release, but UpgradeId must NEVER change! This may
// seem conter-intuitive, but the UpgradeId is actually what ties
// the product to it's upgrades and the product is actually unique
// each time it is released, so there is some semblance of logic
// to this scheme.
wixProductUpgradeId := "4C966AFF-585E-4E17-8CC2-059FD70FEC77"
// Light options. Bring in standard dialog boxes and localization.
// The suppression of ICE61 is required as we *DO* permit
// re-installation of the same version. Despite the presence of
// specific XML to enable this, the WiX compiler and linker
// complain about it unless you specifically suppress the warning.
lightOptions := Seq(
"-sval", // validation does not currently work under Wine, this disables that
"-sice:ICE61",
"-ext", "WixUIExtension",
"-cultures:en-us",
"-loc", ((sourceDirectory in Windows).value / "Product_en-us.wxl").toString
)
// Build an RTF version of the license file for display in the license
// acceptance dialog box. This file will also be sent to the
// printer when and if the user asks for hard copy via the 'print' button.
wixProductLicense := {
// Make sure the target direcotry exists.
(target in Windows).value.mkdirs()
// This target file doesn't exist until placed there by the build.
val targetLicense = (target in Windows).value / "LICENSE.rtf"
val sourceLicense = baseDirectory.value / "bin.LICENSE"
// somehow convert sourceLicense into RTF and store at targetLicense
val rtfHeader = """{\rtf {\fonttbl {\f0 Arial;}} \f0\fs18"""
val rtfFooter = """}"""
val licenseLines = scala.io.Source.fromFile(sourceLicense, "UTF-8").getLines
val writer = new java.io.PrintWriter(targetLicense, "UTF-8")
// windows style line endings in the license are required by the WiX toolkit
writer.write(rtfHeader + "\r\n")
licenseLines.foreach { line =>
writer.write(line + """\line""" + "\r\n")
}
writer.write(rtfFooter + "\r\n")
writer.close
Option(targetLicense)
}
// Use the wixFiles variable to add in the Daffodil-specific dialog
// boxes and sequence.
wixFiles ++= Seq(
(sourceDirectory in Windows).value / "WixUI_Daffodil.wxs",
(sourceDirectory in Windows).value / "DisclaimerDlg_Daffodil.wxs"
)
// The SBT Native Packager plug-in assumes that we want to give the user
// a Feature Tree to select from. One of the 'features' that the plug-in
// offers up is a set of all shortcuts and menu links. Daffodil is
// actually a command-line executable, so we do not include
// configuration links as they are unnecessary. From a practical
// standpoint the user must invoke a command shell in a window
// before they can invoke Daffodil anyway.
wixFeatures := {
val features = wixFeatures.value
features.filter { _.id != "AddConfigLinks"}
}
// Make sure that we don't use an MSI installer that is older than
// version 2.0. It also fixes the comment attribute that hangs
// out on the Package keyword.
wixPackageInfo := wixPackageInfo.value.copy(installerVersion = "200", comments = "!(loc.Comments)")
// Fix the XML that is associated with the installable files and directories.
wixProductConfig := {
// Pick up the generated code.
val pc = wixProductConfig.value
// Replace the default headline banner and Welcome/Exit screen
// bitmaps with the custom ones we developed for Daffodil.
val banner = <WixVariable Id="WixUIBannerBmp" Value={ ((sourceDirectory in Windows).value / "banner.bmp").toString } />
val dialog = <WixVariable Id="WixUIDialogBmp" Value={ ((sourceDirectory in Windows).value / "dialog.bmp").toString } />
// Reference the Daffodil-specific User Interface (dialog box) sequence.
val ui = <UI><UIRef Id="WixUI_Daffodil" /></UI>
// Make sure we abort if we are not installing on Windows 95 or later.
val osCondition = <Condition Message="!(loc.OS2Old)"><![CDATA[Installed OR (VersionNT >= 400)]]></Condition>
// Define icons (ID should not be longer than 18 chars and must end with ".exe")
val icon = Seq(
<Icon Id="Icon.exe" SourceFile={ ((sourceDirectory in Windows).value / "apache-daffodil.ico").toString } />,
<Property Id="ARPPRODUCTICON" Value="Icon.exe" />
)
// String together the additional XML around the generated directory and file lists.
val pcGroup = pc.asInstanceOf[scala.xml.Group]
val newNodes = osCondition ++ icon ++ pcGroup.nodes ++ dialog ++ banner ++ ui
val pcWithNewNodes = pcGroup.copy(nodes = newNodes)
// Change (edit) some items inside the directory/files list.
val pcRewriteRule = new RewriteRule {
override def transform(n: scala.xml.Node): Seq[scala.xml.Node] = n match {
// We want to comply with the Windows standard pattern of
// installing at /Program Files/ManufacturerName/Application
// This case effectively inserts the manufacturer name into
// the XML as a directory to comply with the standard.
case e: scala.xml.Elem if (e \ "@Name").text == "PFiles" => {
val apacheDir = <Directory Id="ProgramFilesApache" Name="!(loc.ManufacturerName)" />
val apacheDirWithChild = apacheDir.copy(child = e.child)
e.copy(child = apacheDirWithChild)
}
// We *ARE* going to allow the user to repair and reinstall
// the same exact version, so we need to add an attribute
// to the MajorUpgrade keyword. This will trigger an 'ICE61'
// error that we suppress on the 'light' linker command line.
case e: scala.xml.Elem if e.label == "MajorUpgrade" => {
e % scala.xml.Attribute("", "AllowSameVersionUpgrades", "yes", e.attributes)
}
// Fixup for registry key.
case e: scala.xml.Elem if e.label == "RegistryValue" => {
val attribs = e.attributes.remove("Key")
e % scala.xml.Attribute("", "Key", """Software\Apache\Installed Products\Daffodil""", attribs)
}
// The WixUI_FeatureTree reference has to be removed so that
// our custom Daffodil UI can operate properly.
case e: scala.xml.Elem if e.label == "UIRef" && (e \ "@Id").text == "WixUI_FeatureTree" => {
scala.xml.NodeSeq.Empty
}
case `n` => n
}
}
// Now apply all the edits in the RewriteRule defined above.
val newXml = new RuleTransformer(pcRewriteRule).transform(pcWithNewNodes)
<xml:group>{newXml}</xml:group>
}