langmo / gradle-nsis

A gradle plugin to run NSIS
Apache License 2.0
6 stars 1 forks source link

Table of contents

Introduction

The plugin uses NSIS (Nullsoft Scriptable Install System) to create a Windows installer for any gradle project, i.e. a single .EXE file which extract all binary files generated by the project to, for example, C:/Program Files/MyProgram.

Different to other gradle plugins, this plugin comes with its own NSIS binaries which are automatically installed to a temporary folder. Therefore, no separate NSIS installation is needed, rendering this plugin suitable to be included e.g. in automatic builds of github repositories via Actions.

Configuration

How to include

The gradle-nsis plugin can be included via the standard plugin mechanism of Gradle 2.1 or higher:

plugins {
  // Load gradle-nsis plugin
  id "com.github.langmo.gradlensis" version "0.1.0"
}
nsis {
  // Enter here the configuration settings of the gradle-nsis plugin. 
  // Note: a task "createInstaller" is automatically generated.

  // path to the NSIS configuration file
  configuration = file("${rootProject.projectDir}/installer_configuration.nsi")

  // folder where the NSIS installer generator is run. All paths 
  // in the NSIS configuration file are relative to this folder.
  runIn =  file("${rootProject.projectDir}")
}

How to configure

Property Name Default Value Description
File configuration file("${rootProject.projectDir}/config.nsis") Configuration file of the NSIS installer. See examples and https://nsis.sourceforge.io/Docs/ for syntax.
File extractTo file("${rootProject.buildDir}/tmp/nsis/") Folder where the NSIS binaries are automatically extracted. Usually, there is no need to change this property.
File runIn (Folder where NSIS configuration file is located) Folder where the Windows task creating the NSIS installer (makensis.exe) is executed in (home/current directory). All file references in NSIS configuration file must be relative to this directory. Typically, this file is set to the base folder of the binaries created by the gradle project, e.g. runIn = file("${rootProject.buildDir}/install/my_application_name/") would be suited when using the gradle application/distribution plugin.
File destinationFolder file("${rootProject.buildDir}/distributions/") Folder where the NSIS installer, once created, is saved. Note: Do not include file name in this property, use destinationName instead. Usually, there is no need to change this property.
Map<String, String> variables [] Variables passed to NSIS installer generator, and which can be used in the NSIS configuration file. For example, when setting variables = ['WIN64':'True'], this is equivalent to the statement !define WIN64 True in the NSIS configuration file, and can e.g. be used by !ifdef WIN64...!endif conditional statements.
Set additionalPlugins [] Names of additional NSIS plugins on which the NSIS configuration file depends. Currently, only the plugin AccessControl is available, which can be made available via additionalPlugins = ['AccessControl']
String destinationName (see description) Name of the installer which is created. Usually, the name of the installer is set in the NSIS configuration file via the OutFile property, e.g. OutFile "MyInstaller.exe", and there is no need to set this parameter here.

Examples

Basic Example

This example creates an installer copying the file basic.nsi into the installation folder. The raw files for this example can be found here. Run gradlew createInstaller to generate the installer (the respective task is automatically generated).

File /settings.gradle:

rootProject.name = 'basic'

File /build.gradle:

// Load gradle-nsis plugin
plugins {
    id "com.github.langmo.gradlensis" version "0.1.0"
}

// Configuration of gradle-nsis plugin.
nsis {
    // path to the NSIS configuration file
    configuration = file("${rootProject.projectDir}/basic.nsi")
    // folder where the NSIS installer generator is run. All paths 
    // in the NSIS configuration file are relative to this folder.
    runIn =  file("${rootProject.projectDir}")
}

