Build

Contents

Overview

Niagara 4 contains many architecture and functionality improvements. One area Tridium is improving on is the Niagara system’s support for standard software development tools. The intent is that there will be minimal changes required in your development environment to compile modules in Niagara 4, while providing a better and more standard user experience for our Java developer customers.

One change being made is to incorporate Gradle into our build tool chain and migrate away from the proprietary build system used in Niagara AX. This should enable a more standard setup of development projects and provide more standard integration with Java IDEs (specifically Eclipse or IntelliJ).

Additional information on Gradle can be found by following the links below. It is not expected that Niagara developers become experts in Gradle, but there is a lot of information available on the web, as well as several books available for those who wish to learn more.

Gradle home page
Gradle user guide
Gradle language reference

Gradle Configuration

There is some configuration required to run Gradle to compile module source code, build a module jar file, and assemble module a javadoc jar file. For single module projects, a basic build.gradle script is required to actually build the module, and a gradlew.bat script is required to install Gradle, set up the environment, and initiate the build process.

Build scripts for single module projects or the main project of a multi-project build should be executed with the gradlew.bat. The first time it is run it will install Gradle for you, so there is no installation required by the developer. It also sets up the build environment (Java classpath, etc.) for a Gradle project to use during execution. The

The build.gradle script contains the actual Domain Specific Language (DSL) code used by Gradle to run the module build task. It contains the same basic information as a build.xml file has for Niagara AX modules, like the module name, version, vendor, and dependencies. More details of the elements defined in the build.gradle and a mapping of build.xml elements to a build.gradle script are located in the Build Script Elements section below.

For multi-project builds, a single gradlew.bat file and a build.gradle script is needed for the main project of the build. Each module will have a gradle file containing module-specific configuration elements.

For large multi-project builds, Gradle includes a Configuration On Demand mode that improves build performance by only configuring projects that are relevant for the required tasks. To enable this feature, add it to your Gradle properties file:

Other elements can be configured here, including org.gradle.daemon = true. Enabling the daemon element can improve build times, but will keep the JVM binary locked on Windows. You can read more about Gradle configuration on the Gradle web site.

Note: Certain network configurations may require setting proxy information in the gradle.properties file in the user’s home folder. More information on how this is configured can be found on the Gradle web site.

Project Setup

Project Configuration Files

In addition to the gradlew.bat and build.gradle files, a module-include.xml file is required, and the module.palette and module.lexicon files are optional. If you have test classes for your module, a moduleTest-include.xml is needed. The contents of these files are described in a later section of this document. Note that the Niagara AX build.xml file is no longer needed to build Niagara 4 modules.

Project Source Code Layout

Gradle locates source code through a configuration called sourceSets. The default source set configuration for Niagara projects is for the source code to be in a folder called src and for test source code to be in srcTest. This folder structure is used during compile to allow Gradle to locate source code and during module jar creation to enable Gradle to locate any files to include in the module. See the build script for examples of include files for main and test modules - the from(…) syntax. More details on setting up tests can be found in the TestNG Support in Niagara 4 document.

Stand-alone Module Project

\<module name> - Top level source directory
|- build.gradle - Gradle script file
|- module.lexicon - Default lexicon file
|- module.palette - Defines Palette information for the module
|- module-include.xml - Declares Types, Defs, etc. for the module
|- moduleTest-include.xml - Declares Types, Defs, etc. for the test module
|- module-permissions.xml - Declares permissions for the module
|- src\ - Folder containing module packages, source files, and resource files
|- srcTest\ - Folder containing test packages, source files, and resource files

Multi-project Module Set

\<some folder name> - Top level directory
|- build.gradle - Main Gradle script file
|- vendor.gradle - Define the group (vendorName) and version here - they will be used in all modules
|- settings.gradle - Gradle script containing the names of all modules or folders containing modules
|- <module 1 name>\ - Folder containing Module 1
| |- <module 1 name>.gradle - Module 1 Gradle script file
| |- module.lexicon - Default lexicon file for module 1
| |- module.palette - Defines Palette information for module 1
| |- module-include.xml - Declares Types, Defs, etc. for module 1
| |- module-permissions.xml - Declares permissions for module 1
| |- moduleTest-include.xml - Declares Types, Defs, etc. for test module 1
| |- src\ - Folder containing module 1 packages, source files, and resource files
| |- srcTest\ - Folder containing test 1 packages, source files, and resource files
|- <module 2 name>\ - Folder containing Module 2
| |- <module 2 name>.gradle - Module 2 Gradle script file
...

