Merge changes Ifbf9fe27,I41a6cd42,Ieae59efb
* changes: Allow some duplicates in merged jars Add support for java annotation processors Update java androidmk conversions
This commit is contained in:
@@ -76,6 +76,7 @@ func init() {
|
|||||||
"LOCAL_MODULE_OWNER": "owner",
|
"LOCAL_MODULE_OWNER": "owner",
|
||||||
"LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
|
"LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
|
||||||
"LOCAL_NOTICE_FILE": "notice",
|
"LOCAL_NOTICE_FILE": "notice",
|
||||||
|
"LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
|
||||||
})
|
})
|
||||||
addStandardProperties(bpparser.ListType,
|
addStandardProperties(bpparser.ListType,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
@@ -114,6 +115,9 @@ func init() {
|
|||||||
"LOCAL_AAPT_FLAGS": "aaptflags",
|
"LOCAL_AAPT_FLAGS": "aaptflags",
|
||||||
"LOCAL_PACKAGE_SPLITS": "package_splits",
|
"LOCAL_PACKAGE_SPLITS": "package_splits",
|
||||||
"LOCAL_COMPATIBILITY_SUITE": "test_suites",
|
"LOCAL_COMPATIBILITY_SUITE": "test_suites",
|
||||||
|
|
||||||
|
"LOCAL_ANNOTATION_PROCESSORS": "annotation_processors",
|
||||||
|
"LOCAL_ANNOTATION_PROCESSOR_CLASSES": "annotation_processor_classes",
|
||||||
})
|
})
|
||||||
addStandardProperties(bpparser.BoolType,
|
addStandardProperties(bpparser.BoolType,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
@@ -685,7 +689,7 @@ var prebuiltTypes = map[string]string{
|
|||||||
"SHARED_LIBRARIES": "cc_prebuilt_library_shared",
|
"SHARED_LIBRARIES": "cc_prebuilt_library_shared",
|
||||||
"STATIC_LIBRARIES": "cc_prebuilt_library_static",
|
"STATIC_LIBRARIES": "cc_prebuilt_library_static",
|
||||||
"EXECUTABLES": "cc_prebuilt_binary",
|
"EXECUTABLES": "cc_prebuilt_binary",
|
||||||
"JAVA_LIBRARIES": "prebuilt_java_library",
|
"JAVA_LIBRARIES": "java_import",
|
||||||
}
|
}
|
||||||
|
|
||||||
var soongModuleTypes = map[string]bool{}
|
var soongModuleTypes = map[string]bool{}
|
||||||
|
@@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
sortEntries = flag.Bool("s", false, "sort entries (defaults to the order from the input zip files)")
|
sortEntries = flag.Bool("s", false, "sort entries (defaults to the order from the input zip files)")
|
||||||
sortJava = flag.Bool("j", false, "sort zip entries using jar ordering (META-INF first)")
|
emulateJar = flag.Bool("j", false, "sort zip entries using jar ordering (META-INF first)")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -76,7 +76,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// do merge
|
// do merge
|
||||||
if err := mergeZips(readers, writer, *sortEntries, *sortJava); err != nil {
|
if err := mergeZips(readers, writer, *sortEntries, *emulateJar); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ type fileMapping struct {
|
|||||||
dest string
|
dest string
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergeZips(readers []namedZipReader, writer *zip.Writer, sortEntries bool, sortJava bool) error {
|
func mergeZips(readers []namedZipReader, writer *zip.Writer, sortEntries bool, emulateJar bool) error {
|
||||||
|
|
||||||
mappingsByDest := make(map[string]fileMapping, 0)
|
mappingsByDest := make(map[string]fileMapping, 0)
|
||||||
orderedMappings := []fileMapping{}
|
orderedMappings := []fileMapping{}
|
||||||
@@ -128,24 +128,33 @@ func mergeZips(readers []namedZipReader, writer *zip.Writer, sortEntries bool, s
|
|||||||
source := zipEntry{path: zipEntryPath{zipName: namedReader.path, entryName: file.Name}, content: file}
|
source := zipEntry{path: zipEntryPath{zipName: namedReader.path, entryName: file.Name}, content: file}
|
||||||
newMapping := fileMapping{source: source, dest: dest}
|
newMapping := fileMapping{source: source, dest: dest}
|
||||||
|
|
||||||
// handle duplicates
|
|
||||||
if exists {
|
if exists {
|
||||||
|
// handle duplicates
|
||||||
wasDir := existingMapping.source.content.FileHeader.FileInfo().IsDir()
|
wasDir := existingMapping.source.content.FileHeader.FileInfo().IsDir()
|
||||||
isDir := newMapping.source.content.FileHeader.FileInfo().IsDir()
|
isDir := newMapping.source.content.FileHeader.FileInfo().IsDir()
|
||||||
if !wasDir || !isDir {
|
if wasDir != isDir {
|
||||||
|
return fmt.Errorf("Directory/file mismatch at %v from %v and %v\n",
|
||||||
|
dest, existingMapping.source.path, newMapping.source.path)
|
||||||
|
}
|
||||||
|
if emulateJar &&
|
||||||
|
file.Name == jar.ManifestFile || file.Name == jar.ModuleInfoClass {
|
||||||
|
// Skip manifest and module info files that are not from the first input file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !isDir {
|
||||||
return fmt.Errorf("Duplicate path %v found in %v and %v\n",
|
return fmt.Errorf("Duplicate path %v found in %v and %v\n",
|
||||||
dest, existingMapping.source.path, newMapping.source.path)
|
dest, existingMapping.source.path, newMapping.source.path)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
// save entry
|
// save entry
|
||||||
mappingsByDest[mapKey] = newMapping
|
mappingsByDest[mapKey] = newMapping
|
||||||
orderedMappings = append(orderedMappings, newMapping)
|
orderedMappings = append(orderedMappings, newMapping)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if sortJava {
|
if emulateJar {
|
||||||
jarSort(orderedMappings)
|
jarSort(orderedMappings)
|
||||||
} else if sortEntries {
|
} else if sortEntries {
|
||||||
alphanumericSort(orderedMappings)
|
alphanumericSort(orderedMappings)
|
||||||
|
@@ -62,9 +62,6 @@ type byteReaderCloser struct {
|
|||||||
io.Closer
|
io.Closer
|
||||||
}
|
}
|
||||||
|
|
||||||
// the file path in the zip at which a Java manifest file gets written
|
|
||||||
const manifestDest = "META-INF/MANIFEST.MF"
|
|
||||||
|
|
||||||
type fileArg struct {
|
type fileArg struct {
|
||||||
pathPrefixInZip, sourcePrefixToStrip string
|
pathPrefixInZip, sourcePrefixToStrip string
|
||||||
sourceFiles []string
|
sourceFiles []string
|
||||||
@@ -360,7 +357,7 @@ func (z *zipWriter) write(out string, pathMappings []pathMapping, manifest strin
|
|||||||
if !*emulateJar {
|
if !*emulateJar {
|
||||||
return errors.New("must specify --jar when specifying a manifest via -m")
|
return errors.New("must specify --jar when specifying a manifest via -m")
|
||||||
}
|
}
|
||||||
pathMappings = append(pathMappings, pathMapping{manifestDest, manifest, zip.Deflate})
|
pathMappings = append(pathMappings, pathMapping{jar.ManifestFile, manifest, zip.Deflate})
|
||||||
}
|
}
|
||||||
|
|
||||||
if *emulateJar {
|
if *emulateJar {
|
||||||
@@ -372,7 +369,7 @@ func (z *zipWriter) write(out string, pathMappings []pathMapping, manifest strin
|
|||||||
defer close(z.writeOps)
|
defer close(z.writeOps)
|
||||||
|
|
||||||
for _, ele := range pathMappings {
|
for _, ele := range pathMappings {
|
||||||
if *emulateJar && ele.dest == manifestDest {
|
if *emulateJar && ele.dest == jar.ManifestFile {
|
||||||
err = z.addManifest(ele.dest, ele.src, ele.zipMethod)
|
err = z.addManifest(ele.dest, ele.src, ele.zipMethod)
|
||||||
} else {
|
} else {
|
||||||
err = z.addFile(ele.dest, ele.src, ele.zipMethod)
|
err = z.addFile(ele.dest, ele.src, ele.zipMethod)
|
||||||
|
12
jar/jar.go
12
jar/jar.go
@@ -19,6 +19,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MetaDir = "META-INF/"
|
||||||
|
ManifestFile = MetaDir + "MANIFEST.MF"
|
||||||
|
ModuleInfoClass = "module-info.class"
|
||||||
|
)
|
||||||
|
|
||||||
// EntryNamesLess tells whether <filepathA> should precede <filepathB> in
|
// EntryNamesLess tells whether <filepathA> should precede <filepathB> in
|
||||||
// the order of files with a .jar
|
// the order of files with a .jar
|
||||||
func EntryNamesLess(filepathA string, filepathB string) (less bool) {
|
func EntryNamesLess(filepathA string, filepathB string) (less bool) {
|
||||||
@@ -39,9 +45,9 @@ func patternMatch(pattern, name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var jarOrder = []string{
|
var jarOrder = []string{
|
||||||
"META-INF/",
|
MetaDir,
|
||||||
"META-INF/MANIFEST.MF",
|
ManifestFile,
|
||||||
"META-INF/*",
|
MetaDir + "*",
|
||||||
"*",
|
"*",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
81
java/java.go
81
java/java.go
@@ -99,6 +99,12 @@ type CompilerProperties struct {
|
|||||||
|
|
||||||
// If set to false, don't allow this module to be installed. Defaults to true.
|
// If set to false, don't allow this module to be installed. Defaults to true.
|
||||||
Installable *bool
|
Installable *bool
|
||||||
|
|
||||||
|
// List of modules to use as annotation processors
|
||||||
|
Annotation_processors []string
|
||||||
|
|
||||||
|
// List of classes to pass to javac to use as annotation processors
|
||||||
|
Annotation_processor_classes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompilerDeviceProperties struct {
|
type CompilerDeviceProperties struct {
|
||||||
@@ -167,6 +173,7 @@ var (
|
|||||||
bootClasspathTag = dependencyTag{name: "bootclasspath"}
|
bootClasspathTag = dependencyTag{name: "bootclasspath"}
|
||||||
frameworkResTag = dependencyTag{name: "framework-res"}
|
frameworkResTag = dependencyTag{name: "framework-res"}
|
||||||
sdkDependencyTag = dependencyTag{name: "sdk"}
|
sdkDependencyTag = dependencyTag{name: "sdk"}
|
||||||
|
annotationProcessorTag = dependencyTag{name: "annotation processor"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
|
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
|
||||||
@@ -195,6 +202,7 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
|
|||||||
}
|
}
|
||||||
ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
|
ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
|
||||||
ctx.AddDependency(ctx.Module(), staticLibTag, j.properties.Static_libs...)
|
ctx.AddDependency(ctx.Module(), staticLibTag, j.properties.Static_libs...)
|
||||||
|
ctx.AddDependency(ctx.Module(), annotationProcessorTag, j.properties.Annotation_processors...)
|
||||||
|
|
||||||
android.ExtractSourcesDeps(ctx, j.properties.Srcs)
|
android.ExtractSourcesDeps(ctx, j.properties.Srcs)
|
||||||
}
|
}
|
||||||
@@ -221,9 +229,18 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt
|
|||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Module) collectDeps(ctx android.ModuleContext) (classpath, bootClasspath, staticJars,
|
type deps struct {
|
||||||
aidlIncludeDirs, srcFileLists android.Paths, aidlPreprocess android.OptionalPath) {
|
classpath android.Paths
|
||||||
|
bootClasspath android.Paths
|
||||||
|
staticJars android.Paths
|
||||||
|
aidlIncludeDirs android.Paths
|
||||||
|
srcFileLists android.Paths
|
||||||
|
annotationProcessors android.Paths
|
||||||
|
aidlPreprocess android.OptionalPath
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
||||||
|
var deps deps
|
||||||
ctx.VisitDirectDeps(func(module blueprint.Module) {
|
ctx.VisitDirectDeps(func(module blueprint.Module) {
|
||||||
otherName := ctx.OtherModuleName(module)
|
otherName := ctx.OtherModuleName(module)
|
||||||
tag := ctx.OtherModuleDependencyTag(module)
|
tag := ctx.OtherModuleDependencyTag(module)
|
||||||
@@ -240,50 +257,60 @@ func (j *Module) collectDeps(ctx android.ModuleContext) (classpath, bootClasspat
|
|||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case bootClasspathTag:
|
case bootClasspathTag:
|
||||||
bootClasspath = append(bootClasspath, dep.ClasspathFiles()...)
|
deps.bootClasspath = append(deps.bootClasspath, dep.ClasspathFiles()...)
|
||||||
case libTag:
|
case libTag:
|
||||||
classpath = append(classpath, dep.ClasspathFiles()...)
|
deps.classpath = append(deps.classpath, dep.ClasspathFiles()...)
|
||||||
case staticLibTag:
|
case staticLibTag:
|
||||||
classpath = append(classpath, dep.ClasspathFiles()...)
|
deps.classpath = append(deps.classpath, dep.ClasspathFiles()...)
|
||||||
staticJars = append(staticJars, dep.ClasspathFiles()...)
|
deps.staticJars = append(deps.staticJars, dep.ClasspathFiles()...)
|
||||||
|
case annotationProcessorTag:
|
||||||
|
deps.annotationProcessors = append(deps.annotationProcessors, dep.ClasspathFiles()...)
|
||||||
case frameworkResTag:
|
case frameworkResTag:
|
||||||
if ctx.ModuleName() == "framework" {
|
if ctx.ModuleName() == "framework" {
|
||||||
// framework.jar has a one-off dependency on the R.java and Manifest.java files
|
// framework.jar has a one-off dependency on the R.java and Manifest.java files
|
||||||
// generated by framework-res.apk
|
// generated by framework-res.apk
|
||||||
srcFileLists = append(srcFileLists, module.(*AndroidApp).aaptJavaFileList)
|
deps.srcFileLists = append(deps.srcFileLists, module.(*AndroidApp).aaptJavaFileList)
|
||||||
}
|
}
|
||||||
case sdkDependencyTag:
|
case sdkDependencyTag:
|
||||||
sdkDep := module.(sdkDependency)
|
sdkDep := module.(sdkDependency)
|
||||||
bootClasspath = append(bootClasspath, sdkDep.ClasspathFiles()...)
|
deps.bootClasspath = append(deps.bootClasspath, sdkDep.ClasspathFiles()...)
|
||||||
if sdkDep.AidlPreprocessed().Valid() {
|
if sdkDep.AidlPreprocessed().Valid() {
|
||||||
if aidlPreprocess.Valid() {
|
if deps.aidlPreprocess.Valid() {
|
||||||
ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
|
ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
|
||||||
aidlPreprocess, sdkDep.AidlPreprocessed())
|
deps.aidlPreprocess, sdkDep.AidlPreprocessed())
|
||||||
} else {
|
} else {
|
||||||
aidlPreprocess = sdkDep.AidlPreprocessed()
|
deps.aidlPreprocess = sdkDep.AidlPreprocessed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
|
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
|
||||||
}
|
}
|
||||||
|
|
||||||
aidlIncludeDirs = append(aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return deps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Module) compile(ctx android.ModuleContext) {
|
func (j *Module) compile(ctx android.ModuleContext) {
|
||||||
|
|
||||||
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs)
|
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs)
|
||||||
|
|
||||||
classpath, bootClasspath, staticJars, aidlIncludeDirs, srcFileLists,
|
deps := j.collectDeps(ctx)
|
||||||
aidlPreprocess := j.collectDeps(ctx)
|
|
||||||
|
|
||||||
var flags javaBuilderFlags
|
var flags javaBuilderFlags
|
||||||
|
|
||||||
javacFlags := j.properties.Javacflags
|
javacFlags := j.properties.Javacflags
|
||||||
|
|
||||||
|
if len(deps.annotationProcessors) > 0 {
|
||||||
|
javacFlags = append(javacFlags,
|
||||||
|
"-processorpath "+strings.Join(deps.annotationProcessors.Strings(), ":"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range j.properties.Annotation_processor_classes {
|
||||||
|
javacFlags = append(javacFlags, "-processor "+c)
|
||||||
|
}
|
||||||
|
|
||||||
if j.properties.Java_version != nil {
|
if j.properties.Java_version != nil {
|
||||||
flags.javaVersion = *j.properties.Java_version
|
flags.javaVersion = *j.properties.Java_version
|
||||||
} else {
|
} else {
|
||||||
@@ -295,25 +322,25 @@ func (j *Module) compile(ctx android.ModuleContext) {
|
|||||||
flags.javacFlags = "$javacFlags"
|
flags.javacFlags = "$javacFlags"
|
||||||
}
|
}
|
||||||
|
|
||||||
aidlFlags := j.aidlFlags(ctx, aidlPreprocess, aidlIncludeDirs)
|
aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
|
||||||
if len(aidlFlags) > 0 {
|
if len(aidlFlags) > 0 {
|
||||||
ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
|
ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
|
||||||
flags.aidlFlags = "$aidlFlags"
|
flags.aidlFlags = "$aidlFlags"
|
||||||
}
|
}
|
||||||
|
|
||||||
var deps android.Paths
|
var extraDeps android.Paths
|
||||||
|
|
||||||
if len(bootClasspath) > 0 {
|
if len(deps.bootClasspath) > 0 {
|
||||||
flags.bootClasspath = "-bootclasspath " + strings.Join(bootClasspath.Strings(), ":")
|
flags.bootClasspath = "-bootclasspath " + strings.Join(deps.bootClasspath.Strings(), ":")
|
||||||
deps = append(deps, bootClasspath...)
|
extraDeps = append(extraDeps, deps.bootClasspath...)
|
||||||
} else if ctx.Device() {
|
} else if ctx.Device() {
|
||||||
// Explicitly clear the bootclasspath for device builds
|
// Explicitly clear the bootclasspath for device builds
|
||||||
flags.bootClasspath = `-bootclasspath ""`
|
flags.bootClasspath = `-bootclasspath ""`
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(classpath) > 0 {
|
if len(deps.classpath) > 0 {
|
||||||
flags.classpath = "-classpath " + strings.Join(classpath.Strings(), ":")
|
flags.classpath = "-classpath " + strings.Join(deps.classpath.Strings(), ":")
|
||||||
deps = append(deps, classpath...)
|
extraDeps = append(extraDeps, deps.classpath...)
|
||||||
}
|
}
|
||||||
|
|
||||||
srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
|
srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
|
||||||
@@ -326,7 +353,7 @@ func (j *Module) compile(ctx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
srcFileLists = append(srcFileLists, j.ExtraSrcLists...)
|
deps.srcFileLists = append(deps.srcFileLists, j.ExtraSrcLists...)
|
||||||
|
|
||||||
var extraJarDeps android.Paths
|
var extraJarDeps android.Paths
|
||||||
|
|
||||||
@@ -334,7 +361,7 @@ func (j *Module) compile(ctx android.ModuleContext) {
|
|||||||
|
|
||||||
if len(srcFiles) > 0 {
|
if len(srcFiles) > 0 {
|
||||||
// Compile java sources into .class files
|
// Compile java sources into .class files
|
||||||
classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, deps)
|
classes := TransformJavaToClasses(ctx, srcFiles, deps.srcFileLists, flags, extraDeps)
|
||||||
if ctx.Failed() {
|
if ctx.Failed() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -346,7 +373,7 @@ func (j *Module) compile(ctx android.ModuleContext) {
|
|||||||
// the jar command so the two compiles can run in parallel.
|
// the jar command so the two compiles can run in parallel.
|
||||||
// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
|
// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
|
||||||
// enable error-prone without affecting the output class files.
|
// enable error-prone without affecting the output class files.
|
||||||
errorprone := RunErrorProne(ctx, srcFiles, srcFileLists, flags, deps)
|
errorprone := RunErrorProne(ctx, srcFiles, deps.srcFileLists, flags, extraDeps)
|
||||||
extraJarDeps = append(extraJarDeps, errorprone)
|
extraJarDeps = append(extraJarDeps, errorprone)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +393,7 @@ func (j *Module) compile(ctx android.ModuleContext) {
|
|||||||
jars = append(jars, resourceJar)
|
jars = append(jars, resourceJar)
|
||||||
}
|
}
|
||||||
|
|
||||||
jars = append(jars, staticJars...)
|
jars = append(jars, deps.staticJars...)
|
||||||
|
|
||||||
// Combine the classes built from sources, any manifests, and any static libraries into
|
// Combine the classes built from sources, any manifests, and any static libraries into
|
||||||
// classes-combined.jar. If there is only one input jar this step will be skipped.
|
// classes-combined.jar. If there is only one input jar this step will be skipped.
|
||||||
|
Reference in New Issue
Block a user