brick-module 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BrickModule.podspec +1 -0
- package/android/brick_modules.gradle +221 -30
- package/android/build.gradle +4 -4
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/android/gradlew +252 -0
- package/android/gradlew.bat +94 -0
- package/android/src/main/java/com/brickmodule/BrickModuleBase.kt +62 -10
- package/android/src/main/java/com/brickmodule/BrickModulePackage.kt +3 -2
- package/android/src/main/java/com/brickmodule/BrickModuleRegistry.kt +89 -163
- package/android/src/main/java/com/brickmodule/BrickRegistrar.kt +9 -0
- package/android/src/main/java/com/brickmodule/EventDataConverter.kt +122 -0
- package/dist/BrickModule.js +1 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/ios/BrickModule/Internal/BrickCoreModule.swift +14 -0
- package/ios/BrickModule/Internal/BrickModuleRegistry.swift +7 -4
- package/ios/BrickModule/Public/BrickModule-Swift.h +3 -1
- package/package.json +4 -4
- package/podfile_helper.rb +134 -15
- /package/android/src/main/java/com/brickmodule/{AndroidManifestNew.xml → AndroidManifest.xml} +0 -0
package/BrickModule.podspec
CHANGED
|
@@ -44,6 +44,7 @@ Pod::Spec.new do |s|
|
|
|
44
44
|
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
45
45
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
46
46
|
})
|
|
47
|
+
s.dependency 'React'
|
|
47
48
|
s.dependency "React-Codegen"
|
|
48
49
|
s.dependency "RCT-Folly"
|
|
49
50
|
s.dependency "RCTRequired"
|
|
@@ -43,6 +43,88 @@ ext.readPackageJson = { File packageJsonFile ->
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
ext.findBrickJson = { startDir ->
|
|
47
|
+
// Walk up the directory tree looking for brick.json
|
|
48
|
+
if (!startDir) {
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
def current = new File(startDir).canonicalFile
|
|
54
|
+
def root = new File('/').canonicalFile
|
|
55
|
+
|
|
56
|
+
while (current != root && current != null) {
|
|
57
|
+
def brickJsonFile = new File(current, 'brick.json')
|
|
58
|
+
if (brickJsonFile.exists()) {
|
|
59
|
+
return brickJsonFile
|
|
60
|
+
}
|
|
61
|
+
def parent = current.parentFile
|
|
62
|
+
if (parent == current || parent == null) break // Reached filesystem root
|
|
63
|
+
current = parent
|
|
64
|
+
}
|
|
65
|
+
} catch (Exception e) {
|
|
66
|
+
// Failed to process directory, return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ext.resolveProjectRoot = { projectRootPath, configDir ->
|
|
73
|
+
// Handle both absolute and relative paths
|
|
74
|
+
if (!projectRootPath || !configDir) {
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
def projectRootFile = new File(projectRootPath)
|
|
80
|
+
if (projectRootFile.isAbsolute()) {
|
|
81
|
+
return projectRootFile.exists() ? projectRootFile : null
|
|
82
|
+
} else {
|
|
83
|
+
// Relative to brick.json location
|
|
84
|
+
def resolvedFile = new File(configDir, projectRootPath).canonicalFile
|
|
85
|
+
return resolvedFile.exists() ? resolvedFile : null
|
|
86
|
+
}
|
|
87
|
+
} catch (Exception e) {
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
ext.getBrickAndroidPath = { searchRoot ->
|
|
93
|
+
// Walk up directory tree to find brick.json
|
|
94
|
+
def brickConfigFile = findBrickJson(searchRoot)
|
|
95
|
+
|
|
96
|
+
if (brickConfigFile && brickConfigFile.exists()) {
|
|
97
|
+
try {
|
|
98
|
+
def config = new JsonSlurper().parse(brickConfigFile)
|
|
99
|
+
|
|
100
|
+
// Get the effective project root
|
|
101
|
+
def effectiveRoot = brickConfigFile.parentFile
|
|
102
|
+
if (config.projectRoot) {
|
|
103
|
+
def resolvedRoot = resolveProjectRoot(config.projectRoot, brickConfigFile.parentFile)
|
|
104
|
+
if (resolvedRoot) {
|
|
105
|
+
effectiveRoot = resolvedRoot
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
def androidPath = config?.output?.android
|
|
110
|
+
if (androidPath && !androidPath.isEmpty()) {
|
|
111
|
+
// Handle absolute paths (though not recommended)
|
|
112
|
+
if (new File(androidPath).isAbsolute()) {
|
|
113
|
+
println("[Brick] Warning: Using absolute path for Android output is not recommended: ${androidPath}")
|
|
114
|
+
return androidPath
|
|
115
|
+
}
|
|
116
|
+
// Otherwise, treat as relative to effective project root
|
|
117
|
+
return new File(effectiveRoot, androidPath).canonicalPath
|
|
118
|
+
}
|
|
119
|
+
} catch (Exception e) {
|
|
120
|
+
println("[Brick] Warning: Failed to parse brick.json: ${e.message}")
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Default: .brick directory in the Android project root
|
|
125
|
+
return new File(searchRoot, '.brick').canonicalPath
|
|
126
|
+
}
|
|
127
|
+
|
|
46
128
|
ext.getAllDependencies = { packageJson ->
|
|
47
129
|
def deps = []
|
|
48
130
|
deps.addAll(packageJson.dependencies?.keySet() ?: [])
|
|
@@ -54,6 +136,44 @@ ext.isBrickModule = { packageJson ->
|
|
|
54
136
|
return packageJson?.brickModule != null
|
|
55
137
|
}
|
|
56
138
|
|
|
139
|
+
ext.findProjectRoot = { androidDir ->
|
|
140
|
+
// 1. Walk up directory tree to find brick.json
|
|
141
|
+
def brickConfigFile = findBrickJson(androidDir)
|
|
142
|
+
if (brickConfigFile) {
|
|
143
|
+
brickLog("Found brick.json at: ${brickConfigFile.canonicalPath}")
|
|
144
|
+
try {
|
|
145
|
+
def config = new JsonSlurper().parse(brickConfigFile)
|
|
146
|
+
if (config.projectRoot) {
|
|
147
|
+
def projectRoot = resolveProjectRoot(config.projectRoot, brickConfigFile.parentFile)
|
|
148
|
+
if (projectRoot) {
|
|
149
|
+
brickLog("Using projectRoot from brick.json: ${projectRoot.canonicalPath}")
|
|
150
|
+
return projectRoot
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// If brick.json exists but has no projectRoot, use its directory as project root
|
|
154
|
+
return brickConfigFile.parentFile
|
|
155
|
+
} catch (Exception e) {
|
|
156
|
+
println("[Brick] Warning: Failed to parse brick.json: ${e.message}")
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 2. Walk up to find package.json with node_modules
|
|
161
|
+
def current = androidDir
|
|
162
|
+
while (current != null && current != new File('/')) {
|
|
163
|
+
if (new File(current, 'package.json').exists() && new File(current, 'node_modules').exists()) {
|
|
164
|
+
brickLog("Found project root via package.json: ${current.canonicalPath}")
|
|
165
|
+
return current
|
|
166
|
+
}
|
|
167
|
+
def parent = current.parentFile
|
|
168
|
+
if (parent == current) break
|
|
169
|
+
current = parent
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// If no project root found, use default fallback
|
|
173
|
+
brickLog("Warning: Failed to find project root via brick.json or package.json. Using default: ${androidDir.parentFile.canonicalPath}")
|
|
174
|
+
return androidDir.parentFile
|
|
175
|
+
}
|
|
176
|
+
|
|
57
177
|
ext.runBrickCodegen = { workingDir ->
|
|
58
178
|
def brickModuleDir = resolveModule(workingDir, "brick-module")
|
|
59
179
|
if (brickModuleDir == null) {
|
|
@@ -82,7 +202,7 @@ ext.runBrickCodegen = { workingDir ->
|
|
|
82
202
|
// =============================================================================
|
|
83
203
|
|
|
84
204
|
ext.applyBrickModules = { settings ->
|
|
85
|
-
def projectRoot = settings.rootDir
|
|
205
|
+
def projectRoot = findProjectRoot(settings.rootDir)
|
|
86
206
|
def foundModules = []
|
|
87
207
|
def brickModulesData = [:]
|
|
88
208
|
|
|
@@ -119,34 +239,44 @@ ext.applyBrickModules = { settings ->
|
|
|
119
239
|
def packageJson = readPackageJson(new File(moduleDir, "package.json"))
|
|
120
240
|
if (!isBrickModule(packageJson)) return
|
|
121
241
|
|
|
242
|
+
// Check if autoRegister is enabled (default: true)
|
|
243
|
+
def autoRegister = packageJson.brickModule.autoRegister != false
|
|
244
|
+
if (!autoRegister) return
|
|
245
|
+
|
|
122
246
|
def androidDir = new File(moduleDir, "android")
|
|
123
247
|
if (androidDir.exists()) {
|
|
124
|
-
|
|
125
|
-
|
|
248
|
+
// Convert npm package name to valid Gradle project name
|
|
249
|
+
// Replace @ with empty and / with _
|
|
250
|
+
def gradleProjectName = depName.replaceAll("^@", "").replaceAll("/", "_")
|
|
251
|
+
|
|
252
|
+
settings.include(":${gradleProjectName}")
|
|
253
|
+
settings.project(":${gradleProjectName}").projectDir = androidDir
|
|
126
254
|
foundModules.add(depName)
|
|
127
255
|
|
|
128
256
|
// Store module data for project configuration
|
|
129
257
|
if (packageJson.brickModule.android?.package) {
|
|
130
258
|
brickModulesData[depName] = [
|
|
131
259
|
moduleName: packageJson.brickModule.android.moduleName ?: depName,
|
|
132
|
-
packageName: packageJson.brickModule.android.package
|
|
260
|
+
packageName: packageJson.brickModule.android.package,
|
|
261
|
+
gradleProjectName: gradleProjectName
|
|
133
262
|
]
|
|
134
263
|
}
|
|
135
264
|
}
|
|
136
265
|
}
|
|
137
266
|
|
|
138
|
-
// Check if codegen is needed
|
|
139
|
-
def
|
|
267
|
+
// Check if codegen is needed (use configured path)
|
|
268
|
+
def androidBrickPath = getBrickAndroidPath(settings.rootDir)
|
|
269
|
+
def brickDir = new File(androidBrickPath)
|
|
140
270
|
def needsCodegen = !brickDir.exists() || !new File(brickDir, "src/main/kotlin/BrickModule.kt").exists()
|
|
141
271
|
|
|
142
272
|
if (needsCodegen) {
|
|
143
273
|
runBrickCodegen(projectRoot)
|
|
144
274
|
}
|
|
145
275
|
|
|
146
|
-
// Include generated module
|
|
276
|
+
// Include generated module (use configured path)
|
|
147
277
|
if (brickDir.exists()) {
|
|
148
|
-
settings.include(":brick-
|
|
149
|
-
settings.project(":brick-
|
|
278
|
+
settings.include(":brick-codegen")
|
|
279
|
+
settings.project(":brick-codegen").projectDir = brickDir
|
|
150
280
|
}
|
|
151
281
|
|
|
152
282
|
if (!foundModules.isEmpty()) {
|
|
@@ -184,8 +314,8 @@ def configureBrickModules(project) {
|
|
|
184
314
|
project.android.sourceSets.main.java.srcDir "${project.buildDir}/generated/source/brick-provider"
|
|
185
315
|
|
|
186
316
|
// Create provider generation task
|
|
187
|
-
project.tasks.create('
|
|
188
|
-
description = 'Generates
|
|
317
|
+
project.tasks.create('generateBrickModulesList') {
|
|
318
|
+
description = 'Generates BrickModulesList class for module injection in MainActivity'
|
|
189
319
|
group = 'brick-module'
|
|
190
320
|
|
|
191
321
|
doLast {
|
|
@@ -194,7 +324,7 @@ def configureBrickModules(project) {
|
|
|
194
324
|
}
|
|
195
325
|
|
|
196
326
|
// Hook into build process
|
|
197
|
-
project.preBuild.dependsOn('
|
|
327
|
+
project.preBuild.dependsOn('generateBrickModulesList')
|
|
198
328
|
project.preBuild.doFirst {
|
|
199
329
|
def workingDir = projectRoot
|
|
200
330
|
|
|
@@ -223,8 +353,39 @@ def configureBrickModules(project) {
|
|
|
223
353
|
// Add dependencies
|
|
224
354
|
project.dependencies {
|
|
225
355
|
// Add brick module dependencies
|
|
356
|
+
brickLog("🔍 Processing subprojects for dependencies...")
|
|
357
|
+
brickLog("📋 Available brick modules: ${brickModulesData.keySet()}")
|
|
358
|
+
|
|
359
|
+
brickLog("🔍 Available subprojects: ${rootProject.subprojects.collect { it.name }}")
|
|
360
|
+
|
|
226
361
|
rootProject.subprojects.each { subproject ->
|
|
227
|
-
|
|
362
|
+
// Try to find matching brick module by normalizing names
|
|
363
|
+
def foundModule = null
|
|
364
|
+
def normalizedSubprojectName = subproject.name.replaceAll('[-_]', '') // Remove both - and _
|
|
365
|
+
|
|
366
|
+
brickModulesData.each { moduleKey, moduleData ->
|
|
367
|
+
def normalizedModuleKey = moduleKey.replaceAll('[@/-]', '')
|
|
368
|
+
|
|
369
|
+
if (normalizedSubprojectName == normalizedModuleKey) {
|
|
370
|
+
foundModule = moduleKey
|
|
371
|
+
return
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (foundModule) {
|
|
376
|
+
brickLog("✅ Adding brick module dependency: ${foundModule} (matched with ${subproject.name})")
|
|
377
|
+
add('implementation', subproject)
|
|
378
|
+
} else if (brickModulesData.containsKey(subproject.name)) {
|
|
379
|
+
brickLog("✅ Adding brick module dependency: ${subproject.name}")
|
|
380
|
+
add('implementation', subproject)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (subproject.name == 'brick-module') {
|
|
384
|
+
brickLog("✅ Adding brick-module dependency")
|
|
385
|
+
add('implementation', subproject)
|
|
386
|
+
}
|
|
387
|
+
if (subproject.name == 'brick-codegen') {
|
|
388
|
+
brickLog("✅ Adding brick-codegen dependency")
|
|
228
389
|
add('implementation', subproject)
|
|
229
390
|
}
|
|
230
391
|
}
|
|
@@ -236,12 +397,11 @@ def configureBrickModules(project) {
|
|
|
236
397
|
}
|
|
237
398
|
}
|
|
238
399
|
|
|
239
|
-
// Generate
|
|
400
|
+
// Generate BrickModulesList.kt
|
|
240
401
|
def generateProvider(project, brickModulesData) {
|
|
241
402
|
def modules = brickModulesData.collect { name, data ->
|
|
242
403
|
[
|
|
243
|
-
|
|
244
|
-
className: data.moduleName + "Module",
|
|
404
|
+
moduleName: data.moduleName,
|
|
245
405
|
packageName: data.packageName
|
|
246
406
|
]
|
|
247
407
|
}
|
|
@@ -249,31 +409,62 @@ def generateProvider(project, brickModulesData) {
|
|
|
249
409
|
def outputDir = project.file("${project.buildDir}/generated/source/brick-provider/com/brickmodule")
|
|
250
410
|
outputDir.mkdirs()
|
|
251
411
|
|
|
252
|
-
def imports = modules.collect { "import ${it.packageName}.${it.
|
|
253
|
-
def moduleInstances = modules.collect { " ${it.
|
|
254
|
-
def moduleNames = modules.collect { " \"${it.
|
|
412
|
+
def imports = modules.collect { "import ${it.packageName}.${it.moduleName}" }.join("\n")
|
|
413
|
+
def moduleInstances = modules.collect { " ${it.moduleName}(context)" }.join(",\n")
|
|
414
|
+
def moduleNames = modules.collect { " \"${it.moduleName}\"" }.join(",\n")
|
|
255
415
|
|
|
256
|
-
new File(outputDir, "
|
|
416
|
+
new File(outputDir, "BrickModulesList.kt").text = """// Auto-generated by brick_modules.gradle
|
|
257
417
|
package com.brickmodule
|
|
258
418
|
|
|
259
|
-
import com.
|
|
419
|
+
import com.facebook.react.bridge.ReactContext
|
|
260
420
|
${imports}
|
|
261
421
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
422
|
+
/**
|
|
423
|
+
* Auto-generated helper for brick modules
|
|
424
|
+
* Use this class to get auto-linked modules in your MainActivity
|
|
425
|
+
*
|
|
426
|
+
* Example usage:
|
|
427
|
+
* ```kotlin
|
|
428
|
+
* override fun getBrickModules(context: ReactContext): List<BrickModuleBase> {
|
|
429
|
+
* return BrickModulesList(context).modules
|
|
430
|
+
* }
|
|
431
|
+
* ```
|
|
432
|
+
*/
|
|
433
|
+
class BrickModulesList(private val context: ReactContext) {
|
|
434
|
+
/**
|
|
435
|
+
* Get all auto-linked brick modules
|
|
436
|
+
*
|
|
437
|
+
* @return List of auto-linked module instances
|
|
438
|
+
*/
|
|
439
|
+
val modules: List<BrickModuleBase> by lazy {
|
|
440
|
+
listOf<BrickModuleBase>(
|
|
265
441
|
${moduleInstances}
|
|
266
442
|
)
|
|
267
|
-
|
|
268
|
-
if (modules.isNotEmpty()) {
|
|
269
|
-
BrickModuleRegistry.register(modules)
|
|
270
|
-
println("🧱 BrickModuleProvider: Registered \${modules.size} modules")
|
|
271
|
-
}
|
|
272
443
|
}
|
|
273
444
|
|
|
274
|
-
|
|
445
|
+
/**
|
|
446
|
+
* Get available module names (for debugging)
|
|
447
|
+
*
|
|
448
|
+
* @return List of module names
|
|
449
|
+
*/
|
|
450
|
+
val availableModules: List<String> = listOf(
|
|
275
451
|
${moduleNames}
|
|
276
452
|
)
|
|
453
|
+
|
|
454
|
+
companion object {
|
|
455
|
+
/**
|
|
456
|
+
* Legacy static method for backward compatibility
|
|
457
|
+
* @deprecated Use BrickModulesList(context).modules instead
|
|
458
|
+
*/
|
|
459
|
+
@Deprecated(
|
|
460
|
+
message = "Use BrickModulesList(context).modules instead",
|
|
461
|
+
replaceWith = ReplaceWith("BrickModulesList(context).modules")
|
|
462
|
+
)
|
|
463
|
+
@JvmStatic
|
|
464
|
+
fun getAutolinkedModules(context: ReactContext): MutableList<Any> {
|
|
465
|
+
return BrickModulesList(context).modules.toMutableList() as MutableList<Any>
|
|
466
|
+
}
|
|
467
|
+
}
|
|
277
468
|
}
|
|
278
469
|
"""
|
|
279
470
|
}
|
package/android/build.gradle
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
buildscript {
|
|
2
2
|
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
3
|
-
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["
|
|
3
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["BrickModule_kotlinVersion"]
|
|
4
4
|
|
|
5
5
|
repositories {
|
|
6
6
|
google()
|
|
@@ -8,7 +8,7 @@ buildscript {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
dependencies {
|
|
11
|
-
classpath "com.android.tools.build:gradle:
|
|
11
|
+
classpath "com.android.tools.build:gradle:8.2.0"
|
|
12
12
|
// noinspection DifferentKotlinGradleVersion
|
|
13
13
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
14
14
|
|
|
@@ -103,10 +103,10 @@ dependencies {
|
|
|
103
103
|
//noinspection GradleDynamicVersion
|
|
104
104
|
if (project.ext.shouldConsumeReactNativeFromMavenCentral()) {
|
|
105
105
|
// noinspection GradleDynamicVersion
|
|
106
|
-
|
|
106
|
+
api 'com.facebook.react:react-android:+'
|
|
107
107
|
} else {
|
|
108
108
|
// noinspection GradleDynamicVersion
|
|
109
|
-
|
|
109
|
+
api 'com.facebook.react:react-native:+'
|
|
110
110
|
}
|
|
111
111
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
112
112
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
|
|
Binary file
|
package/android/gradlew
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright © 2015-2021 the original authors.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
##############################################################################
|
|
22
|
+
#
|
|
23
|
+
# Gradle start up script for POSIX generated by Gradle.
|
|
24
|
+
#
|
|
25
|
+
# Important for running:
|
|
26
|
+
#
|
|
27
|
+
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
|
28
|
+
# noncompliant, but you have some other compliant shell such as ksh or
|
|
29
|
+
# bash, then to run this script, type that shell name before the whole
|
|
30
|
+
# command line, like:
|
|
31
|
+
#
|
|
32
|
+
# ksh Gradle
|
|
33
|
+
#
|
|
34
|
+
# Busybox and similar reduced shells will NOT work, because this script
|
|
35
|
+
# requires all of these POSIX shell features:
|
|
36
|
+
# * functions;
|
|
37
|
+
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
|
38
|
+
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
|
39
|
+
# * compound commands having a testable exit status, especially «case»;
|
|
40
|
+
# * various built-in commands including «command», «set», and «ulimit».
|
|
41
|
+
#
|
|
42
|
+
# Important for patching:
|
|
43
|
+
#
|
|
44
|
+
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
|
45
|
+
# by Bash, Ksh, etc; in particular arrays are avoided.
|
|
46
|
+
#
|
|
47
|
+
# The "traditional" practice of packing multiple parameters into a
|
|
48
|
+
# space-separated string is a well documented source of bugs and security
|
|
49
|
+
# problems, so this is (mostly) avoided, by progressively accumulating
|
|
50
|
+
# options in "$@", and eventually passing that to Java.
|
|
51
|
+
#
|
|
52
|
+
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
|
53
|
+
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
|
54
|
+
# see the in-line comments for details.
|
|
55
|
+
#
|
|
56
|
+
# There are tweaks for specific operating systems such as AIX, CygWin,
|
|
57
|
+
# Darwin, MinGW, and NonStop.
|
|
58
|
+
#
|
|
59
|
+
# (3) This script is generated from the Groovy template
|
|
60
|
+
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
|
61
|
+
# within the Gradle project.
|
|
62
|
+
#
|
|
63
|
+
# You can find Gradle at https://github.com/gradle/gradle/.
|
|
64
|
+
#
|
|
65
|
+
##############################################################################
|
|
66
|
+
|
|
67
|
+
# Attempt to set APP_HOME
|
|
68
|
+
|
|
69
|
+
# Resolve links: $0 may be a link
|
|
70
|
+
app_path=$0
|
|
71
|
+
|
|
72
|
+
# Need this for daisy-chained symlinks.
|
|
73
|
+
while
|
|
74
|
+
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
|
75
|
+
[ -h "$app_path" ]
|
|
76
|
+
do
|
|
77
|
+
ls=$( ls -ld "$app_path" )
|
|
78
|
+
link=${ls#*' -> '}
|
|
79
|
+
case $link in #(
|
|
80
|
+
/*) app_path=$link ;; #(
|
|
81
|
+
*) app_path=$APP_HOME$link ;;
|
|
82
|
+
esac
|
|
83
|
+
done
|
|
84
|
+
|
|
85
|
+
# This is normally unused
|
|
86
|
+
# shellcheck disable=SC2034
|
|
87
|
+
APP_BASE_NAME=${0##*/}
|
|
88
|
+
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
|
89
|
+
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
|
90
|
+
' "$PWD" ) || exit
|
|
91
|
+
|
|
92
|
+
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
93
|
+
MAX_FD=maximum
|
|
94
|
+
|
|
95
|
+
warn () {
|
|
96
|
+
echo "$*"
|
|
97
|
+
} >&2
|
|
98
|
+
|
|
99
|
+
die () {
|
|
100
|
+
echo
|
|
101
|
+
echo "$*"
|
|
102
|
+
echo
|
|
103
|
+
exit 1
|
|
104
|
+
} >&2
|
|
105
|
+
|
|
106
|
+
# OS specific support (must be 'true' or 'false').
|
|
107
|
+
cygwin=false
|
|
108
|
+
msys=false
|
|
109
|
+
darwin=false
|
|
110
|
+
nonstop=false
|
|
111
|
+
case "$( uname )" in #(
|
|
112
|
+
CYGWIN* ) cygwin=true ;; #(
|
|
113
|
+
Darwin* ) darwin=true ;; #(
|
|
114
|
+
MSYS* | MINGW* ) msys=true ;; #(
|
|
115
|
+
NONSTOP* ) nonstop=true ;;
|
|
116
|
+
esac
|
|
117
|
+
|
|
118
|
+
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# Determine the Java command to use to start the JVM.
|
|
122
|
+
if [ -n "$JAVA_HOME" ] ; then
|
|
123
|
+
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
124
|
+
# IBM's JDK on AIX uses strange locations for the executables
|
|
125
|
+
JAVACMD=$JAVA_HOME/jre/sh/java
|
|
126
|
+
else
|
|
127
|
+
JAVACMD=$JAVA_HOME/bin/java
|
|
128
|
+
fi
|
|
129
|
+
if [ ! -x "$JAVACMD" ] ; then
|
|
130
|
+
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
131
|
+
|
|
132
|
+
Please set the JAVA_HOME variable in your environment to match the
|
|
133
|
+
location of your Java installation."
|
|
134
|
+
fi
|
|
135
|
+
else
|
|
136
|
+
JAVACMD=java
|
|
137
|
+
if ! command -v java >/dev/null 2>&1
|
|
138
|
+
then
|
|
139
|
+
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
140
|
+
|
|
141
|
+
Please set the JAVA_HOME variable in your environment to match the
|
|
142
|
+
location of your Java installation."
|
|
143
|
+
fi
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# Increase the maximum file descriptors if we can.
|
|
147
|
+
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|
148
|
+
case $MAX_FD in #(
|
|
149
|
+
max*)
|
|
150
|
+
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
|
151
|
+
# shellcheck disable=SC2039,SC3045
|
|
152
|
+
MAX_FD=$( ulimit -H -n ) ||
|
|
153
|
+
warn "Could not query maximum file descriptor limit"
|
|
154
|
+
esac
|
|
155
|
+
case $MAX_FD in #(
|
|
156
|
+
'' | soft) :;; #(
|
|
157
|
+
*)
|
|
158
|
+
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
|
159
|
+
# shellcheck disable=SC2039,SC3045
|
|
160
|
+
ulimit -n "$MAX_FD" ||
|
|
161
|
+
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
|
162
|
+
esac
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Collect all arguments for the java command, stacking in reverse order:
|
|
166
|
+
# * args from the command line
|
|
167
|
+
# * the main class name
|
|
168
|
+
# * -classpath
|
|
169
|
+
# * -D...appname settings
|
|
170
|
+
# * --module-path (only if needed)
|
|
171
|
+
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
|
172
|
+
|
|
173
|
+
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
174
|
+
if "$cygwin" || "$msys" ; then
|
|
175
|
+
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
|
176
|
+
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
177
|
+
|
|
178
|
+
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
|
179
|
+
|
|
180
|
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
181
|
+
for arg do
|
|
182
|
+
if
|
|
183
|
+
case $arg in #(
|
|
184
|
+
-*) false ;; # don't mess with options #(
|
|
185
|
+
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
|
186
|
+
[ -e "$t" ] ;; #(
|
|
187
|
+
*) false ;;
|
|
188
|
+
esac
|
|
189
|
+
then
|
|
190
|
+
arg=$( cygpath --path --ignore --mixed "$arg" )
|
|
191
|
+
fi
|
|
192
|
+
# Roll the args list around exactly as many times as the number of
|
|
193
|
+
# args, so each arg winds up back in the position where it started, but
|
|
194
|
+
# possibly modified.
|
|
195
|
+
#
|
|
196
|
+
# NB: a `for` loop captures its iteration list before it begins, so
|
|
197
|
+
# changing the positional parameters here affects neither the number of
|
|
198
|
+
# iterations, nor the values presented in `arg`.
|
|
199
|
+
shift # remove old arg
|
|
200
|
+
set -- "$@" "$arg" # push replacement arg
|
|
201
|
+
done
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
206
|
+
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
207
|
+
|
|
208
|
+
# Collect all arguments for the java command:
|
|
209
|
+
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
|
210
|
+
# and any embedded shellness will be escaped.
|
|
211
|
+
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
|
212
|
+
# treated as '${Hostname}' itself on the command line.
|
|
213
|
+
|
|
214
|
+
set -- \
|
|
215
|
+
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
|
216
|
+
-classpath "$CLASSPATH" \
|
|
217
|
+
org.gradle.wrapper.GradleWrapperMain \
|
|
218
|
+
"$@"
|
|
219
|
+
|
|
220
|
+
# Stop when "xargs" is not available.
|
|
221
|
+
if ! command -v xargs >/dev/null 2>&1
|
|
222
|
+
then
|
|
223
|
+
die "xargs is not available"
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
# Use "xargs" to parse quoted args.
|
|
227
|
+
#
|
|
228
|
+
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
|
229
|
+
#
|
|
230
|
+
# In Bash we could simply go:
|
|
231
|
+
#
|
|
232
|
+
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
|
233
|
+
# set -- "${ARGS[@]}" "$@"
|
|
234
|
+
#
|
|
235
|
+
# but POSIX shell has neither arrays nor command substitution, so instead we
|
|
236
|
+
# post-process each arg (as a line of input to sed) to backslash-escape any
|
|
237
|
+
# character that might be a shell metacharacter, then use eval to reverse
|
|
238
|
+
# that process (while maintaining the separation between arguments), and wrap
|
|
239
|
+
# the whole thing up as a single "set" statement.
|
|
240
|
+
#
|
|
241
|
+
# This will of course break if any of these variables contains a newline or
|
|
242
|
+
# an unmatched quote.
|
|
243
|
+
#
|
|
244
|
+
|
|
245
|
+
eval "set -- $(
|
|
246
|
+
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
|
247
|
+
xargs -n1 |
|
|
248
|
+
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
|
249
|
+
tr '\n' ' '
|
|
250
|
+
)" '"$@"'
|
|
251
|
+
|
|
252
|
+
exec "$JAVACMD" "$@"
|