Running Gradle

Gradle Task Resolution

Part of the reason for using Gradle is that it includes a DSL (Domain Specific Language) for building Java projects. A small amount of script configuration results in a powerful set of tasks for compiling, assembling, testing, and publishing software. When you run gradlew <taskName>, Gradle will apply that task to all projects that declare that task. For example, gradlew clean will clean all modules in a multi-project configuration. If you want to execute a task against a specific project, use the gradlew :path:to:project:<taskName> syntax. If your multi-project module set is organized as described above, you can run Gradle tasks for a single module using gradlew :<moduleName>:<taskName>. For example, to clean the componentLinks module in the developer examples under the dev folder, run gradlew :componentLinks:clean. When you execute gradlew for the first time, it will download the Gradle framework required to complete task execution. This will take a few moments, but will only be needed once.

Common Gradle Tasks

gradlew tasks - List the Gradle tasks available for execution
gradlew jar - Compile module source code, assemble the module jar, and copy it to the installation location
gradlew javadocJar - Generate javadoc files and assemble them into a jar file
gradlew moduleTestJar - Compile, jar, and install test module code
gradlew clean - Clean compiled artifacts from the module folder
gradlew :<moduleName>:jar - Compile, jar, and install a single
gradlew :<moduleName>:slotomatic - Run slot-o-matic on a single

Additional Gradle Options

External Dependencies

In Niagara AX, if you had an external dependency on a third-party jar (like Apache commons-pool) and choose not to convert it to a module, then you included it in the extdirectory of your module source and build.jar would take care of including it in your generated module. This process is typically called creating an “uberjar” or “fatjar”.

In Niagara 4, using Gradle we take a slightly different approach. You declare all your external dependencies in your Gradle script using a special uberjar dependency configuration. Any dependencies declared against the uberjar configuration will be automatically included in the generated module. Also, in Niagara 4 we are moving towards pulling external dependencies from a central repository. Gradle includes support for the central Maven repository, which is a commonly used repository for software artifacts. Gradle will download the dependency automatically from the central Maven repository and include it in the generated module. The Gradle build scripts will no longer look for dependencies in the ext directory of your module.

NOTE: Internet connectivity is required for accessing the central Maven repository.

Gradle IDE Integration

Gradle projects can be automatically imported into both IntelliJ and Eclipse. Simply open your project’s build.gradle with either and it will import your project automatically.

NOTE: Previous versions of Niagara used the gradlew idea and gradlew eclipse commands, which are now deprecated. See Updating to a new Gradle Project Layout if you are using a project layout from Niagara 4.4 or earlier.

Gradle Build Scripts

The Gradle script files contain elements similar to those in the Niagara AX build.xml file, configured for Gradle. The specific configuration will depend on the type of project (stand-alone or multi-project) required by the developer. For a stand-alone module, the Gradle script file is build.gradle. For a multi-project build environment, there will be one build.gradle for the main project, and each module within the project will have a <module>.gradle file. The developer examples found in the dev folder contain script files for both configurations. See the description of stand-alone and multi-project configurations for details on the two project types.

Each build.gradle script, either stand-alone or multi-project, will have an associated gradlew.bat Gradle wrapper file.

Gradle Wrapper Script - gradlew.bat

A gradle wrapper file is available in the bin folder of the Niagara installation. It sets up the build environment for compiling Niagara modules, including Java class paths and Gradle configuration settings. The first time it is used to compile a module, it will download the Gradle runtime libraries and any external dependencies needed to compile. It should be used every time modules are compiled, as it enables a Gradle daemon to improve compile efficiency.

Additional information about the Gradle wrapper is available on the Gradle web site. More advanced users may choose to modify the wrapper script as needed, but it is likely that this will not be necessary.

Build Script Elements - build.gradle

Several Gradle properties must be declared in the appropriate script file in order for the module to compile, jar, and test correctly. The examples shown later in this document and the source examples in the dev folder contain the commonly used properties that will need to be defined for each module. Use them as templates for your stand-alone modules. There are other elements in these examples that should be left as they are; these are noted by comments in the Gradle scripts. Some common elements used in Gradle build scripts are described below. The specific Gradle file containing these elements depends on which configuration being used (stand-alone or multi-project). Refer to the examples for guidance on where to locate these elements in your projects.

