Week 31 — What are build tools and which problem do they solve?

Question of the Week #31
What are build tools and which problem do they solve?
8 Replies
Eric McIntyre
Eric McIntyre17mo ago
The build tool is a piece of software that takes all parts of the source code, and produces executable objects. One of the main features of the build tools are dependency management. You can download and update different versions of libraries located remotely or locally.
Submission from gargatuma#0000
Eric McIntyre
Eric McIntyre17mo ago
Build tools are frameworks or scripts used to automatically download and install listed dependencies (e.g. libraries; versions) which are then being shipped with the programm. It solves the problem of having to update lots of dependencies and checking compatability whenever there is a change
Submission from Soulvenom#0749
Eric McIntyre
Eric McIntyre17mo ago
Build tools automate the process of compiling, assembling, and deploying software, which is tedious to do by hand, especially when dealing with large projects. Build tools also make the building process more consistent.
Submission from accq#0000
Eric McIntyre
Eric McIntyre17mo ago
A build tool is a tool that helps set up setting for development. It is a program for automating application generation from source code. Examples of build tools are Gradle or Maven
Submission from wooj0408#0000
Eric McIntyre
Eric McIntyre17mo ago
Software build tools are used to automate the creation of executable applications from source code. They script or automate a variety of tasks, such as downloading dependencies, compiling and packaging code, running tests, and deployment.
Submission from geekynerd_#0000
Eric McIntyre
Eric McIntyre17mo ago
Build tools are a class of tools that automate some or all of the build process, including but not restricted to: environment configuration, dependency management, linting, compiling, testing, documentation generation, and packaging. Build tools provide reproducibility in the build process for developers. Commonly used build tools in Java development include Ant, Maven, Gradle, and sometimes SBT. Many build tools are also capable of automating the process of starting a new project, oftentimes utilising a template.
⭐ Submission from gachrud#0000
Eric McIntyre
Eric McIntyre17mo ago
Build tools are managing the dependencies and build of a program. Without a build tool, it is inconvenient to manage a project using many libraries and other tooling, especially when these libraries should be updated and when multiple people work together on a project. A build tool can then automatically resolve and download the dependencies, run the project as well as the tests, deploy the project or similar. With Java, the main build tools are Maven and Gradle. Maven is configured using a file called pom.xml while Gradle is configured using a build.gradle (Groovy) file. Both can resolve and download dependencies from Maven repositories which are then used within the project and manage version conflicts. Furthermore, it is possible to configure what artefacts to produce and how, use custom logic/tooling, and e.g. run tests. Maven can be installed from https://maven.apache.org/download.cgi By default, Maven expects source files to be in src/main/java while resources are typically in src/main/resources. Test source files and test resources are normally in src/test/java and src/test/resources. A minimal pom.xml looks like the following:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
However, this configuration will use an outdated Java version. The Java version can be set to something newer with the maven-compiler-plugin:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
Then, one can also add dependencies using <dependency>-blocks:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
In this case, the pom.xml declares JUnit as a dependency. The dependency is resolved using the combination of the dependency's group id, artifact id and version (artifact coordinates). the <scope>test</scope> block means that the dependency is only available in tests (src/test/java). See https://canary.discord.com/channels/648956210850299986/1055111097562181684 for Maven scopes. In order to avoid retyping the same version for both JUnit dependencies, it is possible to create a property and reference that somewhere else in the pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<junit.version>5.9.3</junit.version>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<junit.version>5.9.3</junit.version>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
In order to actually use the some dependencies, one can add more dependencies create a class somewhere in src/main/java using these dependencies:
package io.github.danthe1st.mavendemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MavenDemo {

private static final Logger LOG = LoggerFactory.getLogger(MavenDemo.class);

public static void main(String[] args) {
add(123, 456);
}

public static int add(int a, int b) {
int result = a + b;
LOG.info("calculating {} + {} = {}", a, b, result);
return result;
}

}
package io.github.danthe1st.mavendemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MavenDemo {

private static final Logger LOG = LoggerFactory.getLogger(MavenDemo.class);

public static void main(String[] args) {
add(123, 456);
}

public static int add(int a, int b) {
int result = a + b;
LOG.info("calculating {} + {} = {}", a, b, result);
return result;
}

}
as well as a test class in src/test/java:
package io.github.danthe1st.mavendemo;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class MavenTests {
@Test
void testDemo() {
int result = MavenDemo.add(1, 2);
assertEquals(3, result);
}
}
package io.github.danthe1st.mavendemo;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class MavenTests {
@Test
void testDemo() {
int result = MavenDemo.add(1, 2);
assertEquals(3, result);
}
}
The main class can be run using the mvn exec:java command, e.g.
mvn exec:java -Dexec.mainClass="io.github.danthe1st.mavendemo.MavenDemo"
mvn exec:java -Dexec.mainClass="io.github.danthe1st.mavendemo.MavenDemo"
However, a plugin is needed in order to run all the tests. A popular option for this is the maven surefire plugin:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<junit.version>5.9.3</junit.version>
<java.version>17</java.version>
<slf4j.version>2.0.7</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins>
</build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.danthe1st</groupId>
<artifactId>mvn-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<junit.version>5.9.3</junit.version>
<java.version>17</java.version>
<slf4j.version>2.0.7</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins>
</build>
</project>
Eric McIntyre
Eric McIntyre17mo ago
With the Maven surefire plugin added to the pom.xml, it is possible to execute the tests using the command mvn test. In order to create a JAR with all necessary dependencies, one can use another plugin called the Maven assembly plugin by adding the following to the plugins section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<archive>
<manifest>
<mainClass>io.github.danthe1st.mavendemo.MavenDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<archive>
<manifest>
<mainClass>io.github.danthe1st.mavendemo.MavenDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
Upon executing mvn package, Maven should then create a JAR file ending with jar-with-dependencies.jar. This can then be executed with the java -jar command, e.g.
java -jar target/mvn-demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar
java -jar target/mvn-demo-0.0.1-SNAPSHOT-jar-with-dependencies.jar
⭐ Submission from dan1st#0000
Want results from more Discord servers?
Add your server