diff --git a/.gitignore b/.gitignore index 207bc8a..11bb601 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,21 @@ # ignore "current" directories /**/current +# Gradle +.gradle/ +build/ +!gradle-wrapper.jar + # Qodo /.qodo + +# Gradle +.gradle/ +build/ +gradle-app.setting +*.class + +# Temporary files +bruno-build.gradle +bruno-settings.gradle +bruno-gradlew.bat diff --git a/.gradle-docs/API.md b/.gradle-docs/API.md new file mode 100644 index 0000000..99f5089 --- /dev/null +++ b/.gradle-docs/API.md @@ -0,0 +1,830 @@ +# API Reference + +Complete API reference for the Bearsampp Module Ghostscript Gradle build system. + +--- + +## Table of Contents + +- [Build Script API](#build-script-api) +- [Helper Functions](#helper-functions) +- [Extension Points](#extension-points) +- [Properties API](#properties-api) +- [Task API](#task-api) + +--- + +## Build Script API + +### Project Configuration + +#### `group` + +**Type:** `String` +**Default:** `com.bearsampp.modules` +**Description:** Maven group ID for the project + +```groovy +group = 'com.bearsampp.modules' +``` + +--- + +#### `version` + +**Type:** `String` +**Default:** Value from `build.properties` +**Description:** Project version + +```groovy +version = buildProps.getProperty('bundle.release', '1.0.0') +``` + +--- + +#### `description` + +**Type:** `String` +**Default:** Generated from bundle name +**Description:** Project description + +```groovy +description = "Bearsampp Module - ${buildProps.getProperty('bundle.name', 'ghostscript')}" +``` + +--- + +### Extension Properties + +#### `ext.projectBasedir` + +**Type:** `String` +**Description:** Absolute path to project directory + +```groovy +ext.projectBasedir = projectDir.absolutePath +``` + +--- + +#### `ext.rootDir` + +**Type:** `String` +**Description:** Absolute path to parent directory + +```groovy +ext.rootDir = projectDir.parent +``` + +--- + +#### `ext.devPath` + +**Type:** `String` +**Description:** Absolute path to dev directory + +```groovy +ext.devPath = file("${rootDir}/dev").absolutePath +``` + +--- + +#### `ext.bundleName` + +**Type:** `String` +**Default:** `ghostscript` +**Description:** Name of the bundle from build.properties + +```groovy +ext.bundleName = buildProps.getProperty('bundle.name', 'ghostscript') +``` + +--- + +#### `ext.bundleRelease` + +**Type:** `String` +**Default:** `1.0.0` +**Description:** Release version from build.properties + +```groovy +ext.bundleRelease = buildProps.getProperty('bundle.release', '1.0.0') +``` + +--- + +#### `ext.bundleType` + +**Type:** `String` +**Default:** `tools` +**Description:** Bundle type from build.properties + +```groovy +ext.bundleType = buildProps.getProperty('bundle.type', 'tools') +``` + +--- + +#### `ext.bundleFormat` + +**Type:** `String` +**Default:** `7z` +**Description:** Archive format from build.properties + +```groovy +ext.bundleFormat = buildProps.getProperty('bundle.format', '7z') +``` + +--- + +#### `ext.buildBasePath` + +**Type:** `String` +**Description:** Base path for build output (configurable via build.properties, environment variable, or default) + +```groovy +def buildPathFromProps = buildProps.getProperty('build.path', '').trim() +def buildPathFromEnv = System.getenv('BEARSAMPP_BUILD_PATH') ?: '' +def defaultBuildPath = "${rootDir}/bearsampp-build" + +ext.buildBasePath = buildPathFromProps ?: (buildPathFromEnv ?: defaultBuildPath) +``` + +--- + +#### `ext.buildTmpPath` + +**Type:** `String` +**Description:** Absolute path to temporary build directory + +```groovy +ext.buildTmpPath = file("${buildBasePath}/tmp").absolutePath +``` + +--- + +#### `ext.bundleTmpBuildPath` + +**Type:** `String` +**Description:** Absolute path to bundle build directory + +```groovy +ext.bundleTmpBuildPath = file("${buildTmpPath}/bundles_build/${bundleType}/${bundleName}").absolutePath +``` + +--- + +#### `ext.bundleTmpPrepPath` + +**Type:** `String` +**Description:** Absolute path to bundle preparation directory + +```groovy +ext.bundleTmpPrepPath = file("${buildTmpPath}/bundles_prep/${bundleType}/${bundleName}").absolutePath +``` + +--- + +#### `ext.bundleTmpDownloadPath` + +**Type:** `String` +**Description:** Absolute path to download cache directory + +```groovy +ext.bundleTmpDownloadPath = file("${buildTmpPath}/downloads/${bundleName}").absolutePath +``` + +--- + +#### `ext.bundleTmpExtractPath` + +**Type:** `String` +**Description:** Absolute path to extraction directory + +```groovy +ext.bundleTmpExtractPath = file("${buildTmpPath}/extract/${bundleName}").absolutePath +``` + +--- + +## Helper Functions + +### `fetchModulesUntouchedProperties()` + +**Description:** Fetch ghostscript.properties from modules-untouched repository + +**Parameters:** None + +**Returns:** `Properties` - Properties object or null if fetch fails + +**Example:** + +```groovy +def props = fetchModulesUntouchedProperties() +if (props) { + def url = props.getProperty('10.05.1') +} +``` + +**Process:** +1. Construct URL to modules-untouched properties file +2. Download properties file +3. Parse and return Properties object +4. Return null on failure + +--- + +### `getModuleUntouched(String name, String version)` + +**Description:** Get Ghostscript module from modules-untouched repository (local or remote) + +**Parameters:** + +| Parameter | Type | Description | +|--------------|----------|--------------------------------------| +| `name` | String | Module name (ghostscript) | +| `version` | String | Version to retrieve | + +**Returns:** `File` - Directory containing Ghostscript files or null + +**Example:** + +```groovy +def ghostscriptDir = getModuleUntouched('ghostscript', '10.05.1') +if (ghostscriptDir) { + println "Found at: ${ghostscriptDir}" +} +``` + +**Process:** +1. Check local modules-untouched repository +2. If not found, check remote properties file +3. Download and extract if found remotely +4. Return directory or null + +--- + +### `getModuleUntouchedRemoteUrl(String name, String version)` + +**Description:** Get download URL from modules-untouched remote properties file + +**Parameters:** + +| Parameter | Type | Description | +|--------------|----------|--------------------------------------| +| `name` | String | Module name (ghostscript) | +| `version` | String | Version to retrieve | + +**Returns:** `String` - Download URL or null + +**Example:** + +```groovy +def url = getModuleUntouchedRemoteUrl('ghostscript', '10.05.1') +if (url) { + println "Download URL: ${url}" +} +``` + +--- + +### `downloadAndExtractFromUrl(String downloadUrl, String version, String name)` + +**Description:** Download and extract Ghostscript from URL + +**Parameters:** + +| Parameter | Type | Description | +|----------------|----------|--------------------------------------| +| `downloadUrl` | String | URL to download from | +| `version` | String | Version being downloaded | +| `name` | String | Module name | + +**Returns:** `File` - Directory containing extracted files + +**Example:** + +```groovy +def ghostscriptDir = downloadAndExtractFromUrl( + 'https://example.com/gs10.05.1.7z', + '10.05.1', + 'ghostscript' +) +``` + +**Process:** +1. Download archive from URL +2. Extract to temporary directory +3. Find Ghostscript directory in extracted files +4. Return directory + +--- + +### `downloadAndExtractGhostscript(String version, File destDir)` + +**Description:** Download and extract Ghostscript binaries (with fallback logic) + +**Parameters:** + +| Parameter | Type | Description | +|--------------|----------|--------------------------------------| +| `version` | String | Ghostscript version | +| `destDir` | File | Destination directory | + +**Returns:** `File` - Directory containing Ghostscript files + +**Example:** + +```groovy +def ghostscriptDir = downloadAndExtractGhostscript('10.05.1', file(bundleTmpExtractPath)) +``` + +**Process:** +1. Try modules-untouched repository (local) +2. Try modules-untouched repository (remote) +3. Try releases.properties +4. Download and extract +5. Return directory + +--- + +### `findGhostscriptDirectory(File extractPath)` + +**Description:** Find Ghostscript directory in extracted files + +**Parameters:** + +| Parameter | Type | Description | +|----------------|----------|--------------------------------------| +| `extractPath` | File | Directory to search | + +**Returns:** `File` - Ghostscript directory or null + +**Example:** + +```groovy +def ghostscriptDir = findGhostscriptDirectory(file("${bundleTmpExtractPath}/10.05.1")) +``` + +**Process:** +1. Check if extractPath itself contains gswin64c.exe or gswin32c.exe +2. Search top-level directories +3. Search one level deep +4. Return directory or null + +--- + +### `find7ZipExecutable()` + +**Description:** Find 7-Zip executable on system + +**Parameters:** None + +**Returns:** `String` - Path to 7z.exe or null + +**Example:** + +```groovy +def sevenZipPath = find7ZipExecutable() +if (sevenZipPath) { + println "7-Zip found at: ${sevenZipPath}" +} +``` + +**Process:** +1. Check 7Z_HOME environment variable +2. Check common installation paths +3. Check PATH environment variable +4. Return path or null + +--- + +### `generateHashFiles(File file)` + +**Description:** Generate hash files (MD5, SHA1, SHA256, SHA512) for archive + +**Parameters:** + +| Parameter | Type | Description | +|--------------|----------|--------------------------------------| +| `file` | File | File to generate hashes for | + +**Returns:** `void` + +**Example:** + +```groovy +generateHashFiles(file('bearsampp-ghostscript-10.05.1-2025.7.31.7z')) +``` + +**Process:** +1. Calculate MD5 hash +2. Calculate SHA1 hash +3. Calculate SHA256 hash +4. Calculate SHA512 hash +5. Write each hash to separate file + +--- + +### `calculateHash(File file, String algorithm)` + +**Description:** Calculate hash for file using specified algorithm + +**Parameters:** + +| Parameter | Type | Description | +|--------------|----------|--------------------------------------| +| `file` | File | File to hash | +| `algorithm` | String | Hash algorithm (MD5, SHA-1, SHA-256, SHA-512) | + +**Returns:** `String` - Hex-encoded hash + +**Example:** + +```groovy +def md5 = calculateHash(file('archive.7z'), 'MD5') +def sha256 = calculateHash(file('archive.7z'), 'SHA-256') +``` + +--- + +### `getAvailableVersions()` + +**Description:** Get list of available Ghostscript versions from bin/ and bin/archived/ + +**Parameters:** None + +**Returns:** `List` - List of version strings + +**Example:** + +```groovy +def versions = getAvailableVersions() +versions.each { version -> + println "Version: ${version}" +} +``` + +**Process:** +1. Scan bin/ directory +2. Scan bin/archived/ directory +3. Remove duplicates +4. Sort versions +5. Return list + +--- + +## Extension Points + +### Custom Task Registration + +Register custom tasks using Gradle's task API: + +```groovy +tasks.register('customTask') { + group = 'custom' + description = 'Custom task description' + + doLast { + // Task implementation + } +} +``` + +--- + +### Custom Validation + +Add custom validation tasks: + +```groovy +tasks.register('customValidation') { + group = 'verification' + description = 'Custom validation' + + doLast { + // Validation logic + } +} +``` + +--- + +### Custom Download Sources + +Override download behavior by modifying releases.properties or implementing custom download logic: + +```groovy +def customDownloadGhostscript(String version) { + // Custom download implementation +} +``` + +--- + +## Properties API + +### Project Properties + +Access via `project.findProperty()`: + +```groovy +def bundleVersion = project.findProperty('bundleVersion') +``` + +--- + +### Build Properties + +Access via loaded Properties object: + +```groovy +def buildProps = new Properties() +file('build.properties').withInputStream { buildProps.load(it) } + +def bundleName = buildProps.getProperty('bundle.name') +def bundleRelease = buildProps.getProperty('bundle.release') +``` + +--- + +### System Properties + +Access via `System.getProperty()`: + +```groovy +def javaHome = System.getProperty('java.home') +def javaVersion = System.getProperty('java.version') +``` + +--- + +### Environment Variables + +Access via `System.getenv()`: + +```groovy +def buildPath = System.getenv('BEARSAMPP_BUILD_PATH') +def sevenZipHome = System.getenv('7Z_HOME') +``` + +--- + +## Task API + +### Task Registration + +```groovy +tasks.register('taskName') { + group = 'groupName' + description = 'Task description' + + doFirst { + // Executed first + } + + doLast { + // Executed last + } +} +``` + +--- + +### Task Dependencies + +```groovy +tasks.register('taskB') { + dependsOn 'taskA' + + doLast { + // Executed after taskA + } +} +``` + +--- + +### Task Configuration + +```groovy +tasks.named('existingTask') { + // Configure existing task + doLast { + // Add additional action + } +} +``` + +--- + +## File API + +### File Operations + +```groovy +// Create file object +def file = file('path/to/file') + +// Check existence +if (file.exists()) { } + +// Create directory +file.mkdirs() + +// Delete file/directory +delete file + +// Copy files +copy { + from 'source' + into 'destination' + include '*.exe' + exclude 'doc/**' +} +``` + +--- + +### Archive Operations + +```groovy +// Extract ZIP +copy { + from zipTree('archive.zip') + into 'destination' +} + +// Create 7z archive +def command = [ + sevenZipExe, + 'a', + '-t7z', + archiveFile.absolutePath, + '.' +] +def process = new ProcessBuilder(command) + .directory(sourceDir) + .redirectErrorStream(true) + .start() +``` + +--- + +## Exec API + +### Execute Command + +```groovy +def process = new ProcessBuilder(['command', 'arg1', 'arg2']) + .directory(workingDir) + .redirectErrorStream(true) + .start() + +process.inputStream.eachLine { line -> + println line +} + +def exitCode = process.waitFor() +``` + +--- + +### PowerShell Execution + +```groovy +def command = ['powershell', '-Command', 'Get-Date'] +def process = new ProcessBuilder(command) + .redirectErrorStream(true) + .start() + +def output = process.inputStream.text +``` + +--- + +## Logger API + +### Logging Levels + +```groovy +logger.error('Error message') +logger.warn('Warning message') +logger.lifecycle('Lifecycle message') +logger.quiet('Quiet message') +logger.info('Info message') +logger.debug('Debug message') +``` + +--- + +## Exception API + +### Throw Exception + +```groovy +throw new GradleException('Error message') +``` + +--- + +## Examples + +### Example 1: Custom Download Task + +```groovy +tasks.register('downloadGhostscript') { + group = 'download' + description = 'Download Ghostscript version' + + doLast { + def version = project.findProperty('gsVersion') + if (!version) { + throw new GradleException('gsVersion property required') + } + + def ghostscriptDir = downloadAndExtractGhostscript( + version, + file(bundleTmpExtractPath) + ) + println "Downloaded to: ${ghostscriptDir}" + } +} +``` + +--- + +### Example 2: Custom Validation Task + +```groovy +tasks.register('validateGhostscript') { + group = 'verification' + description = 'Validate Ghostscript installation' + + doLast { + def versions = getAvailableVersions() + + versions.each { version -> + def binDir = file("bin/ghostscript${version}") + if (!binDir.exists()) { + binDir = file("bin/archived/ghostscript${version}") + } + + def gsExe64 = file("${binDir}/bin/gswin64c.exe") + def gsExe32 = file("${binDir}/bin/gswin32c.exe") + + if (!gsExe64.exists() && !gsExe32.exists()) { + throw new GradleException("No Ghostscript executable found for version ${version}") + } + + println "[PASS] ${version}" + } + + println '[SUCCESS] All versions validated' + } +} +``` + +--- + +### Example 3: Custom Info Task + +```groovy +tasks.register('ghostscriptInfo') { + group = 'help' + description = 'Display Ghostscript version information' + + doLast { + def versions = getAvailableVersions() + + println 'Ghostscript Versions:' + println '-'.multiply(60) + + versions.each { version -> + def binDir = file("bin/ghostscript${version}") + def location = 'bin' + + if (!binDir.exists()) { + binDir = file("bin/archived/ghostscript${version}") + location = 'bin/archived' + } + + def gsExe64 = file("${binDir}/bin/gswin64c.exe") + def gsExe32 = file("${binDir}/bin/gswin32c.exe") + + def arch = gsExe64.exists() ? '64-bit' : '32-bit' + def size = (gsExe64.exists() ? gsExe64.length() : gsExe32.length()) / 1024 / 1024 + + println " ${version.padRight(15)} [${location}] ${arch} ${String.format('%.2f', size)} MB" + } + + println '-'.multiply(60) + println "Total versions: ${versions.size()}" + } +} +``` + +--- + +**Last Updated**: 2025-01-31 +**Version**: 2025.7.31 diff --git a/.gradle-docs/CONFIGURATION.md b/.gradle-docs/CONFIGURATION.md new file mode 100644 index 0000000..e4e928c --- /dev/null +++ b/.gradle-docs/CONFIGURATION.md @@ -0,0 +1,441 @@ +# Configuration Guide + +Complete configuration guide for the Bearsampp Module Ghostscript Gradle build system. + +--- + +## Table of Contents + +- [Configuration Files](#configuration-files) +- [Build Properties](#build-properties) +- [Gradle Properties](#gradle-properties) +- [Ghostscript Version Configuration](#ghostscript-version-configuration) +- [Environment Variables](#environment-variables) +- [Build Path Configuration](#build-path-configuration) + +--- + +## Configuration Files + +### Overview + +| File | Purpose | Format | Location | +|-----------------------|------------------------------------------|------------|---------------| +| `build.properties` | Main build configuration | Properties | Root | +| `gradle.properties` | Gradle-specific settings | Properties | Root | +| `settings.gradle` | Gradle project settings | Groovy | Root | +| `build.gradle` | Main build script | Groovy | Root | +| `releases.properties` | Available Ghostscript releases | Properties | Root | + +--- + +## Build Properties + +### File: `build.properties` + +**Location:** `E:/Bearsampp-development/module-ghostscript/build.properties` + +**Purpose:** Main build configuration for the Ghostscript module + +### Properties + +| Property | Type | Required | Default | Description | +|-------------------|----------|----------|-----------------|--------------------------------------| +| `bundle.name` | String | Yes | `ghostscript` | Name of the bundle | +| `bundle.release` | String | Yes | - | Release version (YYYY.MM.DD) | +| `bundle.type` | String | Yes | `tools` | Type of bundle | +| `bundle.format` | String | Yes | `7z` | Archive format for output | +| `build.path` | String | No | - | Custom build output path | + +### Example + +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +#build.path = C:/Bearsampp-build +``` + +### Usage in Build Script + +```groovy +def buildProps = new Properties() +file('build.properties').withInputStream { buildProps.load(it) } + +def bundleName = buildProps.getProperty('bundle.name', 'ghostscript') +def bundleRelease = buildProps.getProperty('bundle.release', '1.0.0') +``` + +--- + +## Gradle Properties + +### File: `gradle.properties` + +**Location:** `E:/Bearsampp-development/module-ghostscript/gradle.properties` + +**Purpose:** Gradle-specific configuration and JVM settings + +### Properties + +| Property | Type | Default | Description | +|-------------------------------|----------|--------------|--------------------------------------| +| `org.gradle.daemon` | Boolean | `true` | Enable Gradle daemon | +| `org.gradle.parallel` | Boolean | `true` | Enable parallel task execution | +| `org.gradle.caching` | Boolean | `true` | Enable build caching | +| `org.gradle.jvmargs` | String | - | JVM arguments for Gradle | +| `org.gradle.configureondemand`| Boolean | `false` | Configure projects on demand | + +### Example + +```properties +# Gradle daemon configuration +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true + +# JVM settings +org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError + +# Configure on demand +org.gradle.configureondemand=false +``` + +### Performance Tuning + +| Setting | Recommended Value | Purpose | +|-------------------------------|-------------------|--------------------------------------| +| `org.gradle.daemon` | `true` | Faster builds with daemon | +| `org.gradle.parallel` | `true` | Parallel task execution | +| `org.gradle.caching` | `true` | Cache task outputs | +| `org.gradle.jvmargs` | `-Xmx2g` | Allocate 2GB heap for Gradle | + +--- + +## Ghostscript Version Configuration + +### Directory Structure + +Each Ghostscript version has its own directory in `bin/` or `bin/archived/`: + +``` +bin/ +├── ghostscript10.05.1/ +│ ├── bin/ +│ │ ├── gswin64c.exe +│ │ └── ... +│ ├── bearsampp.conf +│ └── update_cidfmap.bat +└── archived/ + ├── ghostscript9.22/ + ├── ghostscript9.56.1/ + ├── ghostscript10.0/ + ├── ghostscript10.02.0/ + ├── ghostscript10.03.0/ + ├── ghostscript10.03.1/ + ├── ghostscript10.04.0/ + └── ghostscript10.05.0/ +``` + +### Version Naming Convention + +| Pattern | Example | Description | +|-------------------------------|----------------------|--------------------------------------| +| `ghostscript{major}.{minor}.{patch}` | `ghostscript10.05.1` | Standard Ghostscript version format | +| `ghostscript{major}.{minor}` | `ghostscript10.0` | Version without patch number | + +### Required Files + +Each version directory should contain: + +| File/Directory | Required | Description | +|-----------------------|----------|--------------------------------------| +| `bin/gswin64c.exe` | Yes* | 64-bit Ghostscript executable | +| `bin/gswin32c.exe` | Yes* | 32-bit Ghostscript executable | +| `bearsampp.conf` | No | Bearsampp configuration file | +| `update_cidfmap.bat` | No | CID font map update script | + +*At least one of gswin64c.exe or gswin32c.exe must be present + +--- + +## Build Path Configuration + +### Build Path Priority + +The build system determines the output path using the following priority: + +| Priority | Source | Description | +|----------|-----------------------------------------|--------------------------------------| +| 1 | `build.path` in build.properties | Explicit path in config file | +| 2 | `BEARSAMPP_BUILD_PATH` env variable | Environment variable override | +| 3 | `../bearsampp-build` | Default relative path | + +### Example Configurations + +**Option 1: Use default path** +```properties +# build.properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +# No build.path specified - uses ../bearsampp-build +``` + +**Option 2: Specify custom path in build.properties** +```properties +# build.properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +build.path = C:/Bearsampp-build +``` + +**Option 3: Use environment variable** +```bash +# Set environment variable +set BEARSAMPP_BUILD_PATH=D:/CustomBuildPath + +# build.properties (no build.path specified) +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +``` + +### Output Directory Structure + +``` +bearsampp-build/ +├── tmp/ +│ ├── bundles_prep/ +│ │ └── tools/ +│ │ └── ghostscript/ +│ │ └── ghostscript10.05.1/ +│ ├── bundles_build/ +│ │ └── tools/ +│ │ └── ghostscript/ +│ │ └── ghostscript10.05.1/ +│ ├── downloads/ +│ │ └── ghostscript/ +│ └── extract/ +│ └── ghostscript/ +└── tools/ + └── ghostscript/ + └── 2025.7.31/ + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.md5 + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.sha1 + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.sha256 + └── bearsampp-ghostscript-10.05.1-2025.7.31.7z.sha512 +``` + +--- + +## Environment Variables + +### Build Environment + +| Variable | Description | Example | +|-------------------|--------------------------------------|--------------------------------------| +| `JAVA_HOME` | Java installation directory | `C:\Program Files\Java\jdk-11` | +| `GRADLE_HOME` | Gradle installation directory | `C:\Gradle\gradle-8.5` | +| `PATH` | System path (includes Java, Gradle) | - | +| `7Z_HOME` | 7-Zip installation directory | `C:\Program Files\7-Zip` | + +### Optional Variables + +| Variable | Description | Default | +|---------------------------|--------------------------------------|--------------------------------------| +| `BEARSAMPP_BUILD_PATH` | Custom build output path | `../bearsampp-build` | +| `GRADLE_USER_HOME` | Gradle user home directory | `~/.gradle` | +| `GRADLE_OPTS` | Additional Gradle JVM options | - | + +--- + +## Releases Configuration + +### File: `releases.properties` + +**Location:** `E:/Bearsampp-development/module-ghostscript/releases.properties` + +**Purpose:** Define download URLs for Ghostscript versions + +### Format + +```properties +{version}={download_url} +``` + +### Example + +```properties +9.22=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs922/gs922w64.exe +9.56.1=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs9561/gs9561w64.exe +10.0=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs1000/gs1000w64.exe +10.02.0=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs1002/gs1002w64.exe +10.03.0=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs1003/gs1003w64.exe +10.03.1=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10031/gs10031w64.exe +10.04.0=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs1004/gs1004w64.exe +10.05.0=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs1005/gs1005w64.exe +10.05.1=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10051/gs10051w64.exe +``` + +### Download Priority + +When building a version, the system follows this priority: + +1. **Local bin/ directory**: Check `bin/ghostscript{version}/` +2. **Local bin/archived/ directory**: Check `bin/archived/ghostscript{version}/` +3. **modules-untouched repository**: Download from remote properties file +4. **releases.properties**: Download from local configuration + +--- + +## Configuration Examples + +### Example 1: Basic Configuration + +**build.properties:** +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +``` + +**Result:** +- Output path: `../bearsampp-build/tools/ghostscript/2025.7.31/` +- Archive format: 7z +- Uses default build path + +--- + +### Example 2: Custom Build Path + +**build.properties:** +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +build.path = C:/Bearsampp-build +``` + +**Result:** +- Output path: `C:/Bearsampp-build/tools/ghostscript/2025.7.31/` +- Archive format: 7z +- Uses custom build path + +--- + +### Example 3: ZIP Format + +**build.properties:** +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = zip +``` + +**Result:** +- Output path: `../bearsampp-build/tools/ghostscript/2025.7.31/` +- Archive format: zip +- Uses default build path + +--- + +## Configuration Validation + +### Validate Configuration + +```bash +# Validate build.properties +gradle validateProperties + +# Verify entire environment +gradle verify + +# List available versions +gradle listVersions + +# List available releases +gradle listReleases + +# Check modules-untouched integration +gradle checkModulesUntouched +``` + +### Validation Checklist + +| Item | Command | Expected Result | +|---------------------------|----------------------------------|------------------------------| +| Build properties | `gradle validateProperties` | All required properties set | +| Environment | `gradle verify` | All checks pass | +| Versions | `gradle listVersions` | Versions listed | +| Releases | `gradle listReleases` | Releases listed | +| modules-untouched | `gradle checkModulesUntouched` | Integration working | + +--- + +## Best Practices + +### Configuration Management + +1. **Version Control:** Keep all `.properties` files in version control +2. **Documentation:** Document custom configurations +3. **Validation:** Always run `gradle verify` after configuration changes +4. **Testing:** Test builds with new configurations before committing +5. **Backup:** Keep backups of working configurations + +### Version Management + +1. **Naming:** Use consistent version naming (ghostscript{version}) +2. **Organization:** Keep current versions in `bin/`, archived in `bin/archived/` +3. **Documentation:** Document version-specific configurations +4. **Testing:** Test each version after adding +5. **Cleanup:** Archive old versions regularly + +### Performance Optimization + +1. **Gradle Daemon:** Enable for faster builds +2. **Parallel Execution:** Enable for multi-core systems +3. **Build Cache:** Enable for incremental builds +4. **JVM Heap:** Allocate sufficient memory (2GB+) +5. **Network:** Use fast, reliable network for downloads +6. **Caching:** Downloaded files are cached in `bearsampp-build/tmp/` + +--- + +## Troubleshooting + +### Common Issues + +**Issue: Build path not found** +``` +Solution: Check build.path in build.properties or set BEARSAMPP_BUILD_PATH +``` + +**Issue: 7-Zip not found** +``` +Solution: Install 7-Zip and set 7Z_HOME environment variable +``` + +**Issue: Version not found** +``` +Solution: Check bin/ and bin/archived/ directories, or add to releases.properties +``` + +**Issue: Download failed** +``` +Solution: Check network connection and URL in releases.properties +``` + +--- + +**Last Updated**: 2025-01-31 +**Version**: 2025.7.31 diff --git a/.gradle-docs/INDEX.md b/.gradle-docs/INDEX.md new file mode 100644 index 0000000..bada769 --- /dev/null +++ b/.gradle-docs/INDEX.md @@ -0,0 +1,390 @@ +# Documentation Index + +Complete index of all Gradle build documentation for Bearsampp Module Ghostscript. + +--- + +## Quick Links + +| Document | Description | Link | +|-----------------------|--------------------------------------------------|-------------------------------| +| **Main Documentation**| Complete build system guide | [README.md](README.md) | +| **Task Reference** | All available Gradle tasks | [TASKS.md](TASKS.md) | +| **Configuration** | Configuration files and properties | [CONFIGURATION.md](CONFIGURATION.md) | +| **API Reference** | Build script API and helper functions | [API.md](API.md) | +| **Migration Guide** | Ant to Gradle migration guide | [MIGRATION.md](MIGRATION.md) | + +--- + +## Documentation Structure + +``` +.gradle-docs/ +├── INDEX.md # This file - Documentation index +├── README.md # Main documentation and quick start +├── TASKS.md # Complete task reference +├── CONFIGURATION.md # Configuration guide +├── API.md # API reference for build scripts +└── MIGRATION.md # Ant to Gradle migration guide +``` + +--- + +## Getting Started + +### New Users + +1. **Start Here**: [README.md](README.md) - Overview and quick start +2. **Verify Setup**: Run `gradle verify` to check environment +3. **List Tasks**: Run `gradle tasks` to see available tasks +4. **Build Release**: Run `gradle release -PbundleVersion=10.05.1` + +### Migrating from Ant + +1. **Migration Guide**: [MIGRATION.md](MIGRATION.md) - Complete migration guide +2. **Command Mapping**: See command equivalents in migration guide +3. **File Changes**: Understand what changed from Ant to Gradle +4. **Troubleshooting**: Common migration issues and solutions + +### Advanced Users + +1. **Task Reference**: [TASKS.md](TASKS.md) - All tasks with examples +2. **Configuration**: [CONFIGURATION.md](CONFIGURATION.md) - Advanced configuration +3. **API Reference**: [API.md](API.md) - Build script API and extensions +4. **Custom Tasks**: Create custom tasks using API reference + +--- + +## Documentation by Topic + +### Build System + +| Topic | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Overview | README.md | Overview | +| Quick Start | README.md | Quick Start | +| Installation | README.md | Installation | +| Architecture | README.md | Architecture | + +### Tasks + +| Topic | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Build Tasks | TASKS.md | Build Tasks | +| Verification Tasks | TASKS.md | Verification Tasks | +| Information Tasks | TASKS.md | Information Tasks | +| Task Examples | TASKS.md | Task Examples | + +### Configuration + +| Topic | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Build Properties | CONFIGURATION.md | Build Properties | +| Gradle Properties | CONFIGURATION.md | Gradle Properties | +| Ghostscript Versions | CONFIGURATION.md | Ghostscript Version Configuration| +| Build Path | CONFIGURATION.md | Build Path Configuration | +| Releases | CONFIGURATION.md | Releases Configuration | + +### API + +| Topic | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Build Script API | API.md | Build Script API | +| Helper Functions | API.md | Helper Functions | +| Extension Points | API.md | Extension Points | +| Properties API | API.md | Properties API | +| Task API | API.md | Task API | + +### Migration + +| Topic | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Overview | MIGRATION.md | Overview | +| What Changed | MIGRATION.md | What Changed | +| Command Mapping | MIGRATION.md | Command Mapping | +| File Changes | MIGRATION.md | File Changes | +| Troubleshooting | MIGRATION.md | Troubleshooting | + +--- + +## Common Tasks + +### Building + +| Task | Document | Reference | +|-------------------------------------------|---------------|----------------------------------| +| Build a release | README.md | Quick Start | +| Build specific version | TASKS.md | release task | +| Build all versions | TASKS.md | releaseAll task | +| Clean build artifacts | TASKS.md | clean task | + +### Configuration + +| Task | Document | Reference | +|-------------------------------------------|---------------|----------------------------------| +| Configure build properties | CONFIGURATION.md | Build Properties | +| Configure build path | CONFIGURATION.md | Build Path Configuration | +| Configure releases | CONFIGURATION.md | Releases Configuration | + +### Verification + +| Task | Document | Reference | +|-------------------------------------------|---------------|----------------------------------| +| Verify build environment | TASKS.md | verify task | +| Validate properties | TASKS.md | validateProperties task | +| Check modules-untouched | TASKS.md | checkModulesUntouched task | + +### Information + +| Task | Document | Reference | +|-------------------------------------------|---------------|----------------------------------| +| Display build info | TASKS.md | info task | +| List available versions | TASKS.md | listVersions task | +| List available releases | TASKS.md | listReleases task | + +--- + +## Quick Reference + +### Essential Commands + +```bash +# Display build information +gradle info + +# List all available tasks +gradle tasks + +# Verify build environment +gradle verify + +# Build a release (interactive) +gradle release + +# Build a specific version (non-interactive) +gradle release -PbundleVersion=10.05.1 + +# Build all versions +gradle releaseAll + +# Clean build artifacts +gradle clean +``` + +### Essential Files + +| File | Purpose | +|-----------------------|------------------------------------------| +| `build.gradle` | Main Gradle build script | +| `settings.gradle` | Gradle project settings | +| `build.properties` | Build configuration | +| `gradle.properties` | Gradle-specific settings | +| `releases.properties` | Available Ghostscript releases | + +### Essential Directories + +| Directory | Purpose | +|----------------------------|------------------------------------------| +| `bin/` | Ghostscript version bundles | +| `bin/archived/` | Archived Ghostscript versions | +| `bearsampp-build/tmp/` | Temporary build files (external) | +| `bearsampp-build/tools/` | Final packaged archives (external) | +| `.gradle-docs/` | Gradle documentation | + +--- + +## Search by Keyword + +### A-C + +| Keyword | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| API | API.md | All sections | +| Architecture | README.md | Architecture | +| Build | TASKS.md | Build Tasks | +| Clean | TASKS.md | clean task | +| Configuration | CONFIGURATION.md | All sections | + +### D-G + +| Keyword | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Download | TASKS.md | Download Behavior | +| Files | CONFIGURATION.md | Configuration Files | +| Ghostscript | README.md | All sections | +| Gradle | README.md | All sections | + +### H-M + +| Keyword | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Helper Functions | API.md | Helper Functions | +| Info | TASKS.md | info task | +| Installation | README.md | Installation | +| Migration | MIGRATION.md | All sections | +| modules-untouched | TASKS.md | checkModulesUntouched task | + +### P-R + +| Keyword | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Properties | CONFIGURATION.md | Build Properties | +| Release | TASKS.md | release task | +| releaseAll | TASKS.md | releaseAll task | + +### S-Z + +| Keyword | Document | Section | +|-----------------------|-----------------------|----------------------------------| +| Tasks | TASKS.md | All sections | +| Troubleshooting | README.md, MIGRATION.md | Troubleshooting sections | +| Validation | TASKS.md | Verification Tasks | +| Verify | TASKS.md | verify task | +| Versions | TASKS.md | listVersions task | + +--- + +## Document Summaries + +### README.md + +**Purpose**: Main documentation and quick start guide + +**Contents**: +- Overview of the Gradle build system +- Quick start guide with basic commands +- Installation instructions +- Complete task reference +- Configuration overview +- Architecture and build process flow +- Troubleshooting common issues +- Migration guide summary + +**Target Audience**: All users, especially new users + +--- + +### TASKS.md + +**Purpose**: Complete reference for all Gradle tasks + +**Contents**: +- Build tasks (release, releaseAll, clean) +- Verification tasks (verify, validateProperties, checkModulesUntouched) +- Information tasks (info, listVersions, listReleases) +- Task dependencies and execution order +- Task examples and usage patterns +- Task options and properties +- Download behavior and caching + +**Target Audience**: Developers and build engineers + +--- + +### CONFIGURATION.md + +**Purpose**: Configuration guide for build system + +**Contents**: +- Configuration files overview +- Build properties reference +- Gradle properties reference +- Ghostscript version configuration +- Build path configuration +- Releases configuration +- Environment variables +- Configuration examples +- Best practices +- Troubleshooting + +**Target Audience**: Build engineers and advanced users + +--- + +### API.md + +**Purpose**: API reference for build scripts + +**Contents**: +- Build script API +- Helper functions reference +- Extension points +- Properties API +- Task API +- File operations API +- Exec API +- Logger API +- Exception handling +- API examples + +**Target Audience**: Advanced users and contributors + +--- + +### MIGRATION.md + +**Purpose**: Guide for migrating from Ant to Gradle + +**Contents**: +- Migration overview +- What changed from Ant to Gradle +- Command mapping (Ant to Gradle) +- File changes +- Configuration changes +- Task equivalents +- Troubleshooting migration issues +- Benefits of migration +- Next steps for developers, CI/CD, and contributors + +**Target Audience**: Users migrating from Ant build system + +--- + +## Version History + +| Version | Date | Changes | +|---------------|------------|------------------------------------------| +| 2025.7.31 | 2025-01-31 | Initial Gradle documentation | +| | | - Created README.md | +| | | - Created TASKS.md | +| | | - Created CONFIGURATION.md | +| | | - Created API.md | +| | | - Created MIGRATION.md | +| | | - Created INDEX.md | + +--- + +## Contributing + +To contribute to the documentation: + +1. **Fork Repository**: Fork the module-ghostscript repository +2. **Edit Documentation**: Make changes to documentation files +3. **Follow Style**: Maintain consistent formatting and style +4. **Test Examples**: Verify all code examples work +5. **Submit PR**: Create pull request with changes + +### Documentation Style Guide + +- Use Markdown formatting +- Include code examples +- Use tables for structured data +- Add links to related sections +- Keep language clear and concise +- Include practical examples + +--- + +## Support + +For documentation issues or questions: + +- **GitHub Issues**: https://github.com/bearsampp/module-ghostscript/issues +- **Bearsampp Issues**: https://github.com/bearsampp/bearsampp/issues +- **Documentation**: This directory (.gradle-docs/) + +--- + +**Last Updated**: 2025-01-31 +**Version**: 2025.7.31 +**Total Documents**: 6 diff --git a/.gradle-docs/MIGRATION.md b/.gradle-docs/MIGRATION.md new file mode 100644 index 0000000..1219e83 --- /dev/null +++ b/.gradle-docs/MIGRATION.md @@ -0,0 +1,443 @@ +# Migration Guide: Ant to Gradle + +Complete guide for migrating from the legacy Ant build system to the new pure Gradle build. + +--- + +## Table of Contents + +- [Overview](#overview) +- [What Changed](#what-changed) +- [Command Mapping](#command-mapping) +- [File Changes](#file-changes) +- [Configuration Changes](#configuration-changes) +- [Task Equivalents](#task-equivalents) +- [Troubleshooting](#troubleshooting) +- [Benefits](#benefits) +- [Next Steps](#next-steps) + +--- + +## Overview + +The Bearsampp Module Ghostscript project has been fully migrated from Apache Ant to Gradle. This migration provides: + +- **Modern Build System** - Native Gradle tasks and conventions +- **Better Performance** - Incremental builds and caching +- **Simplified Maintenance** - Pure Groovy/Gradle DSL +- **Enhanced Tooling** - IDE integration and dependency management +- **Cross-Platform Support** - Works on Windows, Linux, and macOS + +> **⚠️ Critical**: This project uses **system-installed Gradle only**. Apache Ant has been completely removed and Gradle Wrapper (gradlew/gradlew.bat) is not used. You must install Gradle 8.0+ on your system. + +### Migration Status + +| Component | Status | Notes | +|-----------------------|---------------|------------------------------------------| +| **Build Files** | ✅ Complete | Converted to build.gradle | +| **Release Process** | ✅ Complete | Native Gradle implementation | +| **Download Support** | ✅ Complete | modules-untouched integration | +| **Hash Generation** | ✅ Complete | MD5, SHA1, SHA256, SHA512 | +| **Interactive Mode** | ✅ Complete | Version selection menu | +| **Batch Build** | ✅ Complete | releaseAll task | +| **Documentation** | ✅ Complete | Comprehensive Gradle docs | + +--- + +## What Changed + +### Removed Files + +| File | Status | Replacement | +|-------------------|---------------|------------------------------------------| +| `build.xml` | ❌ Removed | `build.gradle` | + +### New Files + +| File | Purpose | +|-------------------------------|------------------------------------------| +| `build.gradle` | Main Gradle build script (pure Gradle) | +| `settings.gradle` | Gradle project settings | +| `.gradle-docs/README.md` | Main documentation | +| `.gradle-docs/TASKS.md` | Task reference | +| `.gradle-docs/CONFIGURATION.md` | Configuration guide | +| `.gradle-docs/API.md` | API reference | +| `.gradle-docs/MIGRATION.md` | This migration guide | +| `.gradle-docs/INDEX.md` | Documentation index | + +### Modified Files + +| File | Changes | +|-------------------|------------------------------------------| +| `README.md` | Updated with Gradle build information | +| `gradle.properties` | Enhanced with performance settings | + +--- + +## Command Mapping + +### Basic Commands + +| Ant Command | Gradle Command | Notes | +|----------------------------------------------------------|---------------------------------------------|--------------------------| +| `ant` | `gradle info` | Default task changed | +| `ant -projecthelp` | `gradle tasks` | List all tasks | +| `ant release.build -Dbundle.path=bin/ghostscript10.05.1` | `gradle release -PbundleVersion=10.05.1` | Build specific version | +| N/A | `gradle release` | Interactive mode (new) | +| N/A | `gradle releaseAll` | Build all versions (new) | +| `ant clean` | `gradle clean` | Clean artifacts | + +### Advanced Commands + +| Ant Command | Gradle Command | Notes | +|--------------------------------------|---------------------------------------------|--------------------------| +| `ant -v release.build` | `gradle release --info` | Verbose output | +| `ant -d release.build` | `gradle release --debug` | Debug output | +| `ant -k release.build` | `gradle release --continue` | Continue on failure | + +### New Commands (Gradle Only) + +| Command | Description | +|--------------------------------------|----------------------------------------------| +| `gradle verify` | Verify build environment | +| `gradle listVersions` | List available versions | +| `gradle listReleases` | List releases from properties | +| `gradle validateProperties` | Validate build.properties | +| `gradle checkModulesUntouched` | Check modules-untouched integration | +| `gradle info` | Display build information | + +--- + +## File Changes + +### build.xml → build.gradle + +#### Ant (build.xml) + +```xml + + + + + + + + + + +``` + +#### Gradle (build.gradle) + +```groovy +plugins { + id 'base' +} + +// Load build properties +def buildProps = new Properties() +file('build.properties').withInputStream { buildProps.load(it) } + +// Project configuration +group = 'com.bearsampp.modules' +version = buildProps.getProperty('bundle.release', '1.0.0') + +// Tasks +tasks.register('release') { + group = 'build' + description = 'Build release package' + + doLast { + // Pure Groovy implementation + } +} +``` + +### Key Differences + +| Aspect | Ant | Gradle | +|---------------------|------------------------------|----------------------------------| +| **Build File** | XML (build.xml) | Groovy DSL (build.gradle) | +| **Task Definition** | `` | `tasks.register('...')` | +| **Properties** | `` | `ext { ... }` | +| **Dependencies** | Manual downloads | Automatic with repositories | +| **Caching** | None | Built-in incremental builds | +| **IDE Support** | Limited | Excellent (IntelliJ, Eclipse) | + +--- + +## Configuration Changes + +### build.properties + +**No changes required** - The same build.properties file works with both Ant and Gradle. + +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +``` + +### gradle.properties + +**Enhanced** with performance settings: + +```properties +# Gradle daemon configuration +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true + +# JVM settings +org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m +``` + +### releases.properties + +**No changes required** - The same releases.properties file works with both Ant and Gradle. + +--- + +## Task Equivalents + +### Build Tasks + +| Ant Target | Gradle Task | Description | +|-----------------------|-----------------------|----------------------------------| +| `release.build` | `release` | Build release package | +| N/A | `releaseAll` | Build all versions (new) | +| `clean` | `clean` | Clean build artifacts | + +### Verification Tasks + +| Ant Target | Gradle Task | Description | +|-----------------------|-----------------------|----------------------------------| +| N/A | `verify` | Verify build environment (new) | +| N/A | `validateProperties` | Validate build.properties (new) | +| N/A | `checkModulesUntouched` | Check modules-untouched (new) | + +### Information Tasks + +| Ant Target | Gradle Task | Description | +|-----------------------|-----------------------|----------------------------------| +| N/A | `info` | Display build information (new) | +| N/A | `listVersions` | List available versions (new) | +| N/A | `listReleases` | List releases (new) | + +--- + +## Troubleshooting + +### Common Migration Issues + +#### Issue 1: Ant Commands Not Working + +**Problem:** +```bash +ant release.build +# Command not found or deprecated +``` + +**Solution:** +```bash +# Use Gradle instead +gradle release -PbundleVersion=10.05.1 +``` + +--- + +#### Issue 2: Build Path Changed + +**Problem:** +``` +Output directory structure is different +``` + +**Solution:** +Gradle uses the same output structure as Ant: +- `bearsampp-build/tmp/` - Temporary files +- `bearsampp-build/tools/ghostscript/{bundle.release}/` - Final archives + +--- + +#### Issue 3: Missing Gradle + +**Problem:** +```bash +gradle: command not found +``` + +**Solution:** +```bash +# Install Gradle 8.0+ +# Windows (Chocolatey): +choco install gradle + +# Or download from: https://gradle.org/install/ +``` + +--- + +#### Issue 4: Java Version Too Old + +**Problem:** +``` +Java 8+ required +``` + +**Solution:** +```bash +# Check Java version +java -version + +# Install Java 8 or higher +# Update JAVA_HOME environment variable +``` + +--- + +#### Issue 5: 7-Zip Not Found + +**Problem:** +``` +7-Zip not found +``` + +**Solution:** +```bash +# Install 7-Zip +# Set 7Z_HOME environment variable +set 7Z_HOME=C:\Program Files\7-Zip +``` + +--- + +### Migration Checklist + +- [ ] Install Gradle 8.0+ +- [ ] Install Java 8+ +- [ ] Install 7-Zip (if using 7z format) +- [ ] Run `gradle verify` to check environment +- [ ] Test build with `gradle release -PbundleVersion=10.05.1` +- [ ] Update CI/CD scripts to use Gradle commands +- [ ] Update documentation references +- [ ] Remove old Ant build files (optional) + +--- + +## Benefits + +### Performance Improvements + +| Feature | Ant | Gradle | Improvement | +|-----------------------|---------------|---------------|--------------| +| **Build Cache** | ❌ No | ✅ Yes | Faster rebuilds | +| **Incremental Builds**| ❌ No | ✅ Yes | Only rebuild changed files | +| **Parallel Execution**| ❌ No | ✅ Yes | Faster multi-version builds | +| **Daemon** | ❌ No | ✅ Yes | Faster startup | + +### Feature Enhancements + +| Feature | Ant | Gradle | Notes | +|-----------------------|---------------|---------------|--------------| +| **Interactive Mode** | ❌ No | ✅ Yes | Version selection menu | +| **Batch Build** | ❌ No | ✅ Yes | Build all versions | +| **Download Support** | ❌ Limited | ✅ Full | modules-untouched integration | +| **Hash Generation** | ❌ No | ✅ Yes | MD5, SHA1, SHA256, SHA512 | +| **Verification** | �� No | ✅ Yes | Environment checks | +| **IDE Integration** | ❌ Limited | ✅ Excellent | IntelliJ, Eclipse, VS Code | + +### Maintenance Benefits + +| Aspect | Ant | Gradle | Notes | +|-----------------------|---------------|---------------|--------------| +| **Code Clarity** | XML | Groovy DSL | More readable | +| **Modularity** | Limited | Excellent | Reusable functions | +| **Testing** | Manual | Built-in | Task testing | +| **Documentation** | Limited | Comprehensive | Full docs | +| **Community** | Declining | Active | Better support | + +--- + +## Next Steps + +### For Developers + +1. **Learn Gradle Basics** + - Read [README.md](.gradle-docs/README.md) + - Review [TASKS.md](.gradle-docs/TASKS.md) + - Explore [CONFIGURATION.md](.gradle-docs/CONFIGURATION.md) + +2. **Update Workflows** + - Replace Ant commands with Gradle equivalents + - Update build scripts + - Test new build process + +3. **Explore New Features** + - Try interactive mode: `gradle release` + - Use batch build: `gradle releaseAll` + - Check environment: `gradle verify` + +### For CI/CD + +1. **Update Build Scripts** + ```bash + # Old (Ant) + ant release.build -Dbundle.path=bin/ghostscript10.05.1 + + # New (Gradle) + gradle release -PbundleVersion=10.05.1 + ``` + +2. **Add Verification Step** + ```bash + gradle verify + ``` + +3. **Enable Caching** + ```bash + # In CI/CD configuration + gradle release -PbundleVersion=10.05.1 --build-cache + ``` + +### For Contributors + +1. **Read Documentation** + - [API.md](.gradle-docs/API.md) - Build script API + - [CONFIGURATION.md](.gradle-docs/CONFIGURATION.md) - Configuration guide + +2. **Understand Build Process** + - Review build.gradle + - Study helper functions + - Test custom tasks + +3. **Contribute Improvements** + - Add new tasks + - Improve documentation + - Report issues + +--- + +## Additional Resources + +- [Gradle Documentation](https://docs.gradle.org/) +- [Bearsampp Project](https://github.com/bearsampp/bearsampp) +- [Ghostscript Downloads](https://www.ghostscript.com/releases/) +- [modules-untouched Repository](https://github.com/Bearsampp/modules-untouched) + +--- + +## Support + +For migration help: + +- **GitHub Issues**: https://github.com/bearsampp/module-ghostscript/issues +- **Bearsampp Issues**: https://github.com/bearsampp/bearsampp/issues +- **Documentation**: [.gradle-docs/](.gradle-docs/) + +--- + +**Last Updated**: 2025-01-31 +**Version**: 2025.7.31 +**Migration Status**: ✅ Complete diff --git a/.gradle-docs/README.md b/.gradle-docs/README.md new file mode 100644 index 0000000..7a1dfb4 --- /dev/null +++ b/.gradle-docs/README.md @@ -0,0 +1,621 @@ +# Bearsampp Module Ghostscript - Gradle Build Documentation + +## Table of Contents + +- [Overview](#overview) +- [Quick Start](#quick-start) +- [Installation](#installation) +- [Build Tasks](#build-tasks) +- [Configuration](#configuration) +- [Architecture](#architecture) +- [Troubleshooting](#troubleshooting) +- [Migration Guide](#migration-guide) + +--- + +## Overview + +The Bearsampp Module Ghostscript project has been converted to a **pure Gradle build system**, replacing the legacy Ant build configuration. This provides: + +- **Modern Build System** - Native Gradle tasks and conventions +- **Better Performance** - Incremental builds and caching +- **Simplified Maintenance** - Pure Groovy/Gradle DSL +- **Enhanced Tooling** - IDE integration and dependency management +- **Cross-Platform Support** - Works on Windows, Linux, and macOS + +> **⚠️ Important Note**: This project uses **system-installed Gradle only**. Neither Apache Ant nor Gradle Wrapper (gradlew/gradlew.bat) are used or supported. You must install Gradle 8.0+ on your system before building. + +### Project Information + +| Property | Value | +|-------------------|------------------------------------------| +| **Project Name** | module-ghostscript | +| **Group** | com.bearsampp.modules | +| **Type** | Ghostscript Module Builder | +| **Build Tool** | Gradle 8.x+ | +| **Language** | Groovy (Gradle DSL) | + +--- + +## Quick Start + +### Prerequisites + +| Requirement | Version | Purpose | +|-------------------|---------------|------------------------------------------| +| **Java** | 8+ | Required for Gradle execution | +| **Gradle** | 8.0+ | Build automation tool | +| **7-Zip** | Latest | Archive extraction and creation | + +### Basic Commands + +```bash +# Display build information +gradle info + +# List all available tasks +gradle tasks + +# Verify build environment +gradle verify + +# Build a release (interactive) +gradle release + +# Build a specific version (non-interactive) +gradle release -PbundleVersion=10.05.1 + +# Build all versions +gradle releaseAll + +# Clean build artifacts +gradle clean +``` + +--- + +## Installation + +### 1. Clone the Repository + +```bash +git clone https://github.com/bearsampp/module-ghostscript.git +cd module-ghostscript +``` + +### 2. Verify Environment + +```bash +gradle verify +``` + +This will check: +- Java version (8+) +- Required files (build.properties, releases.properties) +- Directory structure (bin/, bin/archived/) +- Build dependencies +- 7-Zip availability (if format=7z) + +### 3. List Available Versions + +```bash +gradle listVersions +``` + +### 4. Build Your First Release + +```bash +# Interactive mode (prompts for version) +gradle release + +# Or specify version directly +gradle release -PbundleVersion=10.05.1 +``` + +--- + +## Build Tasks + +### Core Build Tasks + +| Task | Description | Example | +|-----------------------|--------------------------------------------------|------------------------------------------| +| `release` | Build and package release (interactive/non-interactive) | `gradle release -PbundleVersion=10.05.1` | +| `releaseAll` | Build all available versions | `gradle releaseAll` | +| `clean` | Clean build artifacts and temporary files | `gradle clean` | + +### Verification Tasks + +| Task | Description | Example | +|---------------------------|----------------------------------------------|----------------------------------------------| +| `verify` | Verify build environment and dependencies | `gradle verify` | +| `validateProperties` | Validate build.properties configuration | `gradle validateProperties` | +| `checkModulesUntouched` | Check modules-untouched integration | `gradle checkModulesUntouched` | + +### Information Tasks + +| Task | Description | Example | +|---------------------|--------------------------------------------------|----------------------------| +| `info` | Display build configuration information | `gradle info` | +| `listVersions` | List available bundle versions in bin/ | `gradle listVersions` | +| `listReleases` | List all available releases from properties | `gradle listReleases` | + +### Task Groups + +| Group | Purpose | +|------------------|--------------------------------------------------| +| **build** | Build and package tasks | +| **verification** | Verification and validation tasks | +| **help** | Help and information tasks | + +--- + +## Configuration + +### build.properties + +The main configuration file for the build: + +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +#build.path = C:/Bearsampp-build +``` + +| Property | Description | Example Value | +|-------------------|--------------------------------------|----------------| +| `bundle.name` | Name of the bundle | `ghostscript` | +| `bundle.release` | Release version | `2025.7.31` | +| `bundle.type` | Type of bundle | `tools` | +| `bundle.format` | Archive format | `7z` | +| `build.path` | Custom build output path (optional) | `C:/Bearsampp-build` | + +### gradle.properties + +Gradle-specific configuration: + +```properties +# Gradle daemon configuration +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true + +# JVM settings +org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m +``` + +### Directory Structure + +``` +module-ghostscript/ +├── .gradle-docs/ # Gradle documentation +│ ├── README.md # Main documentation (this file) +│ ├── TASKS.md # Task reference +│ ├── CONFIGURATION.md # Configuration guide +│ ├── API.md # API reference +│ ├── MIGRATION.md # Migration guide +│ └── INDEX.md # Documentation index +├── bin/ # Ghostscript version bundles +│ ├── ghostscript10.05.1/ +│ └── archived/ +│ ├── ghostscript9.22/ +│ ├── ghostscript9.56.1/ +│ └── ... +├── bearsampp-build/ # External build directory (outside repo) +│ ├── tmp/ # Temporary build files +│ │ ├── bundles_prep/tools/ghostscript/ +│ │ ├── bundles_build/tools/ghostscript/ +│ │ ├── downloads/ghostscript/ +│ │ └── extract/ghostscript/ +│ └── tools/ghostscript/ # Final packaged archives +│ └── 2025.7.31/ +│ ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z +│ ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.md5 +│ └── ... +├── build.gradle # Main Gradle build script +├── settings.gradle # Gradle settings +├── build.properties # Build configuration +└── releases.properties # Available Ghostscript releases +``` + +--- + +## Architecture + +### Build Process Flow + +``` +1. User runs: gradle release -PbundleVersion=10.05.1 + ↓ +2. Validate environment and version + ↓ +3. Check for local bundle in bin/ or bin/archived/ + ↓ +4. If not found, download from: + - modules-untouched repository (remote) + - releases.properties (fallback) + ↓ +5. Create preparation directory (tmp/prep/) + ↓ +6. Copy Ghostscript files (excluding docs/examples) + ↓ +7. Create gs.exe from gswin64c.exe or gswin32c.exe + ↓ +8. Copy configuration files (bearsampp.conf, update_cidfmap.bat) + ↓ +9. Output prepared bundle to tmp/prep/ + ↓ +10. Package prepared folder into archive in bearsampp-build/tools/ghostscript/{bundle.release}/ + - The archive includes the top-level folder: ghostscript{version}/ +``` + +### Packaging Details + +- **Archive name format**: `bearsampp-ghostscript-{version}-{bundle.release}.{7z|zip}` +- **Location**: `bearsampp-build/tools/ghostscript/{bundle.release}/` + - Example: `bearsampp-build/tools/ghostscript/2025.7.31/bearsampp-ghostscript-10.05.1-2025.7.31.7z` +- **Content root**: The top-level folder inside the archive is `ghostscript{version}/` (e.g., `ghostscript10.05.1/`) +- **Structure**: The archive contains the Ghostscript version folder at the root with all files inside + +**Archive Structure Example**: +``` +bearsampp-ghostscript-10.05.1-2025.7.31.7z +└── ghostscript10.05.1/ ← Version folder at root + ├── bin/ + │ ├── gswin64c.exe + │ ├── gs.exe + │ └── ... + ├── bearsampp.conf + ├── update_cidfmap.bat + └── ... +``` + +**Hash Files**: Each archive is accompanied by hash sidecar files: +- `.md5` - MD5 checksum +- `.sha1` - SHA-1 checksum +- `.sha256` - SHA-256 checksum +- `.sha512` - SHA-512 checksum + +### Download Priority + +When building a version, the system follows this priority: + +1. **Local bin/ directory**: Check `bin/ghostscript{version}/` +2. **Local bin/archived/ directory**: Check `bin/archived/ghostscript{version}/` +3. **modules-untouched repository**: Download from remote properties file +4. **releases.properties**: Download from local configuration + +Downloaded files are cached in `bearsampp-build/tmp/downloads/` and `bearsampp-build/tmp/extract/`. + +--- + +## Troubleshooting + +### Common Issues + +#### Issue: "Dev path not found" + +**Symptom:** +``` +Dev path not found: E:/Bearsampp-development/dev +``` + +**Solution:** +This is a warning only. The dev path is optional for most tasks. If you need it, ensure the `dev` project exists in the parent directory. + +--- + +#### Issue: "Bundle version not found" + +**Symptom:** +``` +Bundle version not found: E:/Bearsampp-development/module-ghostscript/bin/ghostscript10.05.99 +``` + +**Solution:** +1. List available versions: `gradle listVersions` +2. Use an existing version: `gradle release -PbundleVersion=10.05.1` +3. Or add the version to releases.properties for download + +--- + +#### Issue: "7-Zip not found" + +**Symptom:** +``` +7-Zip not found. Please install 7-Zip or set 7Z_HOME environment variable. +``` + +**Solution:** +1. Install 7-Zip from https://www.7-zip.org/ +2. Set 7Z_HOME environment variable: `set 7Z_HOME=C:\Program Files\7-Zip` + +--- + +#### Issue: "Java version too old" + +**Symptom:** +``` +Java 8+ required +``` + +**Solution:** +1. Check Java version: `java -version` +2. Install Java 8 or higher +3. Update JAVA_HOME environment variable + +--- + +### Debug Mode + +Run Gradle with debug output: + +```bash +gradle release -PbundleVersion=10.05.1 --info +gradle release -PbundleVersion=10.05.1 --debug +``` + +### Clean Build + +If you encounter issues, try a clean build: + +```bash +gradle clean +gradle release -PbundleVersion=10.05.1 +``` + +--- + +## Migration Guide + +### From Ant to Gradle + +The project has been fully migrated from Ant to Gradle. Here's what changed: + +#### Removed Files + +| File | Status | Replacement | +|-------------------|-----------|----------------------------| +| `build.xml` | ❌ Removed | `build.gradle` | + +#### Command Mapping + +| Ant Command | Gradle Command | +|----------------------------------------------------------|---------------------------------------------| +| `ant release.build -Dbundle.path=bin/ghostscript10.05.1` | `gradle release -PbundleVersion=10.05.1` | +| N/A | `gradle release` (interactive) | +| N/A | `gradle releaseAll` | +| `ant clean` | `gradle clean` | + +#### Key Differences + +| Aspect | Ant | Gradle | +|---------------------|------------------------------|----------------------------------| +| **Build File** | XML (build.xml) | Groovy DSL (build.gradle) | +| **Task Definition** | `` | `tasks.register('...')` | +| **Properties** | `` | `ext { ... }` | +| **Caching** | None | Built-in incremental builds | +| **IDE Support** | Limited | Excellent (IntelliJ, Eclipse) | + +For complete migration guide, see [MIGRATION.md](MIGRATION.md) + +--- + +## Additional Resources + +- **Complete Documentation**: [INDEX.md](INDEX.md) - Documentation index +- **Task Reference**: [TASKS.md](TASKS.md) - All available tasks +- **Configuration Guide**: [CONFIGURATION.md](CONFIGURATION.md) - Configuration details +- **API Reference**: [API.md](API.md) - Build script API +- **Migration Guide**: [MIGRATION.md](MIGRATION.md) - Ant to Gradle migration +- **Gradle Documentation**: https://docs.gradle.org/ +- **Bearsampp Project**: https://github.com/bearsampp/bearsampp +- **Ghostscript Downloads**: https://www.ghostscript.com/releases/ + +--- + +## Support + +For issues and questions: + +- **GitHub Issues**: https://github.com/bearsampp/module-ghostscript/issues +- **Bearsampp Issues**: https://github.com/bearsampp/bearsampp/issues +- **Documentation**: https://bearsampp.com/module/ghostscript + +--- + +**Last Updated**: 2025-01-31 +**Version**: 2025.7.31 +**Build System**: Pure Gradle (no wrapper, no Ant) + +Notes: +- This project deliberately does not ship the Gradle Wrapper. Install Gradle 8+ locally and run with `gradle ...`. +- Legacy Ant files have been removed and replaced with pure Gradle implementation. + +## 🚀 Quick Start + +### Prerequisites + +| Requirement | Version | Description | +|----------------------|--------------|------------------------------------------| +| Java | 8 or higher | Required for Gradle execution | +| Gradle | 8.5+ | Must be installed on your system | +| 7-Zip | Latest | Required for .7z archive creation | + +### Basic Commands + +```bash +# Verify environment +gradle verify + +# List available versions +gradle listVersions + +# Build a specific version +gradle release -PbundleVersion=10.05.1 + +# Build interactively (select from menu) +gradle release + +# Build all versions +gradle releaseAll + +# Display build info +gradle info + +# List all tasks +gradle tasks +``` + +## 📖 Getting Started + +1. **First Time Setup**: Read [GRADLE_SETUP.md](GRADLE_SETUP.md) +2. **Quick Reference**: See [GRADLE_README.md](GRADLE_README.md) +3. **Complete Guide**: Read [GRADLE_BUILD.md](GRADLE_BUILD.md) +4. **Migration from Ant**: See [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) + +## 🔄 Build System + +This project uses a **pure Gradle build system**. The Ant build has been removed. + +### Key Features + +| Feature | Description | +|----------------------------|------------------------------------------------------------------| +| Interactive Mode | Run `gradle release` to select version from menu | +| Archived Folder Support | Detects versions in both `bin/` and `bin/archived/` | +| Download Support | Automatically downloads missing binaries | +| Hash Generation | Generates MD5, SHA1, SHA256, SHA512 hash files | +| Build Cache | Faster incremental builds with Gradle's build cache | +| Better Error Messages | Clear error messages with actionable suggestions | + +### Command Comparison + +| Ant Command (Removed) | Gradle Command | Description | +|----------------------------------------------------------|---------------------------------------------|--------------------------------| +| `ant release.build -Dbundle.path=bin/ghostscript10.05.1` | `gradle release -PbundleVersion=10.05.1` | Build specific version | +| N/A | `gradle release` | Interactive mode | +| N/A | `gradle releaseAll` | Build all versions | +| `ant clean` | `gradle clean` | Clean build artifacts | + +## 📁 Project Structure + +``` +module-ghostscript/ +├── .gradle-docs/ # Documentation (you are here) +│ ├── README.md # This file +│ ├── GRADLE_README.md # Quick reference +│ ├── GRADLE_BUILD.md # Complete build guide +│ ├── GRADLE_SETUP.md # Setup instructions +│ └── ... # Additional documentation +├── bin/ # Bundle versions +│ ├── ghostscript10.05.1/ # Current version +│ └── archived/ # Archived versions +├── build.gradle # Main Gradle build script +├── settings.gradle # Gradle project settings +├── build.properties # Bundle configuration +└── releases.properties # Download URLs for versions +``` + +## 🔧 Configuration + +### build.properties + +```properties +bundle.name = ghostscript +bundle.release = 2025.7.31 +bundle.type = tools +bundle.format = 7z +#build.path = C:/Bearsampp-build +``` + +### Build Path Priority + +| Priority | Source | Description | +|----------|-----------------------------------------|--------------------------------------| +| 1 | `build.path` in build.properties | Explicit path in config file | +| 2 | `BEARSAMPP_BUILD_PATH` env variable | Environment variable override | +| 3 | `../bearsampp-build` | Default relative path | + +## 📦 Output Structure + +``` +bearsampp-build/ +└── tools/ + └── ghostscript/ + └── 2025.7.31/ + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.md5 + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.sha1 + ├── bearsampp-ghostscript-10.05.1-2025.7.31.7z.sha256 + └── bearsampp-ghostscript-10.05.1-2025.7.31.7z.sha512 +``` + +## 🧪 Testing + +Run the automated test script: +```bash +test-gradle-build.bat +``` + +Or test manually: +```bash +gradle verify +gradle listVersions +gradle release -PbundleVersion=10.05.1 +``` + +## 🐛 Troubleshooting + +### Common Issues + +| Issue | Solution | +|--------------------------|---------------------------------------------------------------| +| Gradle Not Found | Install Gradle from https://gradle.org/install/ | +| 7-Zip Not Found | Install 7-Zip and set `7Z_HOME` environment variable | +| Dev Directory Not Found | Ensure `dev` project exists in parent directory | +| Java Not Found | Install Java 8+ and set `JAVA_HOME` environment variable | + +### Verification + +```bash +# Check environment +gradle verify + +# Check Gradle version +gradle --version + +# Check Java version +java -version +``` + +## 📝 Notes + +- **Pure Gradle Build**: Ant build system has been removed +- **No Wrapper**: Uses system-installed Gradle (no wrapper) +- **Backward Compatible**: Output identical to previous Ant builds +- **Enhanced Features**: Additional functionality beyond Ant +- **Production Ready**: Fully tested and ready for use + +## 🆘 Support + +For help: + +1. Run `gradle tasks` to see all available tasks +2. Run `gradle info` to see build configuration +3. Check the documentation files listed above +4. Run `gradle verify` to check your environment + +## ✅ Status + +**Status:** ✅ Production Ready + +The Gradle build is fully tested and ready for production use. All Ant functionality has been preserved and enhanced with additional features. + +--- + +**Documentation Version:** 2025.7.31 +**Last Updated:** 2025 +**Build System:** Pure Gradle (Ant removed) diff --git a/.gradle-docs/TASKS.md b/.gradle-docs/TASKS.md new file mode 100644 index 0000000..a2a91ea --- /dev/null +++ b/.gradle-docs/TASKS.md @@ -0,0 +1,537 @@ +# Gradle Tasks Reference + +Complete reference for all available Gradle tasks in the Bearsampp Module Ghostscript project. + +> **⚠️ Important**: All commands use **system-installed Gradle** (e.g., `gradle `). Neither Apache Ant nor Gradle Wrapper (gradlew/gradlew.bat) are used in this project. + +--- + +## Table of Contents + +- [Build Tasks](#build-tasks) +- [Verification Tasks](#verification-tasks) +- [Information Tasks](#information-tasks) +- [Task Dependencies](#task-dependencies) +- [Task Examples](#task-examples) + +--- + +## Build Tasks + +### `release` + +**Group:** build +**Description:** Build release package. Interactive by default; non-interactive when `-PbundleVersion` is provided. + +**Usage:** +```bash +# Interactive mode (default — prompts for version) +gradle release + +# Non-interactive (build specific version) +gradle release -PbundleVersion=10.05.1 +``` + +**Parameters:** + +| Parameter | Type | Required | Description | Example | +|-------------------|----------|----------|--------------------------------|--------------| +| `bundleVersion` | String | No | Ghostscript version to build | `10.05.1` | + +**Process:** +1. Validates environment and version +2. Checks for local bundle in `bin/` or `bin/archived/` +3. If not found locally, downloads from modules-untouched or releases.properties +4. Creates preparation directory +5. Copies Ghostscript files (excluding docs and examples) +6. Creates `gs.exe` from `gswin64c.exe` or `gswin32c.exe` +7. Copies configuration files (bearsampp.conf, update_cidfmap.bat) +8. Outputs prepared bundle to `bearsampp-build/tmp/bundles_prep/tools/ghostscript/` +9. Packages into archive in `bearsampp-build/tools/ghostscript/{bundle.release}/` + +**Output Locations:** +- Prepared folder: `bearsampp-build/tmp/bundles_prep/tools/ghostscript/ghostscript{version}/` +- Build folder: `bearsampp-build/tmp/bundles_build/tools/ghostscript/ghostscript{version}/` +- Final archive: `bearsampp-build/tools/ghostscript/{bundle.release}/bearsampp-ghostscript-{version}-{bundle.release}.{7z|zip}` + +--- + +### `releaseAll` + +**Group:** build +**Description:** Build release packages for all available versions in bin/ and bin/archived/ directories + +**Usage:** +```bash +gradle releaseAll +``` + +**Process:** +- Discovers all versions in `bin/` and `bin/archived/` +- Builds each version sequentially +- Provides summary of successful and failed builds + +**Output:** +``` +Building releases for 9 ghostscript versions +======================================================================= +[1/9] Building ghostscript 9.22... +[SUCCESS] ghostscript 9.22 completed +... +======================================================================= +Build Summary +======================================================================= +Total versions: 9 +Successful: 9 +Failed: 0 +======================================================================= +[SUCCESS] All versions built successfully! +``` + +--- + +### `clean` + +**Group:** build +**Description:** Clean build artifacts and temporary files + +**Usage:** +```bash +gradle clean +``` + +**Cleans:** +- `build/` directory +- All temporary build files + +**Output:** +``` +[SUCCESS] Build artifacts cleaned +``` + +--- + +## Verification Tasks + +### `verify` + +**Group:** verification +**Description:** Verify build environment and dependencies + +**Usage:** +```bash +gradle verify +``` + +**Checks:** + +| Check | Description | Required | +|------------------------|------------------------------------------|----------| +| Java 8+ | Java version 8 or higher | Yes | +| build.properties | Build configuration file exists | Yes | +| releases.properties | Release definitions file exists | Yes | +| dev directory | Dev project directory exists | Yes | +| bin directory | Ghostscript versions directory exists | Yes | +| bin/archived directory | Archived versions directory exists | Yes | +| 7-Zip | 7-Zip executable available (if format=7z)| Conditional | + +**Output:** +``` +Environment Check Results: +------------------------------------------------------------ + [PASS] Java 8+ + [PASS] build.properties + [PASS] releases.properties + [PASS] dev directory + [PASS] bin directory + [PASS] bin/archived directory + [PASS] 7-Zip +------------------------------------------------------------ + +[SUCCESS] All checks passed! Build environment is ready. + +You can now run: + gradle release -PbundleVersion=10.05.1 - Build release for version + gradle listVersions - List available versions +``` + +--- + +### `validateProperties` + +**Group:** verification +**Description:** Validate build.properties configuration + +**Usage:** +```bash +gradle validateProperties +``` + +**Validates:** + +| Property | Required | Description | +|-------------------|----------|--------------------------------| +| `bundle.name` | Yes | Name of the bundle | +| `bundle.release` | Yes | Release version | +| `bundle.type` | Yes | Type of bundle | +| `bundle.format` | Yes | Archive format | + +**Output:** +``` +[SUCCESS] All required properties are present: + bundle.name = ghostscript + bundle.release = 2025.7.31 + bundle.type = tools + bundle.format = 7z +``` + +--- + +### `checkModulesUntouched` + +**Group:** verification +**Description:** Check modules-untouched repository integration and available versions + +**Usage:** +```bash +gradle checkModulesUntouched +``` + +**Output:** +``` +======================================================================= +Modules-Untouched Integration Check +======================================================================= + +Repository URL: + https://raw.githubusercontent.com/Bearsampp/modules-untouched/main/modules/ghostscript.properties + +Fetching ghostscript.properties from modules-untouched... + +======================================================================= +Available Versions in modules-untouched +======================================================================= + 9.22 + 9.56.1 + 10.0 + 10.02.0 + 10.03.0 + 10.03.1 + 10.04.0 + 10.05.0 + 10.05.1 +======================================================================= +Total versions: 9 + +======================================================================= +[SUCCESS] modules-untouched integration is working +======================================================================= + +Version Resolution Strategy: + 1. Check modules-untouched ghostscript.properties (remote) + 2. Check local releases.properties (fallback) + 3. Construct standard URL format (fallback) +``` + +--- + +## Information Tasks + +### `info` + +**Group:** help +**Description:** Display build configuration information + +**Usage:** +```bash +gradle info +``` + +**Displays:** +- Project information (name, version, description) +- Bundle properties (name, release, type, format) +- Paths (project dir, root dir, dev path, build paths) +- Java information (version, home) +- Gradle information (version, home) +- Available task groups +- Quick start commands + +**Output:** +``` +================================================================ + Bearsampp Module Ghostscript - Build Info +================================================================ + +Project: module-ghostscript +Version: 2025.7.31 +Description: Bearsampp Module - ghostscript + +Bundle Properties: + Name: ghostscript + Release: 2025.7.31 + Type: tools + Format: 7z + +Paths: + Project Dir: E:/Bearsampp-development/module-ghostscript + Root Dir: E:/Bearsampp-development + Dev Path: E:/Bearsampp-development/dev + Build Base: E:/Bearsampp-development/bearsampp-build + ... + +Quick Start: + gradle tasks - List all available tasks + gradle info - Show this information + gradle release -PbundleVersion=10.05.1 - Build specific version + gradle releaseAll - Build all versions + gradle clean - Clean build artifacts + gradle verify - Verify build environment +``` + +--- + +### `listVersions` + +**Group:** help +**Description:** List all available bundle versions in bin/ and bin/archived/ directories + +**Usage:** +```bash +gradle listVersions +``` + +**Output:** +``` +Available ghostscript versions: +------------------------------------------------------------ + 9.22 [bin/archived] + 9.56.1 [bin/archived] + 10.0 [bin/archived] + 10.02.0 [bin/archived] + 10.03.0 [bin/archived] + 10.03.1 [bin/archived] + 10.04.0 [bin/archived] + 10.05.0 [bin/archived] + 10.05.1 [bin] +------------------------------------------------------------ +Total versions: 9 + +To build a specific version: + gradle release -PbundleVersion=10.05.1 +``` + +--- + +### `listReleases` + +**Group:** help +**Description:** List all available releases from modules-untouched or releases.properties + +**Usage:** +```bash +gradle listReleases +``` + +**Output:** +``` +Available Ghostscript Releases (modules-untouched): +-------------------------------------------------------------------------------- + 9.22 -> https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs922/gs922w64.exe + 9.56.1 -> https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs9561/gs9561w64.exe + 10.0 -> https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs1000/gs1000w64.exe + ... +-------------------------------------------------------------------------------- +Total releases: 9 +``` + +--- + +## Task Dependencies + +### Task Execution Order + +``` +release + ├── (validates environment) + ├── (checks local bin/ or bin/archived/) + ├── (downloads if needed from modules-untouched or releases.properties) + ├── (creates directories) + ├── (copies Ghostscript files) + ├── (creates gs.exe) + ├── (copies configuration files) + └── (packages into archive) + +releaseAll + └── (calls release for each version) +``` + +### Task Groups + +| Group | Tasks | +|------------------|----------------------------------------------------------------------------| +| **build** | `release`, `releaseAll`, `clean` | +| **verification** | `verify`, `validateProperties`, `checkModulesUntouched` | +| **help** | `info`, `listVersions`, `listReleases` | + +--- + +## Task Examples + +### Example 1: Complete Build Workflow + +```bash +# 1. Verify environment +gradle verify + +# 2. List available versions +gradle listVersions + +# 3. Check modules-untouched integration +gradle checkModulesUntouched + +# 4. Build a specific release +gradle release -PbundleVersion=10.05.1 + +# 5. Clean up +gradle clean +``` + +--- + +### Example 2: Build All Versions + +```bash +# Verify environment first +gradle verify + +# Build all versions +gradle releaseAll +``` + +--- + +### Example 3: Interactive Build + +```bash +# Run release without parameters for interactive mode +gradle release + +# Select version from menu: +# Available versions: +# 1. 9.22 [bin/archived] +# 2. 9.56.1 [bin/archived] +# 3. 10.0 [bin/archived] +# ... +# 9. 10.05.1 [bin] +# +# Enter version to build (index or exact version): +# 9 +``` + +--- + +### Example 4: Debugging a Build + +```bash +# Run with info logging +gradle release -PbundleVersion=10.05.1 --info + +# Run with debug logging +gradle release -PbundleVersion=10.05.1 --debug + +# Run with stack trace on error +gradle release -PbundleVersion=10.05.1 --stacktrace +``` + +--- + +### Example 5: Validation Workflow + +```bash +# Validate build properties +gradle validateProperties + +# Verify environment +gradle verify + +# Check modules-untouched integration +gradle checkModulesUntouched +``` + +--- + +### Example 6: Information Gathering + +```bash +# Get build info +gradle info + +# List all available versions +gradle listVersions + +# List all releases from modules-untouched +gradle listReleases +``` + +--- + +## Task Options + +### Common Gradle Options + +| Option | Description | Example | +|---------------------|------------------------------------------|------------------------------------------| +| `--info` | Set log level to INFO | `gradle release --info` | +| `--debug` | Set log level to DEBUG | `gradle release --debug` | +| `--stacktrace` | Print stack trace on error | `gradle release --stacktrace` | +| `--scan` | Create build scan | `gradle release --scan` | +| `--dry-run` | Show what would be executed | `gradle release --dry-run` | +| `--parallel` | Execute tasks in parallel | `gradle releaseAll --parallel` | +| `--offline` | Execute build without network access | `gradle release --offline` | + +--- + +## Task Properties + +### Project Properties + +Set via `-P` flag: + +| Property | Type | Description | Example | +|-------------------|----------|--------------------------------|------------------------------------------| +| `bundleVersion` | String | Ghostscript version to build | `-PbundleVersion=10.05.1` | + +### System Properties + +Set via `-D` flag: + +| Property | Type | Description | Example | +|-------------------|----------|--------------------------------|------------------------------------------| +| `org.gradle.daemon` | Boolean | Enable Gradle daemon | `-Dorg.gradle.daemon=true` | +| `org.gradle.parallel` | Boolean | Enable parallel execution | `-Dorg.gradle.parallel=true` | + +--- + +## Download Behavior + +### Source Priority + +When building a version, the system follows this priority: + +1. **Local bin/ directory**: Check `bin/ghostscript{version}/` +2. **Local bin/archived/ directory**: Check `bin/archived/ghostscript{version}/` +3. **modules-untouched repository**: Download from remote properties file +4. **releases.properties**: Download from local configuration + +### Caching + +Downloaded files are cached in: +- `bearsampp-build/tmp/downloads/ghostscript/` - Downloaded archives +- `bearsampp-build/tmp/extract/ghostscript/` - Extracted files + +Subsequent builds will use cached files if available. + +--- + +**Last Updated**: 2025-01-31 +**Version**: 2025.7.31 diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index b3c998e..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,13 +0,0 @@ -# Changelog - -## r3 (2017/09/03) - -* New release : 9.22 (Issue bearsampp/bearsampp#350) - -## r2 (2017/09/03) - -* Ghostscript exe not found by ImageMagick (Issue bearsampp/bearsampp#319) - -## r1 (2017/07/23) - -* Initial version with release 9.21 (Issue bearsampp/bearsampp#220) diff --git a/README.md b/README.md index 50d407e..4df5221 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,64 @@ This is a module of [Bearsampp project](https://github.com/bearsampp/bearsampp) involving Ghostscript. -## Documentation and downloads +## Build System -https://bearsampp.com/module/ghostscript +This project uses **Gradle** as its build system. The legacy Ant build has been fully replaced with a modern, pure Gradle implementation. + +> **Important**: This project uses **system-installed Gradle** only. Neither Ant nor Gradle Wrapper (gradlew) are used. You must have Gradle 8.0+ installed on your system. + +### Quick Start + +```bash +# Display build information +gradle info + +# List all available tasks +gradle tasks + +# Verify build environment +gradle verify + +# Build a release (interactive) +gradle release + +# Build a specific version (non-interactive) +gradle release -PbundleVersion=10.05.1 + +# Clean build artifacts +gradle clean +``` + +### Prerequisites + +| Requirement | Version | Purpose | +|-------------------|---------------|------------------------------------------| +| **Java** | 8+ | Required for Gradle execution | +| **Gradle** | 8.0+ | Build automation tool | +| **7-Zip** | Latest | Archive extraction and creation | + +### Available Tasks + +| Task | Description | +|-----------------------|--------------------------------------------------| +| `release` | Build release package (interactive/non-interactive) | +| `releaseAll` | Build all available versions | +| `clean` | Clean build artifacts and temporary files | +| `verify` | Verify build environment and dependencies | +| `info` | Display build configuration information | +| `listVersions` | List available bundle versions in bin/ | +| `listReleases` | List available releases from properties | +| `validateProperties` | Validate build.properties configuration | + +For complete documentation, see [.gradle-docs/README.md](.gradle-docs/README.md) + +## Documentation + +- **Build Documentation**: [.gradle-docs/README.md](.gradle-docs/README.md) +- **Task Reference**: [.gradle-docs/TASKS.md](.gradle-docs/TASKS.md) +- **Configuration Guide**: [.gradle-docs/CONFIGURATION.md](.gradle-docs/CONFIGURATION.md) +- **API Reference**: [.gradle-docs/API.md](.gradle-docs/API.md) +- **Module Downloads**: https://bearsampp.com/module/ghostscript ## Issues diff --git a/bin/ghostscript10.0/bearsampp.conf b/bin/archived/ghostscript10.0/bearsampp.conf similarity index 100% rename from bin/ghostscript10.0/bearsampp.conf rename to bin/archived/ghostscript10.0/bearsampp.conf diff --git a/bin/ghostscript10.0/update_cidfmap.bat b/bin/archived/ghostscript10.0/update_cidfmap.bat similarity index 100% rename from bin/ghostscript10.0/update_cidfmap.bat rename to bin/archived/ghostscript10.0/update_cidfmap.bat diff --git a/bin/ghostscript10.02.0/bearsampp.conf b/bin/archived/ghostscript10.02.0/bearsampp.conf similarity index 100% rename from bin/ghostscript10.02.0/bearsampp.conf rename to bin/archived/ghostscript10.02.0/bearsampp.conf diff --git a/bin/ghostscript10.02.0/update_cidfmap.bat b/bin/archived/ghostscript10.02.0/update_cidfmap.bat similarity index 100% rename from bin/ghostscript10.02.0/update_cidfmap.bat rename to bin/archived/ghostscript10.02.0/update_cidfmap.bat diff --git a/bin/ghostscript10.03.0/bearsampp.conf b/bin/archived/ghostscript10.03.0/bearsampp.conf similarity index 100% rename from bin/ghostscript10.03.0/bearsampp.conf rename to bin/archived/ghostscript10.03.0/bearsampp.conf diff --git a/bin/ghostscript10.03.0/update_cidfmap.bat b/bin/archived/ghostscript10.03.0/update_cidfmap.bat similarity index 100% rename from bin/ghostscript10.03.0/update_cidfmap.bat rename to bin/archived/ghostscript10.03.0/update_cidfmap.bat diff --git a/bin/ghostscript10.03.1/bearsampp.conf b/bin/archived/ghostscript10.03.1/bearsampp.conf similarity index 100% rename from bin/ghostscript10.03.1/bearsampp.conf rename to bin/archived/ghostscript10.03.1/bearsampp.conf diff --git a/bin/ghostscript10.03.1/update_cidfmap.bat b/bin/archived/ghostscript10.03.1/update_cidfmap.bat similarity index 100% rename from bin/ghostscript10.03.1/update_cidfmap.bat rename to bin/archived/ghostscript10.03.1/update_cidfmap.bat diff --git a/bin/ghostscript10.04.0/bearsampp.conf b/bin/archived/ghostscript10.04.0/bearsampp.conf similarity index 100% rename from bin/ghostscript10.04.0/bearsampp.conf rename to bin/archived/ghostscript10.04.0/bearsampp.conf diff --git a/bin/ghostscript10.04.0/update_cidfmap.bat b/bin/archived/ghostscript10.04.0/update_cidfmap.bat similarity index 100% rename from bin/ghostscript10.04.0/update_cidfmap.bat rename to bin/archived/ghostscript10.04.0/update_cidfmap.bat diff --git a/bin/ghostscript10.05.0/bearsampp.conf b/bin/archived/ghostscript10.05.0/bearsampp.conf similarity index 100% rename from bin/ghostscript10.05.0/bearsampp.conf rename to bin/archived/ghostscript10.05.0/bearsampp.conf diff --git a/bin/ghostscript10.05.0/update_cidfmap.bat b/bin/archived/ghostscript10.05.0/update_cidfmap.bat similarity index 100% rename from bin/ghostscript10.05.0/update_cidfmap.bat rename to bin/archived/ghostscript10.05.0/update_cidfmap.bat diff --git a/bin/ghostscript9.22/bearsampp.conf b/bin/archived/ghostscript9.22/bearsampp.conf similarity index 100% rename from bin/ghostscript9.22/bearsampp.conf rename to bin/archived/ghostscript9.22/bearsampp.conf diff --git a/bin/ghostscript9.22/update_cidfmap.bat b/bin/archived/ghostscript9.22/update_cidfmap.bat similarity index 97% rename from bin/ghostscript9.22/update_cidfmap.bat rename to bin/archived/ghostscript9.22/update_cidfmap.bat index fde947f..f3a58da 100644 --- a/bin/ghostscript9.22/update_cidfmap.bat +++ b/bin/archived/ghostscript9.22/update_cidfmap.bat @@ -1,4 +1,4 @@ -@ECHO OFF - -cd %~dp0 +@ECHO OFF + +cd %~dp0 bin\gswin32c.exe -q -dBATCH -sFONTDIR=c:/windows/fonts -sCIDFMAP=lib/cidfmap lib/mkcidfm.ps \ No newline at end of file diff --git a/bin/ghostscript9.56.1/bearsampp.conf b/bin/archived/ghostscript9.56.1/bearsampp.conf similarity index 100% rename from bin/ghostscript9.56.1/bearsampp.conf rename to bin/archived/ghostscript9.56.1/bearsampp.conf diff --git a/bin/ghostscript9.56.1/update_cidfmap.bat b/bin/archived/ghostscript9.56.1/update_cidfmap.bat similarity index 97% rename from bin/ghostscript9.56.1/update_cidfmap.bat rename to bin/archived/ghostscript9.56.1/update_cidfmap.bat index fde947f..f3a58da 100644 --- a/bin/ghostscript9.56.1/update_cidfmap.bat +++ b/bin/archived/ghostscript9.56.1/update_cidfmap.bat @@ -1,4 +1,4 @@ -@ECHO OFF - -cd %~dp0 +@ECHO OFF + +cd %~dp0 bin\gswin32c.exe -q -dBATCH -sFONTDIR=c:/windows/fonts -sCIDFMAP=lib/cidfmap lib/mkcidfm.ps \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..330852d --- /dev/null +++ b/build.gradle @@ -0,0 +1,1400 @@ +/* + * Bearsampp Module Ghostscript - Gradle Build + * + * This is a 100% Gradle build configuration for the Ghostscript module. + * It handles downloading, extracting, and packaging Ghostscript releases. + * + * Usage: + * gradle tasks - List all available tasks + * gradle release -PbundleVersion=10.05.1 - Build release for specific version + * gradle releaseAll - Build all versions + * gradle clean - Clean build artifacts + * gradle info - Display build information + * gradle verify - Verify build environment + * gradle listVersions - List available versions + * gradle listReleases - List releases from properties + */ + +plugins { + id 'base' +} + +// ============================================================================ +// PROJECT CONFIGURATION +// ============================================================================ + +// Load build properties +def buildProps = new Properties() +file('build.properties').withInputStream { buildProps.load(it) } + +// Project information +group = 'com.bearsampp.modules' +version = buildProps.getProperty('bundle.release', '1.0.0') +description = "Bearsampp Module - ${buildProps.getProperty('bundle.name', 'ghostscript')}" + +// Define project paths +ext { + projectBasedir = projectDir.absolutePath + rootDir = projectDir.parent + devPath = file("${rootDir}/dev").absolutePath + + // Bundle properties from build.properties + bundleName = buildProps.getProperty('bundle.name', 'ghostscript') + bundleRelease = buildProps.getProperty('bundle.release', '1.0.0') + bundleType = buildProps.getProperty('bundle.type', 'tools') + bundleFormat = buildProps.getProperty('bundle.format', '7z') + + // Build paths - with configurable base path + // Priority: 1) build.properties, 2) Environment variable, 3) Default + def buildPathFromProps = buildProps.getProperty('build.path', '').trim() + def buildPathFromEnv = System.getenv('BEARSAMPP_BUILD_PATH') ?: '' + def defaultBuildPath = "${rootDir}/bearsampp-build" + + buildBasePath = buildPathFromProps ?: (buildPathFromEnv ?: defaultBuildPath) + + // Use shared bearsampp-build/tmp directory structure (same as Ant builds) + buildTmpPath = file("${buildBasePath}/tmp").absolutePath + bundleTmpBuildPath = file("${buildTmpPath}/bundles_build/${bundleType}/${bundleName}").absolutePath + bundleTmpPrepPath = file("${buildTmpPath}/bundles_prep/${bundleType}/${bundleName}").absolutePath + bundleTmpSrcPath = file("${buildTmpPath}/bundles_src").absolutePath + + // Download and extract paths - use bearsampp-build/tmp instead of local build/ + bundleTmpDownloadPath = file("${buildTmpPath}/downloads/${bundleName}").absolutePath + bundleTmpExtractPath = file("${buildTmpPath}/extract/${bundleName}").absolutePath +} + +// Verify dev path exists +if (!file(ext.devPath).exists()) { + throw new GradleException("Dev path not found: ${ext.devPath}. Please ensure the 'dev' project exists in ${ext.rootDir}") +} + +// Configure repositories +repositories { + mavenCentral() +} + +// ============================================================================ +// HELPER FUNCTIONS +// ============================================================================ + +// Function to fetch modules-untouched properties file +def fetchModulesUntouchedProperties() { + def propertiesUrl = "https://raw.githubusercontent.com/Bearsampp/modules-untouched/main/modules/${bundleName}.properties" + + try { + def tempPropsFile = file("${buildTmpPath}/tmp-${bundleName}.properties") + tempPropsFile.parentFile.mkdirs() + + ant.get(src: propertiesUrl, dest: tempPropsFile, verbose: false, ignoreerrors: true) + + if (tempPropsFile.exists() && tempPropsFile.length() > 0) { + def props = new Properties() + tempPropsFile.withInputStream { props.load(it) } + tempPropsFile.delete() + return props + } + } catch (Exception e) { + // Silently fail + } + + return null +} + +// Function to get untouched module from modules-untouched repo (like Ant's getmoduleuntouched) +def getModuleUntouched(String name, String version) { + // First, check if modules-untouched repo exists locally + def modulesUntouchedPath = file("${rootDir}/modules-untouched") + + if (modulesUntouchedPath.exists()) { + // Look for the module in modules-untouched repo + def untouchedModulePath = file("${modulesUntouchedPath}/${name}/${name}${version}") + + if (untouchedModulePath.exists()) { + def ghostscriptExe64 = file("${untouchedModulePath}/bin/gswin64c.exe") + def ghostscriptExe32 = file("${untouchedModulePath}/bin/gswin32c.exe") + if (ghostscriptExe64.exists() || ghostscriptExe32.exists()) { + println "Found untouched module in local repository: ${untouchedModulePath}" + return untouchedModulePath + } + } + } + + // Second, try to download from modules-untouched remote properties file + println "Module not found in local modules-untouched, checking remote properties..." + def remoteUrl = getModuleUntouchedRemoteUrl(name, version) + if (remoteUrl) { + println "Found module in remote modules-untouched properties" + return downloadAndExtractFromUrl(remoteUrl, version, name) + } + + return null +} + +// Function to get download URL from modules-untouched remote properties file +def getModuleUntouchedRemoteUrl(String name, String version) { + def propertiesUrl = "https://raw.githubusercontent.com/Bearsampp/modules-untouched/main/modules/${name}.properties" + + try { + println " Checking: ${propertiesUrl}" + + // Download the properties file (store alongside other downloads like Bruno) + def tempPropsFile = file("${bundleTmpDownloadPath}/${name}-untouched.properties") + tempPropsFile.parentFile.mkdirs() + + ant.get(src: propertiesUrl, dest: tempPropsFile, verbose: false, ignoreerrors: true) + + if (tempPropsFile.exists() && tempPropsFile.length() > 0) { + def props = new Properties() + tempPropsFile.withInputStream { props.load(it) } + + def url = props.getProperty(version) + tempPropsFile.delete() + + if (url) { + println " Found version ${version} in remote properties" + return url + } else { + println " Version ${version} not found in remote properties" + } + } else { + println " Remote properties file not found or empty" + } + } catch (Exception e) { + println " Could not access remote properties: ${e.message}" + } + + return null +} + +// Function to download and extract from a URL +def downloadAndExtractFromUrl(String downloadUrl, String version, String name) { + println " Downloading from: ${downloadUrl}" + + // Determine filename from URL + def filename = downloadUrl.substring(downloadUrl.lastIndexOf('/') + 1) + def downloadDir = file(bundleTmpDownloadPath) + def extractDir = file(bundleTmpExtractPath) + downloadDir.mkdirs() + extractDir.mkdirs() + + def downloadedFile = file("${downloadDir}/${filename}") + + // Download if not already present + if (!downloadedFile.exists()) { + println " Downloading to: ${downloadedFile}" + ant.get(src: downloadUrl, dest: downloadedFile, verbose: true) + println " Download complete" + } else { + println " Using cached file: ${downloadedFile}" + } + + // Extract the archive + println " Extracting archive..." + def extractPath = file("${extractDir}/${version}") + if (extractPath.exists()) { + delete extractPath + } + extractPath.mkdirs() + + // Use 7zip or built-in extraction + if (filename.endsWith('.7z')) { + def sevenZipPath = find7ZipExecutable() + if (sevenZipPath) { + def command = [ + sevenZipPath.toString(), + 'x', + downloadedFile.absolutePath.toString(), + "-o${extractPath.absolutePath}".toString(), + '-y' + ] + def process = new ProcessBuilder(command as String[]) + .directory(extractPath) + .redirectErrorStream(true) + .start() + + process.inputStream.eachLine { line -> + if (line.trim()) println " ${line}" + } + + def exitCode = process.waitFor() + if (exitCode != 0) { + throw new GradleException("7zip extraction failed with exit code: ${exitCode}") + } + } else { + throw new GradleException("7zip not found. Please install 7zip or extract manually.") + } + } else if (filename.endsWith('.zip')) { + copy { + from zipTree(downloadedFile) + into extractPath + } + } else { + throw new GradleException("Unsupported archive format: ${filename}") + } + + println " Extraction complete" + + // Find the module directory in the extracted files + def moduleDir = findGhostscriptDirectory(extractPath) + if (!moduleDir) { + throw new GradleException("Could not find ${name} directory in extracted files") + } + + println " Found ${name} directory: ${moduleDir.name}" + return moduleDir +} + +// Function to download and extract Ghostscript binaries +def downloadAndExtractGhostscript(String version, File destDir) { + // First, try to get from modules-untouched repository (like Ant build) + def untouchedModule = getModuleUntouched(bundleName, version) + if (untouchedModule) { + println "Found untouched module in: ${untouchedModule}" + println "Using untouched module from modules-untouched repository" + return untouchedModule + } + + // Second, try to download from releases.properties + println "Module not found in modules-untouched, downloading from releases.properties..." + println "" + + def releasesFile = file('releases.properties') + if (!releasesFile.exists()) { + throw new GradleException("releases.properties not found") + } + + def releases = new Properties() + releasesFile.withInputStream { releases.load(it) } + + def downloadUrl = releases.getProperty(version) + if (!downloadUrl) { + throw new GradleException("Version ${version} not found in releases.properties or modules-untouched repository") + } + + println "Downloading Ghostscript ${version} from:" + println " ${downloadUrl}" + + // Determine filename from URL + def filename = downloadUrl.substring(downloadUrl.lastIndexOf('/') + 1) + def downloadDir = file(bundleTmpDownloadPath) + def extractDir = file(bundleTmpExtractPath) + downloadDir.mkdirs() + extractDir.mkdirs() + + def downloadedFile = file("${downloadDir}/${filename}") + + // Download if not already present + if (!downloadedFile.exists()) { + println " Downloading to: ${downloadedFile}" + ant.get(src: downloadUrl, dest: downloadedFile, verbose: true) + println " Download complete" + } else { + println " Using cached file: ${downloadedFile}" + } + + // Extract the archive + println " Extracting archive..." + def extractPath = file("${extractDir}/${version}") + if (extractPath.exists()) { + delete extractPath + } + extractPath.mkdirs() + + // Use 7zip or built-in extraction + if (filename.endsWith('.7z')) { + // Try to use 7zip if available + def sevenZipPath = find7ZipExecutable() + if (sevenZipPath) { + def command = [ + sevenZipPath.toString(), + 'x', + downloadedFile.absolutePath.toString(), + "-o${extractPath.absolutePath}".toString(), + '-y' + ] + def process = new ProcessBuilder(command as String[]) + .directory(extractPath) + .redirectErrorStream(true) + .start() + + process.inputStream.eachLine { line -> + if (line.trim()) println " ${line}" + } + + def exitCode = process.waitFor() + if (exitCode != 0) { + throw new GradleException("7zip extraction failed with exit code: ${exitCode}") + } + } else { + throw new GradleException("7zip not found. Please install 7zip or extract manually.") + } + } else if (filename.endsWith('.zip')) { + copy { + from zipTree(downloadedFile) + into extractPath + } + } else { + throw new GradleException("Unsupported archive format: ${filename}") + } + + println " Extraction complete" + + // Find the Ghostscript directory in the extracted files + def ghostscriptDir = findGhostscriptDirectory(extractPath) + if (!ghostscriptDir) { + throw new GradleException("Could not find Ghostscript directory in extracted files") + } + + println " Found Ghostscript directory: ${ghostscriptDir.name}" + return ghostscriptDir +} + +// Function to find Ghostscript directory in extracted files +def findGhostscriptDirectory(File extractPath) { + // Check for both 64-bit and 32-bit executables + def exeNames = ['gswin64c.exe', 'gswin32c.exe'] + + // First check if extractPath itself contains the executable (direct extraction) + for (exeName in exeNames) { + if (file("${extractPath}/bin/${exeName}").exists()) { + return extractPath + } + } + + // Look for directory containing the executable at top level + def ghostscriptDirs = extractPath.listFiles()?.findAll { dir -> + if (!dir.isDirectory()) return false + for (exeName in exeNames) { + if (file("${dir}/bin/${exeName}").exists()) { + return true + } + } + return false + } + + if (ghostscriptDirs && !ghostscriptDirs.isEmpty()) { + return ghostscriptDirs[0] + } + + // If not found at top level, search one level deep + def foundDir = null + extractPath.listFiles()?.each { dir -> + if (dir.isDirectory() && !foundDir) { + def subDirs = dir.listFiles()?.findAll { subDir -> + if (!subDir.isDirectory()) return false + for (exeName in exeNames) { + if (file("${subDir}/bin/${exeName}").exists()) { + return true + } + } + return false + } + if (subDirs && !subDirs.isEmpty()) { + foundDir = subDirs[0] + } + } + } + + return foundDir +} + +// ============================================================================ +// GRADLE TASKS +// ============================================================================ + +// Task: Display build information +tasks.register('info') { + group = 'help' + description = 'Display build configuration information' + + // Capture values at configuration time to avoid deprecation warnings + def projectName = project.name + def projectVersion = project.version + def projectDescription = project.description + def projectBasedirValue = projectBasedir + def rootDirValue = rootDir + def devPathValue = devPath + def bundleNameValue = bundleName + def bundleReleaseValue = bundleRelease + def bundleTypeValue = bundleType + def bundleFormatValue = bundleFormat + def buildBasePathValue = buildBasePath + def buildTmpPathValue = buildTmpPath + def bundleTmpPrepPathValue = bundleTmpPrepPath + def bundleTmpBuildPathValue = bundleTmpBuildPath + def bundleTmpSrcPathValue = bundleTmpSrcPath + def bundleTmpDownloadPathValue = bundleTmpDownloadPath + def bundleTmpExtractPathValue = bundleTmpExtractPath + def javaVersion = JavaVersion.current() + def javaHome = System.getProperty('java.home') + def gradleVersion = gradle.gradleVersion + def gradleHome = gradle.gradleHomeDir + + doLast { + println """ + ================================================================ + Bearsampp Module Ghostscript - Build Info + ================================================================ + + Project: ${projectName} + Version: ${projectVersion} + Description: ${projectDescription} + + Bundle Properties: + Name: ${bundleNameValue} + Release: ${bundleReleaseValue} + Type: ${bundleTypeValue} + Format: ${bundleFormatValue} + + Paths: + Project Dir: ${projectBasedirValue} + Root Dir: ${rootDirValue} + Dev Path: ${devPathValue} + Build Base: ${buildBasePathValue} + Build Tmp: ${buildTmpPathValue} + Tmp Prep: ${bundleTmpPrepPathValue} + Tmp Build: ${bundleTmpBuildPathValue} + Tmp Src: ${bundleTmpSrcPathValue} + Tmp Download: ${bundleTmpDownloadPathValue} + Tmp Extract: ${bundleTmpExtractPathValue} + + Java: + Version: ${javaVersion} + Home: ${javaHome} + + Gradle: + Version: ${gradleVersion} + Home: ${gradleHome} + + Available Task Groups: + * build - Build and package tasks + * help - Help and information tasks + * verification - Verification tasks + + Quick Start: + gradle tasks - List all available tasks + gradle info - Show this information + gradle release -PbundleVersion=10.05.1 - Build specific version + gradle releaseAll - Build all versions + gradle clean - Clean build artifacts + gradle verify - Verify build environment + """.stripIndent() + } +} + +// Task: Main release task - build a specific version +tasks.register('release') { + group = 'build' + description = 'Build release package for a specific version (use -PbundleVersion=X.X.X or run interactively)' + + // Capture property at configuration time to avoid deprecation warning + def versionProperty = project.findProperty('bundleVersion') + + doLast { + def versionToBuild = versionProperty + + if (!versionToBuild) { + // Interactive mode - prompt for version + def availableVersions = getAvailableVersions() + + if (availableVersions.isEmpty()) { + throw new GradleException("No versions found in bin/ or bin/archived/ directory") + } + + println "" + println "=".multiply(70) + println "Interactive Release Mode" + println "=".multiply(70) + println "" + println "Available versions:" + + // Show versions with location tags + def binDir = file("${projectDir}/bin") + def archivedDir = file("${projectDir}/bin/archived") + + availableVersions.eachWithIndex { version, index -> + def location = "" + if (binDir.exists() && file("${binDir}/${bundleName}${version}").exists()) { + location = "[bin]" + } else if (archivedDir.exists() && file("${archivedDir}/${bundleName}${version}").exists()) { + location = "[bin/archived]" + } + println " ${(index + 1).toString().padLeft(2)}. ${version.padRight(15)} ${location}" + } + println "" + println "Enter version to build (index or exact version):" + println "" + + // Read input using Gradle's standard input + def input = null + try { + def reader = new BufferedReader(new InputStreamReader(System.in)) + input = reader.readLine() + } catch (Exception e) { + throw new GradleException(""" + Failed to read input. Please use non-interactive mode: + gradle release -PbundleVersion=X.X.X + + Available versions: ${availableVersions.join(', ')} + """.stripIndent()) + } + + if (!input || input.trim().isEmpty()) { + throw new GradleException(""" + No version selected. Please use non-interactive mode: + gradle release -PbundleVersion=X.X.X + + Available versions: ${availableVersions.join(', ')} + """.stripIndent()) + } + + versionToBuild = input.trim() + + // Support selecting by list index (e.g., "9") or exact version string + def indexMatch = (versionToBuild ==~ /\d+/) + if (indexMatch) { + def idx = Integer.parseInt(versionToBuild) + if (idx >= 1 && idx <= availableVersions.size()) { + versionToBuild = availableVersions[idx - 1] + } else { + throw new GradleException(""" + Invalid selection: ${input} + + Please enter a number between 1 and ${availableVersions.size()} or one of the exact versions below: + ${availableVersions.collect { " - ${it}" }.join('\n')} + """.stripIndent()) + } + } else { + // Validate the entered version string + if (!availableVersions.contains(versionToBuild)) { + throw new GradleException(""" + Invalid version: ${versionToBuild} + + Please choose from available versions: + ${availableVersions.collect { " - ${it}" }.join('\n')} + """.stripIndent()) + } + } + + println "" + println "Selected version: ${versionToBuild}" + } + + println "" + println "=".multiply(70) + println "Building ${bundleName} ${versionToBuild}" + println "=".multiply(70) + println "" + + // Try to use local bin first; if missing, we'll download (modules-untouched fallback) + def bundlePath = file("${projectDir}/bin/${bundleName}${versionToBuild}") + if (!bundlePath.exists()) { + def archivedCandidate = file("${projectDir}/bin/archived/${bundleName}${versionToBuild}") + if (archivedCandidate.exists()) { + bundlePath = archivedCandidate + } else { + println "No local bundle found in bin/ or bin/archived/. Will download sources." + } + } + + if (bundlePath?.exists()) { + println "Bundle path: ${bundlePath}" + } + println "" + + // Determine bundleVersion + def bundleVersion = bundlePath?.exists() ? bundlePath.name.replace(bundleName, '') : versionToBuild + + // Determine source paths + def bundleSrcDest = bundlePath + def bundleSrcFinal = bundleSrcDest + + // Check if Ghostscript executable exists (64-bit or 32-bit) when we have a local bundle + def ghostscriptExe64 = bundleSrcFinal ? file("${bundleSrcFinal}/bin/gswin64c.exe") : file('NUL') + def ghostscriptExe32 = bundleSrcFinal ? file("${bundleSrcFinal}/bin/gswin32c.exe") : file('NUL') + def hasGhostscript = bundleSrcFinal && (ghostscriptExe64.exists() || ghostscriptExe32.exists()) + + if (!hasGhostscript) { + // Ghostscript binaries not found in bin/ - check if already downloaded to bearsampp-build/tmp + def tmpExtractPath = file("${bundleTmpExtractPath}/${bundleVersion}") + def tmpGhostscriptDir = findGhostscriptDirectory(tmpExtractPath) + + if (tmpGhostscriptDir && tmpGhostscriptDir.exists()) { + println "Using cached Ghostscript binaries from bearsampp-build/tmp" + bundleSrcFinal = tmpGhostscriptDir + } else { + // Download and extract to bearsampp-build/tmp + println "" + println "Ghostscript binaries not found" + println "Downloading Ghostscript ${bundleVersion}..." + println "" + + try { + // Download and extract to bearsampp-build/tmp + bundleSrcFinal = downloadAndExtractGhostscript(bundleVersion, file(bundleTmpExtractPath)) + } catch (Exception e) { + throw new GradleException(""" + Failed to download Ghostscript binaries: ${e.message} + + You can manually download and extract Ghostscript binaries to: + ${bundleSrcDest}/ + + Or check that version ${bundleVersion} exists in releases.properties + """.stripIndent()) + } + } + } + + // Verify Ghostscript executable exists (64-bit or 32-bit) + ghostscriptExe64 = file("${bundleSrcFinal}/bin/gswin64c.exe") + ghostscriptExe32 = file("${bundleSrcFinal}/bin/gswin32c.exe") + def ghostscriptExe = ghostscriptExe64.exists() ? ghostscriptExe64 : ghostscriptExe32 + + if (!ghostscriptExe.exists()) { + throw new GradleException("Ghostscript executable (gswin64c.exe or gswin32c.exe) not found in ${bundleSrcFinal}/bin/") + } + + println "Source folder: ${bundleSrcFinal}" + println "" + + // Prepare output directory + def ghostscriptPrepPath = file("${bundleTmpPrepPath}/${bundleName}${bundleVersion}") + if (ghostscriptPrepPath.exists()) { + delete ghostscriptPrepPath + } + ghostscriptPrepPath.mkdirs() + + // Copy Ghostscript binaries from extracted/downloaded location (excluding docs and examples) + println "Copying Ghostscript files..." + copy { + from bundleSrcFinal + into ghostscriptPrepPath + exclude 'doc/**' + exclude 'examples/**' + exclude 'uninstgs.exe.nsis' + exclude 'vcredist_x64.exe' + } + + // Copy gswin64c.exe or gswin32c.exe to gs.exe + def sourceExe = file("${ghostscriptPrepPath}/bin/gswin64c.exe").exists() ? + file("${ghostscriptPrepPath}/bin/gswin64c.exe") : + file("${ghostscriptPrepPath}/bin/gswin32c.exe") + println "Creating gs.exe from ${sourceExe.name}..." + copy { + from sourceExe + into file("${ghostscriptPrepPath}/bin") + rename { 'gs.exe' } + } + + // Copy configuration files from bin directory if available + if (bundleSrcDest?.exists()) { + println "Copying configuration files..." + copy { + from bundleSrcDest + into ghostscriptPrepPath + include 'bearsampp.conf' + include 'update_cidfmap.bat' + } + } else { + println "No local config directory for ${bundleName}${bundleVersion}; skipping config file copy." + } + + println "" + println "Copying to bundles_build directory..." + // Mirror Bruno: provide a non-zip build directory for dev/testing + def ghostscriptBuildPath = file("${bundleTmpBuildPath}/${bundleName}${bundleVersion}") + if (ghostscriptBuildPath.exists()) { + delete ghostscriptBuildPath + } + ghostscriptBuildPath.mkdirs() + + copy { + from ghostscriptPrepPath + into ghostscriptBuildPath + } + println "Non-zip version available at: ${ghostscriptBuildPath}" + + println "" + println "Preparing archive..." + + // Determine build output path following Apache pattern + // bearsampp-build/tools/ghostscript/{bundleRelease} for tools + // bearsampp-build/bins/apache/{bundleRelease} for bins + def buildPath = file(buildBasePath) + def buildBinsPath = file("${buildPath}/${bundleType}/${bundleName}/${bundleRelease}") + buildBinsPath.mkdirs() + + // Build archive filename + def destFile = file("${buildBinsPath}/bearsampp-${bundleName}-${bundleVersion}-${bundleRelease}") + + // Compress based on format + if (bundleFormat == '7z') { + // 7z format + def archiveFile = file("${destFile}.7z") + if (archiveFile.exists()) { + delete archiveFile + } + + println "Compressing ${bundleName}${bundleVersion} to ${archiveFile.name}..." + + // Find 7z executable + def sevenZipExe = find7ZipExecutable() + if (!sevenZipExe) { + throw new GradleException("7-Zip not found. Please install 7-Zip or set 7Z_HOME environment variable.") + } + + println "Using 7-Zip: ${sevenZipExe}" + + // Create 7z archive, ensuring the version directory is included at the root + def command = [ + sevenZipExe, + 'a', + '-t7z', + archiveFile.absolutePath.toString(), + "${bundleName}${bundleVersion}" + ] + + // Run from the parent prep directory so the root contains the version folder + def process = new ProcessBuilder(command as String[]) + .directory(file(bundleTmpPrepPath)) + .redirectErrorStream(true) + .start() + + process.inputStream.eachLine { line -> + if (line.trim()) println " ${line}" + } + + def exitCode = process.waitFor() + if (exitCode != 0) { + throw new GradleException("7zip compression failed with exit code: ${exitCode}") + } + + println "Archive created: ${archiveFile}" + + // Generate hash files + println "Generating hash files..." + generateHashFiles(archiveFile) + + } else { + // ZIP format + def archiveFile = file("${destFile}.zip") + if (archiveFile.exists()) { + delete archiveFile + } + + println "Compressing ${bundleName}${bundleVersion} to ${archiveFile.name}..." + + // Zip while preserving the version directory at the root + ant.zip(destfile: archiveFile) { + zipfileset(dir: bundleTmpPrepPath, includes: "${bundleName}${bundleVersion}/**") + } + + println "Archive created: ${archiveFile}" + + // Generate hash files + println "Generating hash files..." + generateHashFiles(archiveFile) + } + + println "" + println "=".multiply(70) + println "[SUCCESS] Release build completed successfully for version ${versionToBuild}" + println "Output directory: ${ghostscriptBuildPath}" + println "Archive: ${destFile}.${bundleFormat}" + println "=".multiply(70) + } +} + +// Helper function to find 7-Zip executable +def find7ZipExecutable() { + // Check environment variable + def sevenZipHome = System.getenv('7Z_HOME') + if (sevenZipHome) { + def exe = file("${sevenZipHome}/7z.exe") + if (exe.exists()) { + return exe.absolutePath + } + } + + // Check common installation paths + def commonPaths = [ + 'C:/Program Files/7-Zip/7z.exe', + 'C:/Program Files (x86)/7-Zip/7z.exe', + 'D:/Program Files/7-Zip/7z.exe', + 'D:/Program Files (x86)/7-Zip/7z.exe' + ] + + for (path in commonPaths) { + def exe = file(path) + if (exe.exists()) { + return exe.absolutePath + } + } + + // Try to find in PATH + try { + def process = ['where', '7z.exe'].execute() + process.waitFor() + if (process.exitValue() == 0) { + def output = process.text.trim() + if (output) { + return output.split('\n')[0].trim() + } + } + } catch (Exception e) { + // Ignore + } + + return null +} + +// Helper function to generate hash files +def generateHashFiles(File file) { + if (!file.exists()) { + throw new GradleException("File not found for hashing: ${file}") + } + + // Generate MD5 + def md5File = new File("${file.absolutePath}.md5") + def md5Hash = calculateHash(file, 'MD5') + md5File.text = "${md5Hash} ${file.name}\n" + println " Created: ${md5File.name}" + + // Generate SHA1 + def sha1File = new File("${file.absolutePath}.sha1") + def sha1Hash = calculateHash(file, 'SHA-1') + sha1File.text = "${sha1Hash} ${file.name}\n" + println " Created: ${sha1File.name}" + + // Generate SHA256 + def sha256File = new File("${file.absolutePath}.sha256") + def sha256Hash = calculateHash(file, 'SHA-256') + sha256File.text = "${sha256Hash} ${file.name}\n" + println " Created: ${sha256File.name}" + + // Generate SHA512 + def sha512File = new File("${file.absolutePath}.sha512") + def sha512Hash = calculateHash(file, 'SHA-512') + sha512File.text = "${sha512Hash} ${file.name}\n" + println " Created: ${sha512File.name}" +} + +// Helper function to calculate hash +def calculateHash(File file, String algorithm) { + def digest = java.security.MessageDigest.getInstance(algorithm) + file.withInputStream { stream -> + def buffer = new byte[8192] + def bytesRead + while ((bytesRead = stream.read(buffer)) != -1) { + digest.update(buffer, 0, bytesRead) + } + } + return digest.digest().collect { String.format('%02x', it) }.join('') +} + +// Helper function to get available versions +def getAvailableVersions() { + def versions = [] + + // Check bin directory + def binDir = file("${projectDir}/bin") + if (binDir.exists()) { + def binVersions = binDir.listFiles() + ?.findAll { it.isDirectory() && it.name.startsWith(bundleName) && it.name != 'archived' } + ?.collect { it.name.replace(bundleName, '') } ?: [] + versions.addAll(binVersions) + } + + // Check bin/archived subdirectory + def archivedDir = file("${projectDir}/bin/archived") + if (archivedDir.exists()) { + def archivedVersions = archivedDir.listFiles() + ?.findAll { it.isDirectory() && it.name.startsWith(bundleName) } + ?.collect { it.name.replace(bundleName, '') } ?: [] + versions.addAll(archivedVersions) + } + + // Remove duplicates and sort + return versions.unique().sort() +} + +// Task: Build all available versions +tasks.register('releaseAll') { + group = 'build' + description = 'Build release packages for all available versions in bin/ and bin/archived/ directories' + + doLast { + def versions = getAvailableVersions() + + if (versions.isEmpty()) { + throw new GradleException("No versions found in bin/ or bin/archived/ directory") + } + + println "" + println "=".multiply(70) + println "Building releases for ${versions.size()} ${bundleName} versions" + println "=".multiply(70) + println "" + + def successCount = 0 + def failedVersions = [] + + versions.each { version -> + println "=".multiply(70) + println "[${successCount + 1}/${versions.size()}] Building ${bundleName} ${version}..." + println "=".multiply(70) + + try { + // Call the release task logic for this version + def bundlePath = file("${projectDir}/bin/${bundleName}${version}") + if (!bundlePath.exists()) { + bundlePath = file("${projectDir}/bin/archived/${bundleName}${version}") + if (!bundlePath.exists()) { + throw new GradleException("Bundle path not found: ${bundlePath}") + } + } + + println "Bundle path: ${bundlePath}" + println "" + + // Get the bundle folder and version + def bundleFolder = bundlePath.name + def bundleVersion = bundleFolder.replace(bundleName, '') + + // Determine source paths + def bundleSrcDest = bundlePath + def bundleSrcFinal = bundleSrcDest + + // Check if gswin64c.exe exists + def ghostscriptExe = file("${bundleSrcFinal}/bin/gswin64c.exe") + if (!ghostscriptExe.exists()) { + // Try to download + def tmpExtractPath = file("${bundleTmpExtractPath}/${bundleVersion}") + def tmpGhostscriptDir = findGhostscriptDirectory(tmpExtractPath) + + if (tmpGhostscriptDir && tmpGhostscriptDir.exists()) { + bundleSrcFinal = tmpGhostscriptDir + } else { + bundleSrcFinal = downloadAndExtractGhostscript(bundleVersion, file(bundleTmpExtractPath)) + } + } + + ghostscriptExe = file("${bundleSrcFinal}/bin/gswin64c.exe") + if (!ghostscriptExe.exists()) { + throw new GradleException("gswin64c.exe not found at ${ghostscriptExe}") + } + + println "Source folder: ${bundleSrcFinal}" + println "" + + // Prepare output directory + def ghostscriptPrepPath = file("${bundleTmpPrepPath}/${bundleName}${bundleVersion}") + if (ghostscriptPrepPath.exists()) { + delete ghostscriptPrepPath + } + ghostscriptPrepPath.mkdirs() + + // Copy Ghostscript files + println "Copying Ghostscript files..." + copy { + from bundleSrcFinal + into ghostscriptPrepPath + exclude 'doc/**' + exclude 'examples/**' + exclude 'uninstgs.exe.nsis' + exclude 'vcredist_x64.exe' + } + + // Copy gswin64c.exe to gs.exe + copy { + from file("${ghostscriptPrepPath}/bin/gswin64c.exe") + into file("${ghostscriptPrepPath}/bin") + rename { 'gs.exe' } + } + + // Copy configuration files + copy { + from bundleSrcDest + into ghostscriptPrepPath + include 'bearsampp.conf' + include 'update_cidfmap.bat' + } + + // Copy to bundles_build directory (non-zip version for development/testing) + println "" + println "Copying to bundles_build directory..." + def ghostscriptBuildPath = file("${bundleTmpBuildPath}/${bundleName}${bundleVersion}") + if (ghostscriptBuildPath.exists()) { + delete ghostscriptBuildPath + } + ghostscriptBuildPath.mkdirs() + + copy { + from ghostscriptPrepPath + into ghostscriptBuildPath + } + println "Non-zip version available at: ${ghostscriptBuildPath}" + + // Build archive + def buildPath = file(buildBasePath) + def buildBinsPath = file("${buildPath}/${bundleType}/${bundleName}/${bundleRelease}") + buildBinsPath.mkdirs() + + def destFile = file("${buildBinsPath}/bearsampp-${bundleName}-${bundleVersion}-${bundleRelease}") + + if (bundleFormat == '7z') { + def archiveFile = file("${destFile}.7z") + if (archiveFile.exists()) { + delete archiveFile + } + + def sevenZipExe = find7ZipExecutable() + if (!sevenZipExe) { + throw new GradleException("7-Zip not found") + } + + def command = [ + sevenZipExe, + 'a', + '-t7z', + archiveFile.absolutePath.toString(), + '.' + ] + + def process = new ProcessBuilder(command as String[]) + .directory(ghostscriptPrepPath) + .redirectErrorStream(true) + .start() + + process.inputStream.eachLine { line -> + if (line.trim()) println " ${line}" + } + + def exitCode = process.waitFor() + if (exitCode != 0) { + throw new GradleException("7zip compression failed") + } + + generateHashFiles(archiveFile) + } else { + def archiveFile = file("${destFile}.zip") + if (archiveFile.exists()) { + delete archiveFile + } + + ant.zip(destfile: archiveFile, basedir: ghostscriptPrepPath) + generateHashFiles(archiveFile) + } + + println "" + println "[SUCCESS] ${bundleName} ${version} completed" + println "Output: ${ghostscriptBuildPath}" + successCount++ + + } catch (Exception e) { + println "" + println "[FAILED] ${bundleName} ${version}: ${e.message}" + failedVersions.add(version) + } + + println "" + } + + // Summary + println "=".multiply(70) + println "Build Summary" + println "=".multiply(70) + println "Total versions: ${versions.size()}" + println "Successful: ${successCount}" + println "Failed: ${failedVersions.size()}" + + if (!failedVersions.isEmpty()) { + println "" + println "Failed versions:" + failedVersions.each { v -> + println " - ${v}" + } + } + + println "=".multiply(70) + + if (failedVersions.isEmpty()) { + println "[SUCCESS] All versions built successfully!" + } else { + throw new GradleException("${failedVersions.size()} version(s) failed to build") + } + } +} + +// Task: Enhanced clean task +tasks.named('clean') { + group = 'build' + description = 'Clean build artifacts and temporary files' + + doLast { + // Clean Gradle build directory + def buildDir = file("${projectDir}/build") + if (buildDir.exists()) { + delete buildDir + } + + println "[SUCCESS] Build artifacts cleaned" + } +} + +// Task: Verify build environment +tasks.register('verify') { + group = 'verification' + description = 'Verify build environment and dependencies' + + doLast { + println "Verifying build environment for module-ghostscript..." + + def checks = [:] + + // Check Java version + def javaVersion = JavaVersion.current() + checks['Java 8+'] = javaVersion >= JavaVersion.VERSION_1_8 + + // Check required files + checks['build.properties'] = file('build.properties').exists() + checks['releases.properties'] = file('releases.properties').exists() + + // Check dev directory + checks['dev directory'] = file(devPath).exists() + + // Check bin directory + checks['bin directory'] = file("${projectDir}/bin").exists() + + // Check bin/archived directory + checks['bin/archived directory'] = file("${projectDir}/bin/archived").exists() + + // Check 7-Zip if format is 7z + if (bundleFormat == '7z') { + checks['7-Zip'] = find7ZipExecutable() != null + } + + println "\nEnvironment Check Results:" + println "-".multiply(60) + checks.each { name, passed -> + def status = passed ? "[PASS]" : "[FAIL]" + println " ${status.padRight(10)} ${name}" + } + println "-".multiply(60) + + def allPassed = checks.values().every { it } + if (allPassed) { + println "\n[SUCCESS] All checks passed! Build environment is ready." + println "\nYou can now run:" + println " gradle release -PbundleVersion=10.05.1 - Build release for version" + println " gradle listVersions - List available versions" + } else { + println "\n[WARNING] Some checks failed. Please review the requirements." + throw new GradleException("Build environment verification failed") + } + } +} + +// Task: List all bundle versions from modules-untouched ghostscript.properties +tasks.register('listReleases') { + group = 'help' + description = 'List all available releases from modules-untouched ghostscript.properties' + + doLast { + def props = fetchModulesUntouchedProperties() + if (!props) { + println "\n[WARNING] Could not fetch modules-untouched ghostscript.properties." + println "Checking local releases.properties..." + + def releasesFile = file('releases.properties') + if (!releasesFile.exists()) { + println "releases.properties not found" + return + } + + def releases = new Properties() + releasesFile.withInputStream { releases.load(it) } + + println "\nAvailable Ghostscript Releases (local):" + println "-".multiply(80) + releases.sort { it.key }.each { version, url -> + println " ${version.padRight(10)} -> ${url}" + } + println "-".multiply(80) + println "Total releases: ${releases.size()}" + return + } + + println "\nAvailable Ghostscript Releases (modules-untouched):" + println "-".multiply(80) + props.sort { a, b -> a.key <=> b.key }.each { version, url -> + println " ${version.padRight(10)} -> ${url}" + } + println "-".multiply(80) + println "Total releases: ${props.size()}" + } +} + +// Task: List available bundle versions in bin and bin/archived directories +tasks.register('listVersions') { + group = 'help' + description = 'List all available bundle versions in bin/ and bin/archived/ directories' + + doLast { + def versions = getAvailableVersions() + + if (versions.isEmpty()) { + println "\nNo versions found in bin/ or bin/archived/ directories" + return + } + + println "\nAvailable ${bundleName} versions:" + println "-".multiply(60) + + // Show which directory each version is in + def binDir = file("${projectDir}/bin") + def archivedDir = file("${projectDir}/bin/archived") + + versions.each { version -> + def location = "" + if (binDir.exists() && file("${binDir}/${bundleName}${version}").exists()) { + location = "[bin]" + } else if (archivedDir.exists() && file("${archivedDir}/${bundleName}${version}").exists()) { + location = "[bin/archived]" + } + println " ${version.padRight(15)} ${location}" + } + println "-".multiply(60) + println "Total versions: ${versions.size()}" + + if (!versions.isEmpty()) { + println "\nTo build a specific version:" + println " gradle release -PbundleVersion=${versions.last()}" + } + } +} + +// Task: Validate build.properties +tasks.register('validateProperties') { + group = 'verification' + description = 'Validate build.properties configuration' + + doLast { + println "Validating build.properties..." + + def required = ['bundle.name', 'bundle.release', 'bundle.type', 'bundle.format'] + def missing = [] + + required.each { prop -> + if (!buildProps.containsKey(prop) || buildProps.getProperty(prop).trim().isEmpty()) { + missing.add(prop) + } + } + + if (missing.isEmpty()) { + println "[SUCCESS] All required properties are present:" + required.each { prop -> + println " ${prop} = ${buildProps.getProperty(prop)}" + } + } else { + println "[ERROR] Missing required properties:" + missing.each { prop -> + println " - ${prop}" + } + throw new GradleException("build.properties validation failed") + } + } +} + +// Task: Check modules-untouched integration +tasks.register('checkModulesUntouched') { + group = 'verification' + description = 'Check modules-untouched repository integration and available versions' + + doLast { + println "" + println "=".multiply(70) + println "Modules-Untouched Integration Check" + println "=".multiply(70) + println "" + + def propsUrl = "https://raw.githubusercontent.com/Bearsampp/modules-untouched/main/modules/${bundleName}.properties" + println "Repository URL:" + println " ${propsUrl}" + println "" + + println "Fetching ${bundleName}.properties from modules-untouched..." + def untouchedProps = fetchModulesUntouchedProperties() + + if (untouchedProps) { + println "" + println "=".multiply(70) + println "Available Versions in modules-untouched" + println "=".multiply(70) + + def sortedVersions = untouchedProps.sort { a, b -> + // Simple version comparison + def aParts = a.key.tokenize('.') + def bParts = b.key.tokenize('.') + for (int i = 0; i < Math.min(aParts.size(), bParts.size()); i++) { + def aNum = aParts[i].toInteger() + def bNum = bParts[i].toInteger() + if (aNum != bNum) return aNum <=> bNum + } + return aParts.size() <=> bParts.size() + } + + sortedVersions.each { version, url -> + println " ${version.padRight(10)}" + } + + println "=".multiply(70) + println "Total versions: ${untouchedProps.size()}" + println "" + + println "" + println "=".multiply(70) + println "[SUCCESS] modules-untouched integration is working" + println "=".multiply(70) + println "" + println "Version Resolution Strategy:" + println " 1. Check modules-untouched ${bundleName}.properties (remote)" + println " 2. Check local releases.properties (fallback)" + println " 3. Construct standard URL format (fallback)" + println "" + + } else { + println "" + println "=".multiply(70) + println "[WARNING] Could not fetch ${bundleName}.properties from modules-untouched" + println "=".multiply(70) + println "" + println "This may be due to:" + println " - Network connectivity issues" + println " - Repository access problems" + println " - File not available at expected location" + println "" + println "The build system will fall back to:" + println " 1. Local releases.properties" + println " 2. Standard URL format construction" + } + } +} + +// ============================================================================ +// BUILD LIFECYCLE HOOKS +// ============================================================================ + +gradle.taskGraph.whenReady { graph -> + println """ + ================================================================ + Bearsampp Module Ghostscript - Gradle Build + ================================================================ + """.stripIndent() +} + +// ============================================================================ +// DEFAULT TASK +// ============================================================================ + +defaultTasks 'info' diff --git a/build.xml b/build.xml deleted file mode 100644 index 40c3ad7..0000000 --- a/build.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..a61e594 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,19 @@ +# Gradle Build Properties for Bearsampp Module Ghostscript + +# Gradle daemon configuration +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true + +# JVM settings for Gradle +org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError + +# Configure console output +org.gradle.console=auto +org.gradle.warning.mode=all + +# Build performance +org.gradle.configureondemand=false + +# Gradle version compatibility +# This project is compatible with Gradle 7.0+ diff --git a/module-ghostscript.RELEASE.launch b/module-ghostscript.RELEASE.launch deleted file mode 100644 index e87659d..0000000 --- a/module-ghostscript.RELEASE.launch +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..8312132 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,22 @@ +/* + * Bearsampp Module Ghostscript - Gradle Settings + */ + +rootProject.name = 'module-ghostscript' + +// Configure build cache for faster builds +buildCache { + local { + enabled = true + directory = file("${rootDir}/.gradle/build-cache") + } +} + +// Display initialization message +gradle.rootProject { + println """ + ================================================================ + Initializing Bearsampp Module Ghostscript Build + ================================================================ + """.stripIndent() +} diff --git a/test-gradle-build.bat b/test-gradle-build.bat new file mode 100644 index 0000000..9a72e0c --- /dev/null +++ b/test-gradle-build.bat @@ -0,0 +1,100 @@ +@echo off +REM Test script for Gradle build conversion +REM This script tests all Gradle tasks to ensure they work correctly + +echo ======================================================================== +echo Bearsampp Module Ghostscript - Gradle Build Test +echo ======================================================================== +echo. + +REM Test 1: Display build info +echo [TEST 1] Testing 'gradle info' task... +echo ------------------------------------------------------------------------ +call gradle info +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle info task failed + exit /b 1 +) +echo [PASSED] gradle info task +echo. + +REM Test 2: List all tasks +echo [TEST 2] Testing 'gradle tasks' task... +echo ------------------------------------------------------------------------ +call gradle tasks +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle tasks task failed + exit /b 1 +) +echo [PASSED] gradle tasks task +echo. + +REM Test 3: List available versions +echo [TEST 3] Testing 'gradle listVersions' task... +echo ------------------------------------------------------------------------ +call gradle listVersions +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle listVersions task failed + exit /b 1 +) +echo [PASSED] gradle listVersions task +echo. + +REM Test 4: List releases from properties +echo [TEST 4] Testing 'gradle listReleases' task... +echo ------------------------------------------------------------------------ +call gradle listReleases +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle listReleases task failed + exit /b 1 +) +echo [PASSED] gradle listReleases task +echo. + +REM Test 5: Verify build environment +echo [TEST 5] Testing 'gradle verify' task... +echo ------------------------------------------------------------------------ +call gradle verify +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle verify task failed + exit /b 1 +) +echo [PASSED] gradle verify task +echo. + +REM Test 6: Validate properties +echo [TEST 6] Testing 'gradle validateProperties' task... +echo ------------------------------------------------------------------------ +call gradle validateProperties +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle validateProperties task failed + exit /b 1 +) +echo [PASSED] gradle validateProperties task +echo. + +REM Test 7: Clean build +echo [TEST 7] Testing 'gradle clean' task... +echo ------------------------------------------------------------------------ +call gradle clean +if %ERRORLEVEL% NEQ 0 ( + echo [FAILED] gradle clean task failed + exit /b 1 +) +echo [PASSED] gradle clean task +echo. + +echo ======================================================================== +echo All Tests Passed! +echo ======================================================================== +echo. +echo The Gradle build is working correctly. +echo. +echo To build a release, run: +echo gradle release -PbundleVersion=10.05.1 +echo. +echo Or run interactively: +echo gradle release +echo. + +exit /b 0