ext {} - This namespace is used to declare extra properties within the project.
buildscript {} - Configures the classpath used by the build script for this project.
repositories {} - Gradle uses these to resolve and download dependency artifacts. The defaultconfigurations for Niagara 4 projects uses Maven and local flat file repositories for providing dependencies.
dependencies {} - Specific artifacts required by particular phases of the build sequence (r.g. compile, test, etc.).
jar {} - Enables the jar task to locate additional files to include in the jar file.
apply - Include shared Gradle code into the current project.
sourceSets {} - Configurations for source file locations.
niagaraModule {} - Provided by the niagara-module plugin to enable construction of a Niagara 4 compliant jar file.
moduleTestJar {} - Provided by the niagara-module plugin to enable construction of a Niagara 4 compliant test jar file.

NOTE: The examples in the dev folder contain configurations for both project types. You only need to configure one of these (stand-alone or multi-project).

Gradle Dependency Notation

Your modules will generally have a dependency on one or more Niagara 4 modules. These dependency declarations are declared in the module build Gradle file. The first element in the dependency declaration is the configuration name. The standard Gradle configuration for compiling Java code is compile. A second configuration used for test classes in Niagara 4 is niagaraModuleTestCompile. The second element in the dependency declaration is the dependency notation. The notation used in the example modules for external dependencies uses the String notation format. The notation contains the group (vendorName), name (module), and version, each separated by a colon (:). So the notation for declaring a dependency on the baja.jar module is "Tridium:baja:4.0".

One advantage of using Gradle is that it does transitive dependency resolution automatically. This means that you only need to declare direct dependencies on modules or external libraries that your code directly references. If these direct dependencies have their own compile-time dependencies (i.e. transitive dependencies), Gradle will resolve these automatically.

Other notation formats are possible. See the Gradle documentation for additional information on dependency management.

Convert Niagara AX build.xml to Niagara 4 build.gradle

In the Niagara AX Developer Guide, the section on Build provides an overview of the elements available for inclusion in the build.xml file. This includes a definition of XML element and attributes that can be used in build.xml. There are four XML elements described in the documentation: module (the root element), dependency, package, and resources. Most of the element and attribute mappings from build.xml to the Gradle script are straightforward. Pay particular attention to the dependency declarations. Gradle contains a more sophisticated approach to dependency resolution described above, and has a standard way of declaring and resolving dependencies that has been adopted in Niagara 4.

Mapping Summary

The table below contains a mapping of common elements used in the build.xml to declarations in a corresponding Gradle script.

build.xml Gradle Script
Root <module> Attributes ext or niagaraModule Elements
name = "foo" ext { name = "foo" }
vendor = "X" ext { project.group = "X" }
vendorVersion = "1.5.0" ext { project.version = "1.5.0" }
description = "X foo" ext { project.description = "X foo" }
preferredSymbol = "x" niagaraModule { preferredSymbol = "x" }
bajaVersion = "0" niagaraModule { bajaVersion = "0" } (optional)
<dependency> Tag dependencies Elements
name="bar" vendor="X" vendorVersion="4.0" dependencies { compile "X:bar:4.0" }
<resources> Tag jar Elements
name="/com/example/icons/*.png" jar { from("src") { include "/com/example/icons/*.png" } }
<dependency> Tag for Test dependencies Elements
name="baz" vendor="X" vendorVersion="4.0" test="true" dependencies { niagaraModuleTestCompile "X:baz:4.0" }
<resources> Tag for Test moduleTestJar Elements
name="com/example/test/*.bog" test="true" moduleTestJar { from("srcTest") { include "com/example/test/*.bog" } }

Example Conversion

build.xml

<module 
  name = "componentLinks" 
  bajaVersion = "0" 
  preferredSymbol = "cl" 
  description = "Example of checking and creating Links programmatically" 
  vendor = "Tridium" 
>  
  <dependency name="baja" vendor="Tridium" vendorVersion="4.0" /> 
  <dependency name="kitControl" vendor="Tridium" vendorVersion="4.0" /> 
  <dependency name="control" vendor="Tridium" vendorVersion="4.0" /> 
  <dependency name="bajaui" vendor="Tridium" vendorVersion="4.0" test="true" />

  <package name="com.examples.componentLinks" />

  <resources name="com/examples/icons/*.png" /> 
  <resources name="com/examples/test/bogs/*.bog" test="true" /> 
</module>

NOTE: The module version is retrieved from the devkit.properties file

build.gradle