File /basic.nsi (see https://nsis.sourceforge.io/Docs/ for syntax):

;Include Modern UI
!include "MUI2.nsh"

;Basic configuration
Name "gradle-nsis basic example"
OutFile "basic.exe"
Unicode True
;Default installation folder
InstallDir "$PROGRAMFILES64\gradle_nsis_basic_example"
;Request admin privileges for Vista/7/8/10
RequestExecutionLevel admin
!define MUI_ABORTWARNING

;Pages
!insertmacro MUI_PAGE_LICENSE "LICENSE"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES  

;Languages
!insertmacro MUI_LANGUAGE "English"

;Installer Sections
Section "gradle-nsis basic example" SecExample
    SetOutPath "$INSTDIR"
    FILE basic.nsi
SectionEnd

;Descriptions
LangString DESC_SecExample ${LANG_ENGLISH} "Copies the NSIS configuration."
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
    !insertmacro MUI_DESCRIPTION_TEXT ${SecExample} $(DESC_SecExample)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

Extended Example

This example creates a distribution containing a simple JAR file displaying an info dialog indicating if the JVM runs with 32 or 64bit. It then uses the excellent gradle plugin gradle-launch4j (https://github.com/TheBoegl/gradle-launch4j) to generate two startup EXEs, one loading the JAR in a 32bit Java VM, and one loading it in a 64bit VM. Finally, it creates two NSIS installers using the same NSIS configuration file, one for each architecture.

The raw files for this example can be found here. Run gradlew createInstallers to generate both installers.

File /src/main/java/com/github/langmo/gradlensis/examples/extended/Example.java:

package com.github.langmo.gradlensis.examples.extended;
import javax.swing.JOptionPane;

public class Example {
    public static void main(String[] args) {
        JOptionPane.showMessageDialog(null, "Gradle-NSIS extended example running on "+System.getProperty("os.arch")+".", "Gradle-NSIS extended example", JOptionPane.INFORMATION_MESSAGE);
        System.exit(0);
    }
}

File /settings.gradle:

rootProject.name = 'extended'

File /build.gradle:

plugins {
    // Apply the java plugin to add support for Java
    id 'java'
    // Apply the distribution plugin.
    id 'distribution'
    // Apply the launch4j plugin to add support for generating EXE startup files
    id 'edu.sc.seis.launch4j' version '2.4.6'
    // Apply the gradlensis plugin to add support for generating Windows installers
    id "com.github.langmo.gradlensis" version "0.1.0"
}

// Set JVM compatibility mode to Java 1.7. Always a good idea to use older bytecode versions
// on Windows machines...
allprojects {
    tasks.withType(JavaCompile) {
        sourceCompatibility = '1.7'
        targetCompatibility = '1.7'
    } 
}

// Allow JAR file to be directly executed.
jar {
    manifest {
        attributes(
            'Main-Class': 'com.github.langmo.gradlensis.examples.extended.Example'
        )
    }
}

// Empty task to prevent unnecessary copying of libs by launch4j
task emptyTask{
}

// Configuration to create the EXE startup files using launch4j.
// We will create two EXE files, one for 32bit and one for 64 bit.
// Here, we only define the common properties of both files.
// See https://github.com/TheBoegl/gradle-launch4j for details.
launch4j {
    dontWrapJar = true
    headerType = 'gui'
    jar = "lib/extended.jar"
    errTitle = 'Extended gradlensis Example'
    copyConfigurable = rootProject.tasks.emptyTask.outputs.files

    cmdLine = ""
    chdir = '.'
    priority = 'normal'
    stayAlive = false
    restartOnCrash = false
    manifest = ""
    classpath = ['lib/extended.jar']
    mainClassName = "com.github.langmo.gradlensis.examples.extended.Example"

    bundledJre64Bit = false
    bundledJreAsFallback = false
    jreMinVersion = "1.7.0" 
}

// Task to create the 64 bit version of startup EXE
createExe {
    outfile = 'Example64.exe'
    jreRuntimeBits = "64"
}

// Task to create the 32 bit version of startup EXE
task createExe32(type: edu.sc.seis.launch4j.tasks.Launch4jLibraryTask) {
    outfile = 'Example32.exe'
    jreRuntimeBits = "32"
}

// Create build folder with all necessary files
distributions {
    nsis {
        distributionBaseName = 'nsis'
        contents {
            from(createExe) {
                into ''
            }
            from(createExe32) {
                into ''
            }
            project(':') {
                from(jar) {
                    into 'lib'
                }
            }
            from("${rootProject.projectDir}/LICENSE") {
                into ''
            }
        }
    }
}

// Common configuration for both installers.
nsis {
    configuration = file("${rootProject.projectDir}/extended.nsi")
    runIn =  file("${rootProject.buildDir}/install/nsis/")
}

// Specific configuration for 64bit installer
createInstaller {
    variables = ['WIN64':'True']
}
createInstaller.dependsOn installNsisDist

// Specific configuration for 32bit installer
task createInstaller32(type: com.github.langmo.gradlensis.GradleNsisTask) {
    variables = ['WIN32':'True']
}
createInstaller32.dependsOn installNsisDist

// Task to create both installers.
task createInstallers {
    dependsOn ":createInstaller32"
    dependsOn ":createInstaller"
}

// Add metadata for tasks such that they appear when calling gradlew tasks
def NSIS_GROUP = 'nsis'
createInstaller32.group = createInstaller.group
createInstaller32.description = createInstaller.description
createInstallers.group = createInstaller.group
createInstallers.description = "Creates both the 32bit and the 64bit NSIS installers"

File /extended.nsi:

;Include Modern UI
!include "MUI2.nsh"

;Basic configuration
Name "gradle-nsis extended example"
!ifdef WIN64
    OutFile "ExtendedExample64bit.exe"
!else
    OutFile "ExtendedExample32bit.exe"
!endif
Unicode True
;Default installation folder
!ifdef WIN64
    InstallDir "$PROGRAMFILES64\gradle_nsis_extended_example"
!else
    InstallDir "$PROGRAMFILES32\gradle_nsis_extended_example"
!endif
;Request admin privileges for Vista/7/8/10
RequestExecutionLevel admin
!define MUI_ABORTWARNING

;Pages
!insertmacro MUI_PAGE_LICENSE "LICENSE"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES  

;Languages
!insertmacro MUI_LANGUAGE "English"

;Installer Sections
Section "gradle-nsis extended example" SecExample
    SetOutPath "$INSTDIR"
    FILE LICENSE
    !ifdef WIN64
        FILE Example64.exe
    !else
        FILE Example32.exe
    !endif
    SetOutPath "$INSTDIR\lib"
    FILE "lib\*"
SectionEnd

;Descriptions
LangString DESC_SecExample ${LANG_ENGLISH} "Copies the license, the JAR and the EXE file."
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
    !insertmacro MUI_DESCRIPTION_TEXT ${SecExample} $(DESC_SecExample)
!insertmacro MUI_FUNCTION_DESCRIPTION_END