Cleaned up build scripts and documentation.

This commit is contained in:
Eric Lafortune
2020-01-27 18:16:51 +01:00
parent 227e02b370
commit 0ac9591ca1
24 changed files with 999 additions and 62 deletions

View File

@@ -6,6 +6,9 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/out" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View File

@@ -3,25 +3,17 @@ ProGuard, Java class file shrinker, optimizer, obfuscator, and preverifier
This directory contains a number of alternative ways to build ProGuard:
- build.sh: a shell script for GNU/Linux
./build.sh
- makefile: a makefile for GNU/Linux
make clean all
- build.gradle : a Gradle build file for all platforms
gradle clean assemble
- build.xml: an Ant build file for all platforms
ant clean all
gradle clean assemble
- pom.xml: a Maven POM for building the Maven artifacts
mvn clean package
mvn clean package
- build.sh: a simple and fast shell script for GNU/Linux.
./build.sh
Pick your favorite build tool and enjoy!

View File

@@ -40,13 +40,13 @@
</licenses>
<issueManagement>
<system>SourceForge.net Tracker</system>
<url>https://sourceforge.net/p/proguard/bugs/</url>
<system>Github Tracker</system>
<url>https://github.com/Guardsquare/proguard/issues</url>
</issueManagement>
<scm>
<url>https://hg.code.sf.net/p/proguard/code</url>
<connection>scm:hg:https://hg.code.sf.net/p/proguard/code</connection>
<url>https://github.com/Guardsquare/proguard.git</url>
<connection>scm:git:https://github.com/Guardsquare/proguard.git</connection>
</scm>
<properties>
@@ -65,6 +65,21 @@
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@@ -74,6 +89,7 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
@@ -97,20 +113,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -129,14 +131,6 @@
</plugins>
</build>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>
<modules>
<module>../core</module>
<module>../base</module>
@@ -160,4 +154,12 @@
</modules>
</profile>
</profiles>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>
</project>

View File

@@ -4,7 +4,11 @@
cd $(dirname "$0")
source ../buildscripts/functions.sh
if [ -f ../buildscripts/functions.sh ]; then
source ../buildscripts/functions.sh
else
source functions.sh
fi
MAIN_CLASS=proguard.*

106
core/docs/md/analyzing.md Normal file
View File

@@ -0,0 +1,106 @@
## Analyzing all instructions
If you want to analyze bytecode, you'll probably want to visit specified
instructions of specified code attributes of specified methods of specified
classes. The visitor classes and filters quickly get you to the right place:
programClassPool.classesAccept(
new AllMethodVisitor(
new AllAttributeVisitor(
new AllInstructionVisitor(
new MyInstructionAnalyzer()))));
You then only need to implement the visitor methods to analyze the
instructions:
class MyInstructionAnalyzer
implements InstructionVisitor
{
public void visitSimpleInstruction(Clazz clazz, .....) ...
public void visitVariableInstruction(Clazz clazz, .....) ...
public void visitConstantInstruction(Clazz clazz, .....) ...
public void visitBranchInstruction(Clazz clazz, .....) ...
public void visitTableSwitchInstruction(Clazz clazz, .....) ...
public void visitLookUpSwitchInstruction(Clazz clazz, .....) ...
}
The library already provides classes to analyze the code for you, finding
branching information, performing partial evaluation, finding the control flow
and data flow, etc, as introduced in the following sections.
Complete example: EvaluateCode.java
## Collecting basic branching information
You can extract basic information about branches in a method with the class
BranchTargetFinder. The results are defined at the instruction level: each
instruction is properly labeled as a branch target, branch origin, exception
handler, etc.
BranchTargetFinder branchTargetFinder =
new BranchTargetFinder();
branchTargetFinder.visitCodeAttribute(clazz, method, codeAttribute);
if (branchTargetFinder.isBranchOrigin(offset)) ...
if (branchTargetFinder.isBranchTarget(offset)) ...
Complete example: ApplyPeepholeOptimizations.java
## Basic control flow analysis
You can extract a basic control flow graph of the instructions in a method
with partial evaluation (often called abstract evaluation). The core class is
PartialEvaluator. Its results are defined at the instruction level: each
instruction is labeled with potential branch targets and branch origins.
ValueFactory valueFactory =
new BasicValueFactory();
PartialEvaluator partialEvaluator =
new PartialEvaluator(
new BasicInvocationUnit(valueFactory),
false);
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
InstructionOffsetValue branchOrigins = partialEvaluator.branchOrigins(offset));
InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset));
Complete example: VisualizeControlFlow.java
## Partial evaluation
You can extract a lot more information from a method with the same
PartialEvaluator, by tuning the precision of the partial evaluation with
different value factories and different invocation units:
- A ValueFactory defines the level of detail in representing values like
integers or reference types. The values can be very generic (any primitive
integer, a reference to any object) or more precise (the integer 42, or an
integer between 0 and 5, or a non-null reference to an instance of
java/lang/String).
- An InvocationUnit defines the values returned from retrieved fields and
invoked methods. The values can again be very generic (any integer) or they
can also be values that were cached in prior evaluations of the code base.
You can pass them to the PartialEvaluator, apply it to the code, and retrieve
the results:
ValueFactory valueFactory =
new RangeValueFactory(
new ArrayReferenceValueFactory());
PartialEvaluator partialEvaluator =
new PartialEvaluator(
new BasicInvocationUnit(valueFactory),
false);
partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
TracedStack stack = partialEvaluator.getStackAfter(offset);
Value value = stack.getTop(index);
Complete example: EvaluateCode.java