//use default niagara configurations for modules 
apply from: "${System.getenv('niagara_home')}/etc/gradle/niagara.gradle" 
apply from: "${System.getenv("niagara_home")}/etc/gradle/eclipse.gradle"
apply from: "${System.getenv("niagara_home")}/etc/gradle/idea.gradle"

ext {
  // Declare module name and project properties 
  name = "componentLinks" 
  project.version = "5.0.1"
  project.group = "Tridium"
  description = "Example of checking and creating Links programmatically" 
}

// Declare niagaraModule properties 
niagaraModule { 
  preferredSymbol = "cl" 
  // The runtime profile indicates the minimum Java runtime support required for this module jar 
  runtimeProfile = "rt" 
  // The moduleName is registered with the Niagara runtime engine. 
  // In Niagara 4, it is possible for a module to have multiple jar files for separate runtimeProfile values. 
  moduleName = "componentLinks" 
}

// Declare compile and test dependencies 
dependencies { 
  compile "Tridium:baja:4.0.0" 
  compile "Tridium:kitControl-rt:4.0.0" 
  compile "Tridium:control-rt:4.0.0"

  niagaraModuleTestCompile "Tridium:bajaui-wb:4.0.0"
}

// Include additional files in module jar 
jar { 
  from("src") { 
    include "com/examples/icons/*.png"
  }
}

// Include additional files in the test jar 
moduleTestJar { 
  from("srcTest") {
    include "com/examples/test/bogs/*.bog"
  } 
}

Other Module Files

module-include.xml

This file is placed directly under the module’s root directory. If it is declared, then the build tools automatically include it in the module’s manifest as META-INF/module.xml. Its primary purpose is to allow developers to declare def, type, and lexicon elements.

module-permissions.xml

This file contains any permissions your module requests.

module.palette

The module.palette file is an optional file that is placed directly under the module’s root directory. If included it is automatically inserted into the module jar file, and accessible in the module as /module.palette. The module.palette file should contain the standard palette of public components provided by the module. The format of the file is the same as a standard .bog file.

module.lexicon

The module.lexicon file is an optional file that is placed directly under the module’s root directory. If included it is automatically inserted into the module jar file. The lexicon file defines the name/value pairs accessed via the Lexicon API.

moduleTest-include.xml

Put any Niagara def, type, and lexicon elements used in your test classes in this file.

Single Module Project

Project Setup

A stand-alone module not part of a multi-project build needs to have only the build.gradle and gradle.bat files in the top level folder to support building the module with Gradle. The module-include.xml is still required, and the module.lexicon and module.palette files can be included if needed. A moduleTest-include.xml is needed for any test classes. Here is the file structure for a stand-alone project.

\<module name> - Top level source directory
|- build.gradle - Gradle script file
|- gradlew.bat - Gradle wrapper file
|- module.lexicon - Default lexicon file
|- module.palette - Defines Palette information for the module
|- module-include.xml - Declares Types, Defs, etc. for the module
|- moduleTest-include.xml - Declares Types, Defs, etc. for the test module
|- src\ - Folder containing module packages, source files, and resource files
|- srcTest\ - Folder containing test packages, source files, and resource files

Project Build

Gradle commands will be run from a Windows command prompt. For a single module, navigate to the folder containing the module source and configurations. The Gradle tasks for separate phases of the build sequence are below.

gradlew tasks - List the Gradle tasks available for execution
gradlew jar - Compile module source code, assemble the module jar, and copy it to the installation location
gradlew slotomatic - Run slot-o-matic on the module source code creating boiler plate slot code
gradlew javadocJar - Generate javadoc files and assemble them into a jar file
gradlew moduleTestJar - Compile, jar, and install test module code
gradlew clean - Clean compiled artifacts from the module folder

Multiple Module Project

Project Setup

A multi-project set of module jar files will have a build.gradle and gradle.bat in the top-level folder. There will also be a settings.gradle and vendor.gradle files containing Gradle elements that will be applied to all module builds. Each module jar will require a <moduleName>.gradle file containing Gradle configurations specific to that module. The module-include.xml is required for each module jar, and the module.lexicon and module.palette are included as needed. A moduleTest-include.xml is needed for any module jar containing test classes.

Niagara 4 supports multiple runtime profiles for a single Niagara module. To take advantage of this runtime configuration, there will be a separate module jar file for each profile. By convention, the gradle build file for a module jar file will be<moduleName>-<profile>.gradle and the runtime profile will be declared in that file as part of the Gradle build configuration. Profiles include rt, ux, wb, se, and doc. Here is the file structure for a project containing multiple modules.

