Compare commits

..

5 Commits

Author SHA1 Message Date
niccolo.piazzesi
03a6dc8b51 Formatting 2025-10-14 12:02:59 +02:00
niccolo.piazzesi
a33c7abe01 Release note, version 2025-10-14 12:00:39 +02:00
niccolo.piazzesi
7380021961 Newline 2025-10-14 11:17:10 +02:00
niccolo.piazzesi
48d137466f Comments 2025-10-14 11:14:12 +02:00
niccolo.piazzesi
29d637ed45 Run InterfaceUsageMarker before NestUsageMarker to prevent missing marking of permitted subclasses attribute 2025-10-14 10:58:01 +02:00
31 changed files with 271 additions and 513 deletions

View File

@@ -108,7 +108,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.2'
classpath 'com.guardsquare:proguard-gradle:7.8.0'
}
}
```

View File

@@ -5,7 +5,7 @@ plugins {
afterEvaluate {
publishing {
publications.named(project.name) {
publications.getByName(project.name) {
pom {
description = 'Java annotations to configure ProGuard, the free shrinker, optimizer, obfuscator, and preverifier for Java bytecode'
}

View File

@@ -15,7 +15,7 @@ dependencies {
implementation 'org.apache.ant:ant:1.10.15'
}
def fatJar = tasks.register("fatJar", ShadowJar) {
task fatJar(type: ShadowJar) {
destinationDirectory.set(file("$rootDir/lib"))
archiveFileName.set('proguard-ant.jar')
from sourceSets.main.output
@@ -32,7 +32,7 @@ assemble.dependsOn fatJar
afterEvaluate {
publishing {
publications.named(project.name) {
publications.getByName(project.name) {
pom {
description = 'Ant plugin for ProGuard, the free shrinker, optimizer, obfuscator, and preverifier for Java bytecode'
}

View File

@@ -1,7 +1,6 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id 'java-library'
id 'java-test-fixtures'
id 'maven-publish'
id "org.jetbrains.kotlin.jvm"
id 'com.adarshr.test-logger' version '4.0.0'
@@ -13,10 +12,10 @@ repositories {
mavenCentral()
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.fromTarget(project.findProperty("target")))
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
kotlinOptions {
jvmTarget = "${target}"
}
}
dependencies {
@@ -56,25 +55,24 @@ test {
useJUnitPlatform()
}
def testAllJavaVersion = tasks.register("testAllJavaVersions"){ testAllTask ->
task testAllJavaVersions() { testAllTask ->
dependsOn(test) // the usual test runs on Java 8
}
javaVersionsForTest.each {version ->
def testJavaVersion = tasks.register("testJava$version", Test) {
useJUnitPlatform()
ignoreFailures = true
javaVersionsForTest.each {version ->
task("testJava$version", type: Test) {
useJUnitPlatform()
ignoreFailures = true
// The version of bytebuddy used by mockk only supports Java 22 experimentally so far
// if (version >= 22) systemProperty 'net.bytebuddy.experimental', true
// The version of bytebuddy used by mockk only supports Java 22 experimentally so far
// if (version >= 22) systemProperty 'net.bytebuddy.experimental', true
testAllTask.dependsOn(it)
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(version)
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(version)
}
}
}
testAllJavaVersion.configure { it.dependsOn(testJavaVersion) }
}
jacocoTestReport {
@@ -97,7 +95,7 @@ jacocoTestReport {
afterEvaluate {
publishing {
publications.named(project.name) {
publications.getByName(project.name) {
pom {
description = 'ProGuard is a free shrinker, optimizer, obfuscator, and preverifier for Java bytecode'
}

View File

@@ -1,6 +0,0 @@
package proguard.classfile.attribute;
public enum ProGuardOrigin implements LineOrigin
{
INLINED
}

View File

@@ -131,19 +131,16 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata.flags.hasAnnotations = false;
}
if (kotlinPropertyMetadata.getterMetadata != null &&
kotlinPropertyMetadata.getterMetadata.referencedMethod != null)
if (kotlinPropertyMetadata.referencedGetterMethod != null)
{
kotlinPropertyMetadata.getterMetadata.referencedMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.getterMetadata.hasAnnotations = annotationCounter.getCount() > 0;
kotlinPropertyMetadata.referencedGetterMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.getterFlags.hasAnnotations = annotationCounter.getCount() > 0;
}
if (kotlinPropertyMetadata.flags.isVar &&
kotlinPropertyMetadata.setterMetadata != null &&
kotlinPropertyMetadata.setterMetadata.referencedMethod != null)
if (kotlinPropertyMetadata.flags.isVar && kotlinPropertyMetadata.referencedSetterMethod != null)
{
kotlinPropertyMetadata.setterMetadata.referencedMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.setterMetadata.hasAnnotations = annotationCounter.getCount() > 0;
kotlinPropertyMetadata.referencedSetterMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.setterFlags.hasAnnotations = annotationCounter.getCount() > 0;
}
}
@@ -281,10 +278,9 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata,
this);
if (kotlinValueParameterMetadata.flags.hasAnnotations &&
kotlinPropertyMetadata.setterMetadata != null)
if (kotlinValueParameterMetadata.flags.hasAnnotations)
{
kotlinPropertyMetadata.setterMetadata.referencedMethod.accept(clazz, annotationCounter.reset());
kotlinPropertyMetadata.referencedSetterMethod.accept(clazz, annotationCounter.reset());
kotlinValueParameterMetadata.flags.hasAnnotations =
annotationCounter.getParameterAnnotationCount(kotlinValueParameterMetadata.index) > 0;
}

View File

@@ -146,8 +146,8 @@ public class Marker implements Pass
KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata,
KotlinPropertyMetadata kotlinPropertyMetadata) {
List<Processable> processables = Stream.of(kotlinPropertyMetadata.referencedBackingField,
kotlinPropertyMetadata.getterMetadata.referencedMethod,
kotlinPropertyMetadata.setterMetadata != null ? kotlinPropertyMetadata.setterMetadata.referencedMethod : null)
kotlinPropertyMetadata.referencedGetterMethod,
kotlinPropertyMetadata.referencedSetterMethod)
.filter(Objects::nonNull)
.collect(Collectors.toList());
int flags = 0;

View File

@@ -64,13 +64,11 @@ implements KotlinMetadataVisitor,
if ((kotlinPropertyMetadata.referencedBackingField != null &&
(kotlinPropertyMetadata.referencedBackingField.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0) ||
(kotlinPropertyMetadata.getterMetadata != null &&
kotlinPropertyMetadata.getterMetadata.referencedMethod != null &&
(kotlinPropertyMetadata.getterMetadata.referencedMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0) ||
(kotlinPropertyMetadata.referencedGetterMethod != null &&
(kotlinPropertyMetadata.referencedGetterMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0) ||
(kotlinPropertyMetadata.setterMetadata != null &&
kotlinPropertyMetadata.setterMetadata.referencedMethod != null &&
(kotlinPropertyMetadata.setterMetadata.referencedMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0))
(kotlinPropertyMetadata.referencedSetterMethod != null &&
(kotlinPropertyMetadata.referencedSetterMethod.getProcessingFlags() & ProcessingFlags.DONT_OBFUSCATE) != 0))
{
return;
}

View File

@@ -114,14 +114,14 @@ implements KotlinMetadataVisitor,
KotlinPropertyMetadata kotlinPropertyMetadata)
{
keepParameterInfo = false;
if (kotlinPropertyMetadata.setterMetadata != null && kotlinPropertyMetadata.setterMetadata.referencedMethod != null)
if (kotlinPropertyMetadata.referencedSetterMethod != null)
{
kotlinPropertyMetadata.setterMetadata.referencedMethod.accept(clazz, this);
kotlinPropertyMetadata.referencedSetterMethod.accept(clazz, this);
}
if (keepParameterInfo)
{
kotlinPropertyMetadata.setterParameterAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParametersAccept(clazz, kotlinDeclarationContainerMetadata, this);
}
}

View File

@@ -108,8 +108,8 @@ public class KotlinContextReceiverUsageMarker implements
public void visitAnyProperty(Clazz clazz, KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata, KotlinPropertyMetadata kotlinPropertyMetadata)
{
markContextReceiverParameters(kotlinPropertyMetadata.contextReceivers,
kotlinPropertyMetadata.getterMetadata.referencedMethod,
kotlinPropertyMetadata.setterMetadata != null ? kotlinPropertyMetadata.setterMetadata.referencedMethod : null);
kotlinPropertyMetadata.referencedGetterMethod,
kotlinPropertyMetadata.referencedSetterMethod);
}
private void markContextReceiverParameters(List<KotlinTypeMetadata> contextReceivers, Method...methods)

View File

@@ -29,19 +29,18 @@ import proguard.classfile.ProgramClass;
import proguard.classfile.ProgramMethod;
import proguard.classfile.attribute.Attribute;
import proguard.classfile.attribute.CodeAttribute;
import proguard.classfile.attribute.ExtendedLineNumberInfo;
import proguard.classfile.attribute.LineNumberInfo;
import proguard.classfile.attribute.LineNumberInfoBlock;
import proguard.classfile.attribute.LineNumberTableAttribute;
import proguard.classfile.attribute.StructuredLineNumberInfo;
import proguard.classfile.attribute.visitor.AllAttributeVisitor;
import proguard.classfile.attribute.visitor.AllLineNumberInfoVisitor;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.attribute.visitor.LineNumberInfoVisitor;
import proguard.classfile.attribute.visitor.LineNumberRangeFinder;
import proguard.classfile.visitor.ClassVisitor;
import proguard.classfile.visitor.MemberVisitor;
import proguard.pass.Pass;
import java.util.Arrays;
import java.util.Stack;
/**
@@ -57,7 +56,8 @@ public class LineNumberLinearizer
implements Pass,
ClassVisitor,
MemberVisitor,
AttributeVisitor
AttributeVisitor,
LineNumberInfoVisitor
{
private static final Logger logger = LogManager.getLogger(LineNumberLinearizer.class);
@@ -76,15 +76,16 @@ implements Pass,
* optimizations like method inlining and class merging.
*/
@Override
public void execute(AppView appView) {
public void execute(AppView appView)
{
appView.programClassPool.classesAccept(this);
}
// Implementations for ClassVisitor.
@Override
public void visitAnyClass(Clazz clazz) {
}
public void visitAnyClass(Clazz clazz) { }
@Override
public void visitProgramClass(ProgramClass programClass)
@@ -108,26 +109,26 @@ implements Pass,
}
}
// Implementations for MemberVisitor.
@Override
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
programMethod.attributesAccept(programClass, this);
}
// Implementations for AttributeVisitor.
@Override
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@Override
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
codeAttribute.attributesAccept(clazz, method, this);
}
@Override
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
logger.debug("LineNumberLinearizer [{}.{}{}]:",
@@ -137,142 +138,112 @@ implements Pass,
);
enclosingLineNumbers.clear();
previousLineNumberInfo = null;
// Figure out which lines need linearizing. Only freshly inlined blocks need to be linearized.
// Process all line numbers.
lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
}
LineNumberInfo[] infos = lineNumberTableAttribute.lineNumberTable;
int lineNumberTableLength = lineNumberTableAttribute.u2lineNumberTableLength;
boolean[] inlinedBlock = new boolean[lineNumberTableLength];
int currentDepth = 0;
for (int i = 0; i < lineNumberTableLength; i++)
// Implementations for LineNumberInfoVisitor.
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
String source = lineNumberInfo.getSource();
String debugMessage = String.format(" [%s] line %s%s",
lineNumberInfo.u2startPC,
lineNumberInfo.u2lineNumber,
source == null ? "" : " [" + source + "]"
);
// Is it an inlined line number?
if (source != null)
{
LineNumberInfo currentInfo = infos[i];
if (currentInfo.u2lineNumber == MethodInliner.INLINED_METHOD_START_LINE_NUMBER)
ExtendedLineNumberInfo extendedLineNumberInfo =
(ExtendedLineNumberInfo)lineNumberInfo;
int lineNumber = extendedLineNumberInfo.u2lineNumber;
// Are we entering or exiting a new inlined block?
if (previousLineNumberInfo == null ||
!source.equals(previousLineNumberInfo.getSource()))
{
currentDepth++;
}
inlinedBlock[i] = currentDepth > 0;
if (currentInfo.u2lineNumber == MethodInliner.INLINED_METHOD_END_LINE_NUMBER)
{
currentDepth--;
}
}
// Linearize the line numbers.
LineNumberInfo previousLineNumberInfo = null;
for (int i = 0; i < lineNumberTableLength; i++)
{
LineNumberInfo lineNumberInfo = infos[i];
String source = lineNumberInfo.getSource();
logger.debug(" [{}] line {}{}", lineNumberInfo.u2startPC, lineNumberInfo.u2lineNumber, source == null ? "" : " [" + source + "]");
// Is it an inlined line number?
if (source != null && inlinedBlock[i])
{
int lineNumber = lineNumberInfo.u2lineNumber;
// Are we entering a new inlined block?
if (lineNumber == MethodInliner.INLINED_METHOD_START_LINE_NUMBER)
if (lineNumber != MethodInliner.INLINED_METHOD_END_LINE_NUMBER)
{
// Remember information about the inlined block.
enclosingLineNumbers.push(
previousLineNumberInfo != null
? new MyLineNumberBlock(
currentLineNumberShift,
previousLineNumberInfo.u2lineNumber,
previousLineNumberInfo.getSource() != null
? previousLineNumberInfo.getBlock()
: null)
: new MyLineNumberBlock(0, 0, null));
enclosingLineNumbers.push(previousLineNumberInfo != null ?
new MyLineNumberBlock(currentLineNumberShift,
previousLineNumberInfo.u2lineNumber,
previousLineNumberInfo.getSource()) :
new MyLineNumberBlock(0, 0, null));
// Parse the end line number from the source string, so we know how large a block this
// will be.
// Parse the end line number from the source string,
// so we know how large a block this will be.
int separatorIndex1 = source.indexOf(':');
int separatorIndex2 = source.indexOf(':', separatorIndex1 + 1);
int startLineNumber =
Integer.parseInt(source.substring(separatorIndex1 + 1, separatorIndex2));
int endLineNumber = Integer.parseInt(source.substring(separatorIndex2 + 1));
int startLineNumber = Integer.parseInt(source.substring(separatorIndex1 + 1, separatorIndex2));
int endLineNumber = Integer.parseInt(source.substring(separatorIndex2 + 1));
// TODO: this matches a quirk in the old behavior where the opening line is always :0:0
// this is a bug that probably causes overlapping line numbers but for now we will match
// this behavior so we can directly compare old and new mappings.
startLineNumber = 0;
endLineNumber = 0;
// Start shifting, if necessary, so the block ends up beyond the highest used line number.
// We're striving for rounded shifts, unless we've reached a given limit, to avoid running
// out of line numbers too quickly.
// Start shifting, if necessary, so the block ends up beyond
// the highest used line number. We're striving for rounded
// shifts, unless we've reached a given limit, to avoid
// running out of line numbers too quickly.
currentLineNumberShift =
highestUsedLineNumber > SHIFT_ROUNDING_LIMIT
? highestUsedLineNumber - startLineNumber + 1
: startLineNumber > highestUsedLineNumber
? 0
: (highestUsedLineNumber - startLineNumber + SHIFT_ROUNDING)
/ SHIFT_ROUNDING
* SHIFT_ROUNDING;
highestUsedLineNumber > SHIFT_ROUNDING_LIMIT ?
highestUsedLineNumber - startLineNumber + 1 :
startLineNumber > highestUsedLineNumber ? 0 :
(highestUsedLineNumber - startLineNumber + SHIFT_ROUNDING)
/ SHIFT_ROUNDING * SHIFT_ROUNDING;
highestUsedLineNumber = endLineNumber + currentLineNumberShift;
logger.debug(" (enter with shift {})", currentLineNumberShift);
}
// Are we exiting an inlined block?
else if (lineNumber == MethodInliner.INLINED_METHOD_END_LINE_NUMBER)
{
// TODO: There appear to be cases where the stack is empty at this point, so we've added a
// check.
if (enclosingLineNumbers.isEmpty())
{
logger.debug("Problem linearizing line numbers for optimized code ({}.{})", clazz.getName(), method.getName(clazz));
}
else
{
// Pop information about the enclosing line number.
MyLineNumberBlock lineNumberBlock = enclosingLineNumbers.pop();
// Set this end of the block to the line at which it was inlined.
lineNumberInfo =
lineNumberBlock.enclosingSource != null
? lineNumberBlock.enclosingSource.line(
lineNumberInfo.u2startPC, lineNumberBlock.enclosingLineNumber)
: new LineNumberInfo(
lineNumberInfo.u2startPC, lineNumberBlock.enclosingLineNumber);
infos[i] = lineNumberInfo;
// Reset the shift to the shift of the block.
currentLineNumberShift = lineNumberBlock.lineNumberShift;
logger.debug(" (exit to shift {})", currentLineNumberShift);
}
}
else
{
logger.debug(" (apply shift {})", currentLineNumberShift);
debugMessage += String.format(" (enter with shift %s)", currentLineNumberShift);
// Apply the shift.
lineNumberInfo.u2lineNumber += currentLineNumberShift;
}
// TODO: There appear to be cases where the stack is empty at this point, so we've added a check.
else if (enclosingLineNumbers.isEmpty())
{
debugMessage += String.format("Problem linearizing line numbers for optimized code %s.%s)", clazz.getName(), method.getName(clazz));
logger.debug(debugMessage);
debugMessage = "";
}
// Are we exiting an inlined block?
else
{
// Pop information about the enclosing line number.
MyLineNumberBlock lineNumberBlock = enclosingLineNumbers.pop();
// Set this end of the block to the line at which it was
// inlined.
extendedLineNumberInfo.u2lineNumber = lineNumberBlock.enclosingLineNumber;
extendedLineNumberInfo.source = lineNumberBlock.enclosingSource;
// Reset the shift to the shift of the block.
currentLineNumberShift = lineNumberBlock.lineNumberShift;
debugMessage += String.format(" (exit to shift %s)", currentLineNumberShift);
}
}
else
{
debugMessage += String.format(" (apply shift %s)", currentLineNumberShift);
previousLineNumberInfo = lineNumberInfo;
logger.debug(" -> line {}", lineNumberInfo.u2lineNumber);
// Apply the shift.
lineNumberInfo.u2lineNumber += currentLineNumberShift;
}
}
lineNumberTableAttribute.lineNumberTable =
Arrays.stream(infos, 0, lineNumberTableLength)
.filter(info -> info.u2lineNumber != MethodInliner.INLINED_METHOD_START_LINE_NUMBER)
.toArray(LineNumberInfo[]::new);
lineNumberTableAttribute.u2lineNumberTableLength =
lineNumberTableAttribute.lineNumberTable.length;
previousLineNumberInfo = lineNumberInfo;
debugMessage += String.format(" -> line %s", lineNumberInfo.u2lineNumber);
logger.debug(debugMessage);
}
@@ -282,13 +253,14 @@ implements Pass,
*/
private static class MyLineNumberBlock
{
public final int lineNumberShift;
public final int enclosingLineNumber;
public final LineNumberInfoBlock enclosingSource;
public final int lineNumberShift;
public final int enclosingLineNumber;
public final String enclosingSource;
public MyLineNumberBlock(int lineNumberShift,
int enclosingLineNumber,
LineNumberInfoBlock enclosingSource) {
public MyLineNumberBlock(int lineNumberShift,
int enclosingLineNumber,
String enclosingSource)
{
this.lineNumberShift = lineNumberShift;
this.enclosingLineNumber = enclosingLineNumber;
this.enclosingSource = enclosingSource;

View File

@@ -40,8 +40,6 @@ import proguard.util.ProcessingFlags;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;
/**
@@ -72,9 +70,8 @@ implements AttributeVisitor,
protected static final int MAXIMUM_RESULTING_CODE_LENGTH_JME = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "2000"));
protected static final int MAXIMUM_RESULTING_CODE_LENGTH_JVM = 65535;
static final int METHOD_DUMMY_START_LINE_NUMBER = 0;
public static final int INLINED_METHOD_END_LINE_NUMBER = -1;
public static final int INLINED_METHOD_START_LINE_NUMBER = -2;
static final int METHOD_DUMMY_START_LINE_NUMBER = 0;
static final int INLINED_METHOD_END_LINE_NUMBER = -1;
private static final Logger logger = LogManager.getLogger(MethodInliner.class);
@@ -97,23 +94,23 @@ implements AttributeVisitor,
new MethodInvocationMarker());
private final StackSizeComputer stackSizeComputer = new StackSizeComputer();
private ProgramClass targetClass;
private ProgramMethod targetMethod;
private ConstantAdder constantAdder;
private ExceptionInfoAdder exceptionInfoAdder;
private int estimatedResultingCodeLength;
private boolean inlining;
private Stack inliningMethods = new Stack();
private boolean emptyInvokingStack;
private boolean coveredByCatchAllHandler;
private int exceptionInfoCount;
private int uninitializedObjectCount;
private int variableOffset;
private boolean inlined;
private boolean inlinedAny;
private boolean copiedLineNumbers;
private final Deque<LineNumberInfoBlock> sourceBlock = new ArrayDeque<>();
private int minimumLineNumberIndex;
private ProgramClass targetClass;
private ProgramMethod targetMethod;
private ConstantAdder constantAdder;
private ExceptionInfoAdder exceptionInfoAdder;
private int estimatedResultingCodeLength;
private boolean inlining;
private Stack inliningMethods = new Stack();
private boolean emptyInvokingStack;
private boolean coveredByCatchAllHandler;
private int exceptionInfoCount;
private int uninitializedObjectCount;
private int variableOffset;
private boolean inlined;
private boolean inlinedAny;
private boolean copiedLineNumbers;
private String source;
private int minimumLineNumberIndex;
/**
@@ -325,6 +322,15 @@ implements AttributeVisitor,
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
// Remember the source if we're inlining a method.
source = inlining ?
clazz.getName() + '.' +
method.getName(clazz) +
method.getDescriptor(clazz) + ':' +
lineNumberTableAttribute.getLowestLineNumber() + ':' +
lineNumberTableAttribute.getHighestLineNumber() :
null;
// Insert all line numbers, possibly partly before previously inserted
// line numbers.
lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
@@ -446,61 +452,39 @@ implements AttributeVisitor,
codeAttribute.attributesAccept(clazz, method, this);
// Add a marker at the start of the method. The LineNumberLinearizer relies on this to detect
// inlined blocks.
if (inlining)
{
LineNumberTableAttribute lineNumberTableAttribute =
(LineNumberTableAttribute) codeAttribute.getAttribute(clazz, Attribute.LINE_NUMBER_TABLE);
int lowest = 0;
int highest = 0;
if (lineNumberTableAttribute != null)
{
lowest = lineNumberTableAttribute.getLowestLineNumber();
highest = lineNumberTableAttribute.getHighestLineNumber();
}
StructuredLineNumberInfo.Block block =
new StructuredLineNumberInfo.Block(
ProGuardOrigin.INLINED,
clazz.getName() + '.' + method.getName(clazz) + method.getDescriptor(clazz),
lowest,
highest);
sourceBlock.push(block);
// Insert a start marker.
LineNumberInfo startLineNumberInfo = block.line(0, INLINED_METHOD_START_LINE_NUMBER);
minimumLineNumberIndex =
codeAttributeComposer.insertLineNumber(minimumLineNumberIndex, startLineNumberInfo) + 1;
}
codeAttribute.attributesAccept(clazz, method, this);
// Make sure we at least have some entry at the start of the method.
if (!copiedLineNumbers)
{
LineNumberInfo line =
inlining
? sourceBlock.peekLast().line(0, METHOD_DUMMY_START_LINE_NUMBER)
: new LineNumberInfo(0, METHOD_DUMMY_START_LINE_NUMBER);
String source = inlining ?
clazz.getName() + '.' +
method.getName(clazz) +
method.getDescriptor(clazz) +
":0:0" :
null;
minimumLineNumberIndex =
codeAttributeComposer.insertLineNumber(minimumLineNumberIndex, line) + 1;
codeAttributeComposer.insertLineNumber(minimumLineNumberIndex,
new ExtendedLineNumberInfo(0,
METHOD_DUMMY_START_LINE_NUMBER,
source)) + 1;
}
// Add a marker at the end of an inlined method. The marker will be corrected in
// LineNumberLinearizer, so it points to the line of the enclosing method.
// Add a marker at the end of an inlined method.
// The marker will be corrected in LineNumberLinearizer,
// so it points to the line of the enclosing method.
if (inlining)
{
String source =
clazz.getName() + '.' + method.getName(clazz) + method.getDescriptor(clazz) + ":0:0";
clazz.getName() + '.' +
method.getName(clazz) +
method.getDescriptor(clazz) +
":0:0";
minimumLineNumberIndex =
codeAttributeComposer.insertLineNumber(
minimumLineNumberIndex,
sourceBlock
.pop()
.line(codeAttribute.u4codeLength, INLINED_METHOD_END_LINE_NUMBER))
+ 1;
codeAttributeComposer.insertLineNumber(minimumLineNumberIndex,
new ExtendedLineNumberInfo(codeAttribute.u4codeLength,
INLINED_METHOD_END_LINE_NUMBER,
source)) + 1;
}
codeAttributeComposer.endCodeFragment();
@@ -842,30 +826,19 @@ implements AttributeVisitor,
{
try
{
LineNumberInfoBlock block = sourceBlock.peekLast();
boolean newSource = block != null;
boolean preserveSource = lineNumberInfo.getSource() != null;
String newSource = lineNumberInfo.getSource() != null ?
lineNumberInfo.getSource() :
source;
LineNumberInfo newLineNumberInfo;
if (preserveSource)
{
newLineNumberInfo =
((StructuredLineNumberInfo) lineNumberInfo)
.getBlock(ProGuardOrigin.INLINED)
.line(lineNumberInfo.u2startPC, lineNumberInfo.u2lineNumber);
}
else if (newSource)
{
newLineNumberInfo = block.line(lineNumberInfo.u2startPC, lineNumberInfo.u2lineNumber);
}
else
{
newLineNumberInfo =
new LineNumberInfo(lineNumberInfo.u2startPC, lineNumberInfo.u2lineNumber);
}
LineNumberInfo newLineNumberInfo = newSource != null ?
new ExtendedLineNumberInfo(lineNumberInfo.u2startPC,
lineNumberInfo.u2lineNumber,
newSource) :
new LineNumberInfo(lineNumberInfo.u2startPC,
lineNumberInfo.u2lineNumber);
minimumLineNumberIndex =
codeAttributeComposer.insertLineNumber(minimumLineNumberIndex, newLineNumberInfo) + 1;
codeAttributeComposer.insertLineNumber(minimumLineNumberIndex, newLineNumberInfo) + 1;
}
catch (IllegalArgumentException e)
{

View File

@@ -1869,13 +1869,11 @@ implements ClassVisitor,
kotlinPropertyMetadata.referencedBackingField != null &&
isUsed(kotlinPropertyMetadata.referencedBackingField);
boolean getterUsed =
kotlinPropertyMetadata.getterMetadata != null &&
kotlinPropertyMetadata.getterMetadata.referencedMethod != null &&
isUsed(kotlinPropertyMetadata.getterMetadata.referencedMethod);
kotlinPropertyMetadata.referencedGetterMethod != null &&
isUsed(kotlinPropertyMetadata.referencedGetterMethod);
boolean setterUsed =
kotlinPropertyMetadata.setterMetadata != null &&
kotlinPropertyMetadata.setterMetadata.referencedMethod != null &&
isUsed(kotlinPropertyMetadata.setterMetadata.referencedMethod);
kotlinPropertyMetadata.referencedSetterMethod != null &&
isUsed(kotlinPropertyMetadata.referencedSetterMethod);
if (backingFieldUsed || getterUsed || setterUsed)
{
@@ -1916,7 +1914,7 @@ implements ClassVisitor,
kotlinPropertyMetadata.receiverTypeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.contextReceiverTypesAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParameterAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.versionRequirementAccept( clazz, kotlinDeclarationContainerMetadata, this);
}

View File

@@ -26,7 +26,6 @@ import proguard.classfile.kotlin.KotlinClassKindMetadata;
import proguard.classfile.kotlin.KotlinConstants;
import proguard.classfile.kotlin.KotlinConstructorMetadata;
import proguard.classfile.kotlin.KotlinDeclarationContainerMetadata;
import proguard.classfile.kotlin.KotlinEnumEntryMetadata;
import proguard.classfile.kotlin.KotlinFileFacadeKindMetadata;
import proguard.classfile.kotlin.KotlinFunctionMetadata;
import proguard.classfile.kotlin.KotlinMetadata;
@@ -39,7 +38,6 @@ import proguard.classfile.kotlin.KotlinTypeMetadata;
import proguard.classfile.kotlin.KotlinTypeParameterMetadata;
import proguard.classfile.kotlin.KotlinValueParameterMetadata;
import proguard.classfile.kotlin.KotlinVersionRequirementMetadata;
import proguard.classfile.kotlin.flags.KotlinPropertyAccessorMetadata;
import proguard.classfile.kotlin.visitor.AllTypeVisitor;
import proguard.classfile.kotlin.visitor.KotlinConstructorVisitor;
import proguard.classfile.kotlin.visitor.KotlinFunctionVisitor;
@@ -112,7 +110,8 @@ implements KotlinMetadataVisitor,
shrinkMetadataArray(kotlinClassKindMetadata.constructors);
shrinkEnumEntries(kotlinClassKindMetadata.enumEntries);
shrinkArray(kotlinClassKindMetadata.enumEntryNames,
kotlinClassKindMetadata.referencedEnumEntries);
shrinkArray(kotlinClassKindMetadata.nestedClassNames,
kotlinClassKindMetadata.referencedNestedClasses);
@@ -168,7 +167,7 @@ implements KotlinMetadataVisitor,
{
kotlinPropertyMetadata.versionRequirementAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParameterAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.receiverTypeAccept( clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.contextReceiverTypesAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeParametersAccept( clazz, kotlinDeclarationContainerMetadata, this);
@@ -180,18 +179,21 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata.referencedBackingField = null;
}
if (shouldShrinkMetadata(kotlinPropertyMetadata.getterMetadata))
if (shouldShrinkMetadata(kotlinPropertyMetadata.getterSignature,
kotlinPropertyMetadata.referencedGetterMethod))
{
kotlinPropertyMetadata.getterMetadata.signature = null;
kotlinPropertyMetadata.getterMetadata.referencedMethod = null;
kotlinPropertyMetadata.getterSignature = null;
kotlinPropertyMetadata.referencedGetterMethod = null;
}
if (shouldShrinkMetadata(kotlinPropertyMetadata.setterMetadata))
if (shouldShrinkMetadata(kotlinPropertyMetadata.setterSignature,
kotlinPropertyMetadata.referencedSetterMethod))
{
kotlinPropertyMetadata.setterMetadata.signature = null;
kotlinPropertyMetadata.setterMetadata.referencedMethod = null;
kotlinPropertyMetadata.flags.isVar = false;
kotlinPropertyMetadata.setterParameter = null;
kotlinPropertyMetadata.setterSignature = null;
kotlinPropertyMetadata.referencedSetterMethod = null;
kotlinPropertyMetadata.flags.isVar = false;
kotlinPropertyMetadata.setterParameter = null;
kotlinPropertyMetadata.setterParameters.clear();
}
kotlinPropertyMetadata.versionRequirementAccept(clazz,
@@ -204,7 +206,7 @@ implements KotlinMetadataVisitor,
kotlinPropertyMetadata.syntheticMethodForAnnotations = null;
kotlinPropertyMetadata.referencedSyntheticMethodForAnnotations = null;
kotlinPropertyMetadata.referencedSyntheticMethodClass = null;
kotlinPropertyMetadata.annotations.clear();
kotlinPropertyMetadata.flags.hasAnnotations = false;
}
if (kotlinPropertyMetadata.syntheticMethodForDelegate != null &&
@@ -218,10 +220,8 @@ implements KotlinMetadataVisitor,
// Fix inconsistencies that were introduced as
// a result of shrinking
if (kotlinPropertyMetadata.referencedBackingField != null &&
(kotlinPropertyMetadata.setterMetadata == null ||
kotlinPropertyMetadata.setterMetadata.signature == null) &&
(kotlinPropertyMetadata.getterMetadata == null ||
kotlinPropertyMetadata.getterMetadata.signature == null) &&
kotlinPropertyMetadata.getterSignature == null &&
kotlinPropertyMetadata.setterSignature == null &&
(kotlinPropertyMetadata.referencedBackingField.getAccessFlags() & AccessConstants.PRIVATE) != 0 &&
!kotlinPropertyMetadata.flags.visibility.isPrivate)
{
@@ -399,11 +399,6 @@ implements KotlinMetadataVisitor,
!usageMarker.isUsed(jvmElement);
}
private boolean shouldShrinkMetadata(KotlinPropertyAccessorMetadata kotlinPropertyAccessorMetadata) {
return kotlinPropertyAccessorMetadata != null && !usageMarker.isUsed(kotlinPropertyAccessorMetadata.referencedMethod);
}
/**
* Shrinks elements and their corresponding referenced element, based on
@@ -417,13 +412,10 @@ implements KotlinMetadataVisitor,
shrinkArray(usageMarker, elements, referencedJavaElements);
}
private void shrinkEnumEntries(List<KotlinEnumEntryMetadata> enumEntries) {
enumEntries.removeIf(usageMarker::isUsed);
}
/**
* Shrinks elements and their corresponding referenced element, based on
* markings on the referenced element.
*
* List is modified - must be a modifiable list!
*/
static void shrinkArray(SimpleUsageMarker usageMarker,

View File

@@ -129,9 +129,6 @@ public class UsageMarker
new LocalVariableTypeUsageMarker(classUsageMarker)
))));
// Second Interface Usage marking, this is necessary for marking interface constants that are not directly referenced
// (e.g. interfaces only referenced through annotations). See https://github.com/Guardsquare/proguard/issues/508.
programClassPool.classesAccept(new InterfaceUsageMarker(classUsageMarker));
if (configuration.keepKotlinMetadata)
{

View File

@@ -1,84 +0,0 @@
package proguard.optimize.peephole
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.shouldBe
import proguard.classfile.AccessConstants
import proguard.classfile.ClassConstants
import proguard.classfile.ProgramMethod
import proguard.classfile.VersionConstants
import proguard.classfile.attribute.Attribute
import proguard.classfile.attribute.Attribute.LINE_NUMBER_TABLE
import proguard.classfile.attribute.LineNumberInfo
import proguard.classfile.attribute.LineNumberTableAttribute
import proguard.classfile.attribute.ProGuardOrigin
import proguard.classfile.attribute.StructuredLineNumberInfo
import proguard.classfile.editor.AttributesEditor
import proguard.classfile.editor.ClassBuilder
import proguard.testutils.CodeAttributeFinder
class InlinedMethodLineNumberLinearizerTest : BehaviorSpec({
Given("A method with two levels of inlined line numbers") {
val clazzBuilder = ClassBuilder(VersionConstants.CLASS_VERSION_18, AccessConstants.PUBLIC, "A", ClassConstants.NAME_JAVA_LANG_OBJECT)
val clazz = clazzBuilder.programClass
val method = clazzBuilder.addAndReturnMethod(
AccessConstants.PUBLIC or AccessConstants.STATIC,
"a",
"()V",
10,
) {
it.return_()
} as ProgramMethod
val codeAttribute = CodeAttributeFinder.findCodeAttribute(method)!!
val blockB = StructuredLineNumberInfo.Block(ProGuardOrigin.INLINED, "B.b()V", 0, 0)
val blockC = StructuredLineNumberInfo.Block(ProGuardOrigin.INLINED, "C.c()V", 0, 0)
val lineNumbers = arrayOf(
LineNumberInfo(0, 1),
blockB.line(1, MethodInliner.INLINED_METHOD_START_LINE_NUMBER),
blockB.line(2, 11),
blockC.line(3, MethodInliner.INLINED_METHOD_START_LINE_NUMBER),
blockC.line(4, 21),
blockC.line(5, MethodInliner.INLINED_METHOD_END_LINE_NUMBER),
blockB.line(6, 12),
blockB.line(7, MethodInliner.INLINED_METHOD_END_LINE_NUMBER),
LineNumberInfo(8, 2)
)
val lineNumberTableAttribute = LineNumberTableAttribute(clazzBuilder.constantPoolEditor.addUtf8Constant(LINE_NUMBER_TABLE), lineNumbers.size, lineNumbers)
AttributesEditor(clazz, method, codeAttribute, true).addAttribute(lineNumberTableAttribute)
When("Linearizing the line numbers") {
clazz.accept(LineNumberLinearizer())
Then("The line number table should look correct") {
val lineNumberTableAttribute = codeAttribute.getAttribute(clazz, Attribute.LINE_NUMBER_TABLE) as LineNumberTableAttribute
val table = lineNumberTableAttribute.lineNumberTable
table[0].u2lineNumber shouldBe 1
table[0].source.shouldBeNull()
table[1].u2lineNumber.mod(LineNumberLinearizer.SHIFT_ROUNDING) shouldBe 11
table[1].source shouldBe "B.b()V:0:0"
table[2].u2lineNumber.mod(LineNumberLinearizer.SHIFT_ROUNDING) shouldBe 21
table[2].source shouldBe "C.c()V:0:0"
table[3].u2lineNumber.mod(LineNumberLinearizer.SHIFT_ROUNDING) shouldBe 11
table[3].source shouldBe "B.b()V:0:0"
table[4].u2lineNumber.mod(LineNumberLinearizer.SHIFT_ROUNDING) shouldBe 12
table[4].source shouldBe "B.b()V:0:0"
table[5].u2lineNumber shouldBe 1
table[5].source.shouldBeNull()
table[6].u2lineNumber shouldBe 2
table[6].source.shouldBeNull()
}
}
}
})

View File

@@ -21,74 +21,6 @@ import proguard.testutils.RequiresJavaVersion
import proguard.util.ProcessingFlagSetter
import proguard.util.ProcessingFlags.DONT_SHRINK
class UsageMarkerTest : BehaviorSpec({
Given("A class pool with interfaces only referenced through annotations") {
val (programClassPool, _) = ClassPoolBuilder.fromSource(
JavaSource("MyInterface.java","""
interface MyInterface {}
""".trimIndent()),
JavaSource("MyAnnotation.java","""
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
Class<?> value();
}
""".trimIndent()),
JavaSource("MyImpl.java","""
class MyImpl implements MyInterface {}
""".trimIndent()),
JavaSource("InterfaceTest.java", """
import java.lang.reflect.Field;
class InterfaceTest {
@MyAnnotation(MyImpl.class)
String s;
public static void main(String... args) throws Exception {
Field f = InterfaceTest.class.getDeclaredField("s");
MyAnnotation annotation = f.getAnnotation(MyAnnotation.class);
Object obj = annotation.value().getDeclaredConstructor().newInstance();
if (obj instanceof MyInterface) {
System.out.println("success");
} else {
throw new Exception(obj.getClass() + " does not implement " + MyInterface.class);
}
}
}
""".trimIndent())
)
val implClass = programClassPool.getClass("MyImpl")
val main = programClassPool.getClass("InterfaceTest")
main.accept(
MultiClassVisitor(ProcessingFlagSetter(DONT_SHRINK), AllMemberVisitor(
ProcessingFlagSetter(DONT_SHRINK)
)))
When("marking") {
val simpleUsageMarker = SimpleUsageMarker()
UsageMarker(Configuration()).mark(programClassPool,ClassPool(), ResourceFilePool(),simpleUsageMarker)
Then("The interface class should be marked as used.") {
val used = object : ConstantVisitor {
var used = false
override fun visitAnyConstant(
clazz: Clazz?,
constant: Constant?
) {
used = used or simpleUsageMarker.isUsed(constant)
}
}
implClass.interfaceConstantsAccept(used)
used.used shouldBe true
}
}
}
})
@RequiresJavaVersion(15)
class Java15UsageMarkerTest : BehaviorSpec({
// Regression test for https://github.com/Guardsquare/proguard/issues/501

View File

@@ -13,7 +13,7 @@ allprojects {
}
}
tasks.register("buildDocumentation", Exec) {
task buildDocumentation(type: Exec) {
inputs.dir 'docs/md'
inputs.file 'docs/mkdocs.yml'
outputs.dir 'docs/html'
@@ -60,7 +60,7 @@ allprojects { Project project ->
configure(project) {
publishing {
publications {
register(project.name, MavenPublication) {
create(project.name, MavenPublication) {
pom {
artifactId = "proguard-$project.name"
name = "$group:$artifactId"
@@ -115,7 +115,7 @@ allprojects { Project project ->
}
publishing {
publications {
named(project.name) {
getByName(project.name) {
from components.java
}
}
@@ -146,34 +146,31 @@ allprojects { Project project ->
}
distributions {
main {
distributionBaseName.set('proguard')
contents {
into("lib") {
def distProjects = [
project(":proguard-app"),
project(":gui"),
project(":retrace"),
project(":ant"),
]
from(distProjects.collect { it.tasks.named { it == "fatJar" } })
}
into('docs') {
from('docs/md') {
includeEmptyDirs = false
include '**/*.md'
}
}
from(rootDir) {
include 'bin/'
include 'examples/'
exclude 'examples/*/build'
exclude 'examples/*/.gradle'
include 'LICENSE'
include 'LICENSE_exception.md'
main {
distributionBaseName.set('proguard')
contents {
into('lib') {
from tasks.getByPath(':proguard-app:fatJar').outputs
from tasks.getByPath(':gui:fatJar').outputs
from tasks.getByPath(':retrace:fatJar').outputs
from tasks.getByPath(':ant:fatJar').outputs
}
into('docs') {
from('docs/md') {
includeEmptyDirs = false
include '**/*.md'
}
}
from(rootDir) {
include 'bin/'
include 'examples/'
exclude 'examples/*/build'
exclude 'examples/*/.gradle'
include 'LICENSE'
include 'LICENSE_exception.md'
}
}
}
}
distTar {

View File

@@ -68,9 +68,9 @@ Yes, you can. **ProGuard** itself is distributed under the GPL, but this
doesn't affect the programs that you process. Your code remains yours, and its
license can remain the same.
## Does ProGuard work with Java 2, 5,..., 25? {: #jdk1.4}
## Does ProGuard work with Java 2, 5,..., 19? {: #jdk1.4}
Yes, **ProGuard** supports all JDKs from 1.1 up to and including 25. Java 2
Yes, **ProGuard** supports all JDKs from 1.1 up to and including 19. Java 2
introduced some small differences in the class file format. Java 5 added
attributes for generics and for annotations. Java 6 introduced optional
preverification attributes. Java 7 made preverification obligatory and

View File

@@ -1,4 +1,4 @@
Welcome to the manual for **ProGuard** version 7.8.2 ([what's new?](releasenotes.md)).
Welcome to the manual for **ProGuard** version 7.8.0 ([what's new?](releasenotes.md)).
ProGuard is an open-sourced Java class file shrinker, optimizer, obfuscator, and
preverifier. As a result, ProGuard processed applications and libraries are smaller and faster.

View File

@@ -3,4 +3,4 @@
!!! Warning
ProGuard no longer supports backporting, and cannot backport class files compiled with Java >11.
Provide supports Java versions up to and including 25.
Provide supports Java versions up to and including 19.

View File

@@ -1,15 +1,8 @@
## Version 7.8.2
### Bugfixes
- Fix regression in marking of interface constants (#508).
## Version 7.8.1
### Bugfixes
- Prevent `java.lang.IncompatibleClassChangeError` when shrinking is enabled and sealed interfaces are used (#501).
- Prevent `java.lang.ClassCastException` when inlining (#505).
## Version 7.8

View File

@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.2'
classpath 'com.guardsquare:proguard-gradle:7.8.0'
}
}

View File

@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.2'
classpath 'com.guardsquare:proguard-gradle:7.8.0'
}
}

View File

@@ -5,7 +5,7 @@ buildscript {
google()
}
dependencies {
classpath("com.guardsquare:proguard-gradle:7.8.2")
classpath("com.guardsquare:proguard-gradle:7.8.0")
}
}

View File

@@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.8.2'
classpath 'com.guardsquare:proguard-gradle:7.8.0'
}
}

View File

@@ -1,5 +1,5 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id 'com.github.johnrengelman.shadow'
id 'java-gradle-plugin'
@@ -24,10 +24,12 @@ gradlePlugin {
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.fromTarget(project.findProperty("target")))
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
configurations {
@@ -65,7 +67,7 @@ test {
def localRepo = file("$buildDir/local-repo")
def fatJar = tasks.register("fatJar", ShadowJar) {
task fatJar(type: ShadowJar) {
destinationDirectory.set(localRepo)
archiveFileName.set("proguard-gradle-${version}.jar")
from sourceSets.main.output

View File

@@ -1,7 +1,7 @@
proguardVersion = 7.9.0
proguardVersion = 7.8.1
# The version of ProGuardCORE that sub-projects are built with
proguardCoreVersion = 9.3.0
proguardCoreVersion = 9.2.0
gsonVersion = 2.11.0
kotlinVersion = 2.2.0
target = 1.8

View File

@@ -17,7 +17,7 @@ dependencies {
implementation 'org.apache.logging.log4j:log4j-core:2.24.2'
}
def fatJar = tasks.register("fatJar", ShadowJar) {
task fatJar(type: ShadowJar) {
destinationDirectory.set(file("$rootDir/lib"))
archiveFileName.set('proguardgui.jar')
from sourceSets.main.output
@@ -35,7 +35,7 @@ assemble.dependsOn fatJar
afterEvaluate {
publishing {
publications.named(project.name) {
publications.getByName(project.name) {
pom {
description = 'ProGuardGUI is an interface for ProGuard, the free shrinker, optimizer, obfuscator, and preverifier for Java bytecode'
}

View File

@@ -16,7 +16,7 @@ dependencies {
jar.manifest.attributes('Implementation-Version': version)
def fatJar = tasks.register("fatJar",ShadowJar) {
task fatJar(type: ShadowJar) {
mainClassName = 'proguard.ProGuard'
destinationDirectory.set(file("$rootDir/lib"))
archiveFileName.set('proguard.jar')

View File

@@ -14,7 +14,7 @@ dependencies {
implementation project(':base')
}
def fatJar = tasks.register("fatJar", ShadowJar) {
task fatJar(type: ShadowJar) {
destinationDirectory.set(file("$rootDir/lib"))
archiveFileName.set('retrace.jar')
from sourceSets.main.output
@@ -31,7 +31,7 @@ assemble.dependsOn fatJar
afterEvaluate {
publishing {
publications.named(project.name) {
publications.getByName(project.name) {
pom {
description = "ReTrace is a companion tool for ProGuard and DexGuard that 'de-obfuscates' stack traces."
}