# Reproducible Builds

By default, JAR files generated by Gradle (with or without Shadow) for a single project with the same source code may
not be identical to each other. Sometimes it's desirable to configure a project to consistently output a byte-for-byte
identical JAR on every build. Gradle supports this with the following configuration, and Shadow will correctly respect
these settings too.

Besides file timestamps and file order, this configuration also ensures that all files in the JAR are set to have the
same permissions, irrespective of the locally configured umask.

More information about reproducible builds can be found at [reproducible-builds.org](https://reproducible-builds.org/).

=== "Kotlin"

    ```kotlin
    import java.nio.file.Files
    import java.nio.file.attribute.PosixFilePermission

    tasks.withType<AbstractArchiveTask>().configureEach {
      isPreserveFileTimestamps = false
      isReproducibleFileOrder = true

      eachFile {
        permissions {
          val isExec =
            Files.getPosixFilePermissions(file.toPath()).contains(PosixFilePermission.OWNER_EXECUTE)
          unix(if (isExec) "755" else "644")
        }
      }
      dirPermissions { unix("755") }
    }
    ```

=== "Groovy"

    ```groovy
    import java.nio.file.Files
    import java.nio.file.attribute.PosixFilePermission

    tasks.withType(AbstractArchiveTask).configureEach {
      preserveFileTimestamps = false
      reproducibleFileOrder = true

      eachFile {
          permissions {
              def isExec =
                      Files.getPosixFilePermissions(file.toPath()).contains(PosixFilePermission.OWNER_EXECUTE)
              unix(isExec ? '755' : '644')
          }
      }
      dirPermissions { unix('755') }
    }
    ```

One effect that this configuration will have is that the timestamps of all files in the JAR will be reset to a single
consistent value. If your code or any files being included into the JAR depend on the timestamps being set accurately
within the JAR, then this may not be the correct choice for you.

See
the [Reproducible archives section in Gradle's documentation](https://docs.gradle.org/4.9/userguide/working_with_files.html#sec:reproducible_archives)
for more information.