\<some folder name> - Top level directory
|- build.gradle - Main Gradle script file
|- gradlew.bat - Gradle wrapper file
|- vendor.gradle - Define the group (vendorName) and version here - they will be used in all modules
|- settings.gradle - Gradle script containing the names of all modules or folders containing modules
|- <module 1 name>\ - Folder containing Module 1
| |- <module 1 name>.gradle - Module 1 Gradle script file
| |- module.lexicon - Default lexicon file for module 1
| |- module.palette - Defines Palette information for module 1
| |- module-include.xml - Declares Types, Defs, etc. for module 1
| |- moduleTest-include.xml - Declares Types, Defs, etc. for test module 1
| |- src\ - Folder containing module 1 packages, source files, and resource files
| |- srcTest\ - Folder containing test 1 packages, source files, and resource files
|- <module 2 name>\ - Folder containing Module 2
| |- <module 2 name>.gradle - Module 2 Gradle script file
| |- module-include.xml - Declares Types, Defs, etc. for module 2
...

Project Build

Gradle commands will be run from a Windows command prompt. For a multi-module project, navigate to the main project folder. The Gradle tasks for separate phases of the build sequence are below.

gradlew tasks - List the Gradle tasks available for execution
gradlew jar - Compile source code, assemble jars, and installation for all modules
gradlew slotomatic - Run slot-o-matic on the all source code.
gradlew javadocJar - Generate javadoc files and assemble them into jar files for all modules
gradlew moduleTestJar - Compile, jar, and install test code for all modules
gradlew clean - Clean compiled artifacts for all modules
gradlew :<moduleName>:jar - Compile, jar, and install a single
gradlew :<moduleName>:slotomatic - Run slot-o-matic on the source code.

This same module-specific syntax can be also used for the rest of the Gradle tasks.

Example Gradle Scripts

build.gradle (for the project)

ext { 
  niagaraHome = System.getenv("niagara_home") 
  if (niagaraHome == null) { 
    logger.error("niagara_home environment variable not set")
  } 
}

//to enable idea/intellij or eclipse support, un-comment the lines below 
// apply from: "${System.getenv("niagara_home")}/etc/gradle/idea.gradle" 
// apply from: "${System.getenv("niagara_home")}/etc/gradle/eclipse.gradle"

gradle.beforeProject { p -> 
  configure(p) { 
    def vendorSettings = file("${rootDir}/vendor.gradle") 
    if (vendorSettings.exists()) { 
      apply from: vendorSettings 
    } 
    apply from: "${System.getenv("niagara_home")}/etc/gradle/niagara.gradle"
  } 
}

tasks.addRule(""" 
Pattern: [jar[Test]|clean|<any gradle task>]/[path]: Run a Gradle task against a set of modules rooted at path. 
""") { String taskName -> 
  def matcher = taskName =~ /(.*?)(Test)?\/(.*)/ 
  if (matcher) { 
    def command = matcher.group(1) 
    def includeTestModules = matcher.group(2) == "Test"
    def path = file("${projectDir}/${matcher.group(3)}").toPath() 
    assert path.toFile().exists() 
    def targetProjects = subprojects.findAll { it.projectDir.toPath().startsWith(path) } 
    // default is build command and build is an alias for Gradle"s jar task 
    if (command.isEmpty() || command == "build") { command = "jar" }
    // Create task for subproject 
    task(taskName, dependsOn: targetProjects.tasks[command]) 
    if (includeTestModules && command == "jar") { 
      tasks[taskName].dependsOn targetProjects.moduleTestJar 
    } 
  } 
}

vendor.gradle

// Vendor name applied to all modules
group = "Tridium"
// Major, minor, and build version
def moduleVersion = "5.0.1"
// Patch version can be declared 
// For example, to patch envCtrlDriver module as 5.0.1.1 
// moduleVersionPatch.'envCtrlDriver' = ".1"
def moduleVersionPatch = [:] 
// Final version property applied to all modules 
version = "${moduleVersion}${moduleVersionPatch.get(project.name, '')}"

settings.gradle

import groovy.io.FileVisitResult 
import groovy.io.FileType 
def discoveredProjects = [:] as Map