23
core/docs/md/building.md Normal file
View File

@@ -0,0 +1,23 @@
If you've downloaded the source code of the **ProGuard Core** library, you can
build it in a number of ways:
- build.gradle : a Gradle build file for all platforms.
gradle clean assemble
- pom.xml: a Maven POM for all platforms.
mvn clean package
- build.sh: a simple and fast shell script for GNU/Linux.
./build.sh
Once built, you can include the library and its dependencies in your own
projects.
You can also build the complete API documentation with
gradle javadoc
You can then find the [API documentation](../api/index.html) in `docs/api`.

33
core/docs/md/creating.md Normal file
View File

@@ -0,0 +1,33 @@
The easiest way to create a new class from scratch is with ClassBuilder. It
provides a fluent API to add fields and methods. For example, to create a
class that prints out "Hello, world!":
ProgramClass programClass =
new ClassBuilder(
VersionConstants.CLASS_VERSION_1_8,
AccessConstants.PUBLIC,
"HelloWorld",
ClassConstants.NAME_JAVA_LANG_OBJECT)
.addMethod(
AccessConstants.PUBLIC |
AccessConstants.STATIC,
"main",
"([Ljava/lang/String;)V",
50,
code -> code
.getstatic("java/lang/System", "out", "Ljava/io/PrintStream;")
.ldc("Hello, world!")
.invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V")
.return_())
.getProgramClass();
You can also use it to add fields and methods to an existing class:
ProgramClass programClass =
new ClassBuilder(existingClass)
.....
Complete example: CreateHelloWorldClass.java

18
core/docs/md/downloads.md Normal file
View File

@@ -0,0 +1,18 @@
The **ProGuard Core** library is distributed under the terms of the Apache
License Version 2.0. Please consult the [license page](license.md) for more
details.
ProGuard Core is written in Java, so it requires a Java Runtime Environment
(JRE 1.8 or higher).
You can download the library in various forms:
- [Pre-built artifacts](https://bintray.com/guardsquare/proguard) at JCenter
- [Pre-built artifacts](https://search.maven.org/search?q=g:net.sf.proguard) at Maven Central
- A [Git repository of the source code](https://github.com/Guardsquare/proguard-core) at Github
You can find major releases, minor releases with important bug fixes, and
beta releases with the latest new features and any less urgent bug fixes.
If you're still working with an older version of the library, check out the
[release notes](releasenotes.md), to see if you're missing something essential.

62
core/docs/md/editing.md Normal file
View File

@@ -0,0 +1,62 @@
## Editing classes
You can edit existing classes with ClassEditor and related editors like
InterfacesEditor, AttributesEditor, and ConstantPoolEditor.
ClassEditor classEditor =
new ClassEditor(targetClass);
classEditor.addField(field);
classEditor.addMethod(method);
If you want to create and add new fields or methods from scratch, you can use
the more convenient ClassBuilder:
ProgramClass programClass =
new ClassBuilder(existingClass)
.addField(
AccessConstants.PUBLIC |
AccessConstants.STATIC,
"someField",
TypeConstants.INT);
.addMethod(
AccessConstants.PUBLIC |
AccessConstants.STATIC,
"main",
"([Ljava/lang/String;)V",
50,
code -> code
.getstatic("java/lang/System", "out", "Ljava/io/PrintStream;")
.ldc("Hello, world!")
.invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V")
.return_())
.getProgramClass();
## Editing code
Perhaps more interestingly, you can edit the bytecode of method bodies with
CodeAttributeEditor.
CodeAttributeEditor codeAttributeEditor =
new CodeAttributeEditor();
InstructionSequenceBuilder builder =
new InstructionSequenceBuilder(targetClass);
Instructions[] replacementInstructions = builder
.getstatic("java/lang/System", "out", "Ljava/io/
.ldc("Hello")
.invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V" .instructions();
// Prepare the editor for this code.
codeAttributeEditor.reset(codeAttribute.u4codeLength);
// Insert the instruction sequence before a specified offset.
codeAttributeEditor.insertBeforeOffset(offset, replacementInstructions);
// Apply the changes.
codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);

BIN
core/docs/md/img/core.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

71
core/docs/md/index.md Normal file
View File

@@ -0,0 +1,71 @@
**ProGuard Core** is a free library to read, analyze, modify, and write Java
class files. It is the core of the well-known shrinker, optimizer, and
obfuscator [ProGuard](https://www.guardsquare.com/proguard) and of the
[ProGuard Assembler and
Disassembler](https://github.com/guardsquare/proguardassembler).
Typical applications:
- Perform peephole optimizations in Java bytecode.
- Search for instruction patterns.
- Analyze code with abstract evaluation.
- Optimize and obfuscate, like ProGuard itself.
## Design
The library defines many small classes as the building blocks for applications
that contain the processing logic. This is sometimes taken to the extreme: even
loops and conditional statements can often be implemented as separate classes.
Even though these classes are verbose and repetitive, the resulting main code
becomes much more compact, flexible, and robust.
### Data classes
Basic data classes define the structures to represent Java bytecode. They
reflect the Java bytecode specifications literally, to ensure that no data are
lost when reading, analyzing, and writing them. The data classes contain only
a minimum number of methods. They do have one or more accept methods to let
the visitor classes below operate on them.
### Visitor classes
The library applies the visitor pattern extensively. Visitor classes define
the operations on the data: reading, writing, editing, transforming,
analyzing, etc. The visitor classes have one or more 'visit' methods to
operate on data classes of the same basic type.
For example, a Java bytecode class contains a constant pool with constants of
different types: integer constants, float constants, string constants, etc.
The data classes IntegerConstant, FloatConstant, StringConstant, etc. all
implement the basic type Constant. The visitor interface ConstantVisitor
contains methods 'visitIntegerConstant', 'visitFloatConstant',
'visitStringConstant', etc. Implementations of this visitor interface can
perform all kinds of operations on the constants.
The reasoning behind this pattern is that the data classes are very stable,
because they are directly based on the bytecode specifications. The operations
are more dynamic, since they depend on the final application. It is
practically impossible to add all possible operations in the data classes, but
it is easy to add another implementation of a visitor interface. Implementing
an interface in practice helps a lot to think of all possible cases.
The visitor pattern uses visitor interfaces to operate on the similar elements
of a data structure. Each interface often has many implementations. A great
disadvantage at this time is that visitor methods can invoke one another
(directly or indirectly), but they can't communicate easily. Since the
implementations can't add their own parameters or return values, they often
have to rely on fields to pass values back and forth. This is more
error-prone. Still, the advantages of the visitor pattern outweigh the
disadvantages.
### Dependency injection
The library classes heavily use _constructor-based dependency injection_, to
create immutable instances. Notably the visitor classess are often like
commands that are combined in an immutable structure, via constructors. You
can execute such commands by applying the visitors to the data classes.
## API
You can find the complete API in the [ProGuard Core
javadoc](../api/index.html).

180
core/docs/md/license.md Normal file
View File

@@ -0,0 +1,180 @@
The ProGuard Core library is licensed under the Apache License Version 2.0.
Copyright 2002-2020 Guardsquare NV
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@@ -0,0 +1,70 @@
## Basic pattern matching
The library has powerful support to match patterns in bytecode instruction
sequences. You first define the pattern as a sequence of instructions, with
wildcards. For example:
final int X = InstructionSequenceMatcher.X;
final int C = InstructionSequenceMatcher.C;
InstructionSequenceBuilder ____ =
new InstructionSequenceBuilder();
Instruction[] pattern =
____.iload(X)
.bipush(C)
.istore(X).__();
Constant[] constants = ____.constants();
You can then find that pattern in given code:
programClassPool.classesAccept(
new AllMethodVisitor(
new AllAttributeVisitor(
new AllInstructionVisitor(
new MyMatchPrinter(
new InstructionSequenceMatcher(constants, pattern))))));
Complete example: ApplyPeepholeOptimizations.java
## Replacing patterns
Instead of just matching instruction sequences, you can also replace matched
sequences by other instruction sequences, for example to optimize code or
instrument code. The core classes are PeepholeEditor and
InstructionSequenceReplacer. Say that you want to replace an instruction
sequence "putstatic/getstatic" by an equivalent "dup/putstatic":
final int X = InstructionSequenceReplacer.X;
InstructionSequenceBuilder ____ =
new InstructionSequenceBuilder();
Instruction[][] replacements =
{
____.putstatic(X)
.getstatic(X).__(),
____.dup()
.putstatic(X).__()
};
Constant[] constants = ____.constants();
BranchTargetFinder branchTargetFinder = new BranchTargetFinder();
CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor();
programClassPool.classesAccept(
new AllMethodVisitor(
new AllAttributeVisitor(
new PeepholeEditor(branchTargetFinder, codeAttributeEditor,
new InstructionSequenceReplacer(constants,
replacements,
branchTargetFinder,
codeAttributeEditor)))));
You can define multiple patterns and their respective replacements in one go,
with the wrapper InstructionSequencesReplacer.
Complete example: ApplyPeepholeOptimizations.java

84
core/docs/md/reading.md Normal file
View File

@@ -0,0 +1,84 @@
## Streaming classes from a jar file
You can read classes from class files and various types of (nested) jar files
or jmod files, with some convenient utility classes and visitors. For example,
you can read the classes from a jar file and print them out in a streaming
fashion, without collecting their representations:
DirectoryPump directoryPump =
new DirectoryPump(
new File(inputJarFileName));
directoryPump.pumpDataEntries(
new JarReader(
new ClassFilter(
new ClassReader(false, false, false, false, null,
new ClassPrinter()))));
Note the constructor-based dependency injection of visitor classes. We
typically use a slightly unconventional indentation to make this construct
easy to read.
Complete example: PrintClasses.java
## Writing out streamed classes
You can read classes, optionally perform some small modifications, and write
them out right away, again in a streaming fashion.
JarWriter jarWriter =
new JarWriter(
new ZipWriter(
new FixedFileWriter(
new File(outputJarFileName))));
DirectoryPump directoryPump =
new DirectoryPump(
new File(inputJarFileName));
directoryPump.pumpDataEntries(
new JarReader(
new ClassFilter(
new ClassReader(false, false, false, false, null,
new DataEntryClassWriter(jarWriter)))));
jarWriter.close();
Complete example: ApplyPeepholeOptimizations.java
## Collecting classes
Alternatively, you may want to collect the classes in a so-called class pool
first, so you can perform more extensive analyses on them:
ClassPool classPool = new ClassPool();
DirectoryPump directoryPump =
new DirectoryPump(
new File(jarFileName));
directoryPump.pumpDataEntries(
new JarReader(false,
new ClassFilter(
new ClassReader(false, false, false, false, null,
new ClassPoolFiller(classPool)))));
Complete example: Preverify.java
## Writing out a set of classes
If you've collected a set of classes in a class pool, you can write them out
with the same visitors as before.
JarWriter jarWriter =
new JarWriter(
new ZipWriter(
new FixedFileWriter(
new File(outputJarFileName))));
classPool.classesAccept(
new DataEntryClassWriter(jarWriter));
jarWriter.close();
Complete example: Preverify.java

View File

@@ -0,0 +1,5 @@
## Version 7.0 (Jan 2020)
| Version| Issue | Module | Explanation
|--------|----------|----------|----------------------------------
| 7.0.0 | | CORE | Initial release, extracted from ProGuard.

70
core/docs/mkdocs.yml Normal file
View File

@@ -0,0 +1,70 @@
###################################################################
# Project information
###################################################################
site_name: ProGuard Core
site_description: The ProGuard Core library
site_author: Guardsquare NV
copyright: Copyright &copy; 2002-2020 Guardsquare NV
###################################################################
# Options
###################################################################
theme:
name: null
custom_dir: ../../buildscripts/mkdocs/material
logo: img/core.png
favicon: img/guardsquare.png
language: en
palette: blue
font:
feature:
docs_dir: md
site_dir: html
#extra_css:
# - extra.css
use_directory_urls: false
#strict: true # broken links are errors
###################################################################
# Theme specific
###################################################################
extra:
#font:
# text: 'Droid Sans'
# code: 'Ubuntu Mono'
social:
- type: 'twitter'
link: 'https://twitter.com/guardsquare'
- type: 'linkedin'
link: 'https://www.linkedin.com/company/guardsquare-nv'
- type: 'facebook'
link: 'https://www.facebook.com/guardsquare'
#feature:
# tabs: true
###################################################################
# Extensions
###################################################################
markdown_extensions:
- attr_list
- admonition
- footnotes
- def_list
###################################################################
# Page tree
###################################################################
nav:
- Introduction: index.md
- Reading classes: reading.md
- Creating classes: creating.md
- Editing classes: editing.md
- Pattern matching: patternmatching.md
- Analyzing code: analyzing.md
- License: license.md
- Downloads: downloads.md
- Building: building.md
- Release notes: releasenotes.md

80
core/functions.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
#
# Support functions for building ProGuard.
SRC=src
OUT=out
LIB=lib
TARGET=1.8
PROGUARD_JAR=$LIB/proguard.jar
set -o pipefail
function download {
if [ ! -f "$2" ]; then
echo "Downloading $2..."
mkdir -p $(dirname "$2") && \
if type wget > /dev/null 2>&1; then
wget -O "$2" "$1"
else
curl -L -o "$2" "$1"
fi
fi
}
function compile {
echo "Compiling $(basename $PWD) ($1)..."
mkdir -p "$OUT" && \
# Compile Java source files.
find $SRC -name '_*.java' -o -path "$SRC/${1//.//}.java" \
| xargs --no-run-if-empty \
javac -nowarn -Xlint:none \
-source $TARGET -target $TARGET \
-sourcepath "$SRC" -d "$OUT" \
${2:+-classpath "$2"} 2>&1 \
| sed -e 's|^| |' || return 1
# Compile Kotlin source files.
#find $SRC -path "$SRC/${1//.//}.kotlin" \
#| xargs --no-run-if-empty \
# kotlinc -nowarn -jvm-target $TARGET \
# -d "$OUT" \
# ${2:+-classpath "$2"} 2>&1 \
#| sed -e 's|^| |' || return 1
# Compile Groovy source files.
find $SRC -path "$SRC/${1//.//}.groovy" \
| xargs --no-run-if-empty \
groovyc \
-sourcepath "$SRC" -d "$OUT" \
${2:+-classpath "$2"} 2>&1 \
| sed -e 's|^| |' || return 1
# Copy resource files.
(cd "$SRC" && \
find proguard \
\( -name \*.properties -o -name \*.png -o -name \*.gif -o -name \*.pro \) \
-exec cp --parents {} "../$OUT" \; )
}
function createjar {
echo "Creating $1..."
mkdir -p $(dirname "$1") && \
if [ -f "$SRC/META-INF/MANIFEST.MF" ]; then
jar -cfm "$1" "$SRC/META-INF/MANIFEST.MF" -C "$OUT" proguard
else
jar -cf "$1" -C "$OUT" proguard
fi
}
function updatejar {
echo "Updating $1..."
if [ -f "$SRC/META-INF/MANIFEST.MF" ]; then
jar -ufm "$1" "$SRC/META-INF/MANIFEST.MF" -C "$OUT" proguard
else
jar -uf "$1" -C "$OUT" proguard
fi
}

View File

@@ -2,5 +2,5 @@
target = 1.8
kotlinVersion=1.3.31
kotlinxMetadataVersion=0.1.0
kotlinVersion = 1.3.31
kotlinxMetadataVersion = 0.1.0

View File

@@ -1,40 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Maven POM file for ProGuard. -->
<!-- Maven POM file for the ProGuard Core library. -->
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-parent</artifactId>
<version>6.2.2</version>
<relativePath>../buildscripts/pom.xml</relativePath>
</parent>
<artifactId>proguard-base</artifactId>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-core</artifactId>
<version>7.0.0</version>
<name>[${project.groupId}] ${project.artifactId}</name>
<description>ProGuard Core is a free library to read, analyze, modify, and write Java class files.</description>
<url>https://github.com/Guardsquare/proguard-core</url>
<prerequisites>
<maven>3</maven>
</prerequisites>
<developers>
<developer>
<id>lafortune</id>
<name>Eric Lafortune</name>
<url>https://www.guardsquare.com/proguard</url>
<organization>Guardsquare</organization>
<organizationUrl>https://www.guardsquare.com/</organizationUrl>
<roles>
<role>Project Administrator</role>
<role>Developer</role>
</roles>
</developer>
</developers>
<licenses>
<license>
<name>Apache License Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<issueManagement>
<system>Github Tracker</system>
<url>https://github.com/Guardsquare/proguard-core/issues</url>
</issueManagement>
<scm>
<url>https://github.com/Guardsquare/proguard-core.git</url>
<connection>scm:git:https://github.com/Guardsquare/proguard-core.git</connection>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<sourceDirectory>src</sourceDirectory>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<links>
<link>https://download.oracle.com/javase/1.5.0/docs/api/</link>
</links>
<quiet>true</quiet>
</configuration>
<executions>
<execution>
<id>attach-javadoc</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>proguard.ProGuard</mainClass>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -44,25 +170,31 @@
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.3.31</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-common</artifactId>
<version>1.3.31</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-metadata-jvm</artifactId>
<version>0.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jcenter</id>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
<name>Nexus Release Repository</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>
</project>

View File

@@ -1,8 +1,7 @@
You can find the ReTrace jar in the `lib` directory of the ProGuard
distribution. To run ReTrace, just type:
`java -jar retrace.jar `\[*options...*\] *mapping\_file*
\[*stacktrace\_file*\]
java -jar retrace.jar <options...> <mapping_file> <stacktrace_file>
Alternatively, the `bin` directory contains some short Linux and Windows
scripts containing this command. These are the arguments:

View File

@@ -1,16 +1,16 @@
To run ProGuard, just type:
`bin/proguard `*options* ...
bin/proguard <options...>
Typically, you'll put most options in a configuration file (say,
`myconfig.pro`), and just call:
`bin/proguard @myconfig.pro`
bin/proguard @myconfig.pro
You can combine command line options and options from configuration
files. For instance:
`bin/proguard @myconfig.pro -verbose`
bin/proguard @myconfig.pro -verbose
You can add comments in a configuration file, starting with a `#`
character and continuing until the end of the line.

View File

@@ -6,6 +6,9 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/out" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View File

@@ -1,2 +1,2 @@
includeFlat 'base'
includeFlat 'core'
includeFlat 'base'