ext { 
  // Configure your sub-project folders here 
  // This will include ALL sub-folders as sub-projects. 
  niagaraRoots = ["."] 
  // To explicitly define sub-project folders, name them in the array like this 
  // niagaraRoots = ["componentLinks", "envCtrlDriver"]

  // Configure any directories to exclude from search for nested sub-projects 
  excludeDirs = [".hg", "build", "out", "src", "srcTest"] 
}

// niagaraRoots configuration - do not modify 
niagaraRoots.collect({ file(it) }).findAll({ it.exists() }).each { File projectRoot -> 
  projectRoot.traverse( 
    type: FileType.DIRECTORIES, 
    preRoot: true, 
    preDir: { File projectDir -> 
      def projectName = projectDir.name 
      if (excludeDirs.contains(projectName)) { 
        return FileVisitResult.SKIP_SUBTREE 
      }

      File buildScript = new File(projectDir, "${projectName}.gradle") 
      if (buildScript.exists()) { 
        discoveredProjects[projectName] = projectDir

        if (projectDir != projectRoot) { 
          include projectName 
          return FileVisitResult.SKIP_SUBTREE 
        } 
      } 
    } 
  ) 
}

// Set up the project tree - no need to modify 
rootProject.name = "niagara" 
rootProject.children.each { project -> 
  project.projectDir = discoveredProjects[project.name] 
  project.buildFileName = "${projectName}.gradle" 
  assert project.projectDir.isDirectory() 
  assert project.buildFile.isFile() 
}

`-.gradle`

description = "Example Driver Module"

niagaraModule {
  preferredSymbol = "ecd"
  runtimeProfile = "rt"
  moduleName = "envCtrlDriver"

  modulePart {
    name = "envCtrlDriver-wb"
    runtimeProfile = "wb"
  }
}

dependencies {
  compile "Tridium:nre:4.0.0"
  compile "Tridium:baja:4.0.0"
  compile "Tridium:alarm-rt:4.0.0"
  compile "Tridium:control-rt:4.0.0"
  compile "Tridium:driver-rt:4.0.0"
  compile "Tridium:basicDriver-rt:4.0.0"
}

External Library Dependencies

Project Setup

Modules may depend on 3rd party libraries that implement some desired functionality. These dependencies are configured much like Niagara module dependencies, but are contained in a configuration called uberjar. For example, if a module has a direct dependency on the Apache Velocity library and the baja module, the dependency declaration would look like:

// Declare compile and test dependencies 
dependencies { 
  compile "Tridium:baja:4.0.0" 
  uberjar "org.apache.velocity:velocity:1.7" 
}

Libraries compiled with the uberjar configuration will cause the classes of the dependency to be included in the resulting module jar file. This makes it straightforward to distribute modules with external dependencies.

Note that the string used to identify a particular library follows a specific convention of group:name:version. So in the above example, the group is org.apache.velocity, the name is velocity, and the version is 1.7. This information relates to the Maven information for that library, and it will be verified and downloaded from a central Maven repository. See the Gradle documentation on dependency management for more information on external library dependency naming and the central Maven repository.

Updating from an Older Niagara Version

Updating to reference a new Niagara release

To retarget your project to a new version of Niagara, you must edit the file “environment.gradle” in you project root folder. Early versions of Niagara incorrectly generated this code with warnings that you should not hand-edit this file; these warnings are incorrect and may be safely ignored.

To change the version of Niagara edit “environment.gradle” and change the definitions of niagara_home and, if necessary, niagara_user_home. You need only change niagara_user_home if you are updating to minor versions of Niagara; if you are only updating to an update release, only niagara_home must change.

For example, to change your project to target 4.6 instead of 4.4, change “environment.gradle” from this:

// ...
gradle.ext.niagara_home = "c:/Niagara/Niagara-4.4.73.24"
gradle.ext.niagara_user_home = "c:/Users/user/Niagara4.4/brand"
// ...

to this:

// ...
gradle.ext.niagara_home = "c:/Niagara/Niagara-4.6.83.20"
gradle.ext.niagara_user_home = "c:/Users/user/Niagara4.6/brand"
// ...

Updating to a new Gradle project layout

In some minor releases of Niagara, changes are made to the default Gradle project layout that may require a completely new development environment. This most often occurs when a new version major version of Gradle is released.

In order to update your existing environment, you must run the New Module Wizard again, but to a folder with no existing Gradle files from previous Niagara versions. You can create a dummy module with the New Module Wizard and delete it afterwards, leaving you with just the correct project skeleton for Niagara projects. Once you have done this, you can copy or move your existing module folder(s) from the old project structure into the new one.