Blog | Phodal - A Growth Engineerhttp://www.phodal.com/blog/2020-10-11T00:59:23.066373+00:00BlogGradle IDEA 的项目模型2020-10-11T00:58:45+00:002020-10-11T00:59:23.066373+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/gradle-idea-project-model/最近在为新的工具 [Scie](https://github.com/phodal/scie/) 设计一个模型,以用于描述一个具体的代码工程。而刚好最近也在学习 Gradle 相关的项目模型,便想写一篇文章记录一下相关的模型,以支撑起 Scie 的开发。
PS:相关的代码位于 Gradle 源码中的 IDE 部分。
总体来说,用于支撑 IDE 开发的这个模型主要由这么几部分组成:
- Project,最顶层的类,包含项目的所有信息。
- Modules,模块,包含单个模块的信息。
- GradleProject,包含一个模块的 Gradle 的相关信息。
- ContentRoot,源码部分。
- Dependency,依赖
从目录上来看总体的类便是,这个就是我们所需要的所有 Gradle 的 IDEA 相关的接口模型了。
- BasicIdeaProject
- IdeaCompilerOutput
- IdeaContentRoot
- IdeaDependency
- IdeaDependencyScope
- IdeaJavaLanguageSettings
- IdeaLanguageLevel
- IdeaModule
- IdeaModuleDependency
- IdeaModuleIdentifier
- IdeaProject
- IdeaSingleEntryLibraryDependency
不过,还是让我们从头看起,即 IdeaProject 部分。
## IdeaProject
IdeaProject 部分的代码相对来说还是比较简单的,主要描述了项目相关的模块(Module)、JDK 信息和对应的语言版本等。
```java
public interface IdeaProject extends HierarchicalElement {
IdeaJavaLanguageSettings getJavaLanguageSettings() throws UnsupportedMethodException;
String getJdkName();
IdeaLanguageLevel getLanguageLevel();
DomainObjectSet<? extends IdeaModule> getChildren();
DomainObjectSet<? extends IdeaModule> getModules();
}
```
为了文章的完整性,我补充一下相关的接口类:
```java
public interface HierarchicalElement extends Element {
@Nullable
HierarchicalElement getParent();
DomainObjectSet<? extends HierarchicalElement> getChildren();
}
public interface Element extends Model {
String getName();
@Nullable
String getDescription();
}
```
接着,就是 IdeaModule 部分了。
## IdeaModule
代码也相对比较简单:
```java
public interface IdeaModule extends HierarchicalElement, HasGradleProject {
@Nullable
IdeaJavaLanguageSettings getJavaLanguageSettings() throws UnsupportedMethodException;
String getJdkName() throws UnsupportedMethodException;
DomainObjectSet<? extends IdeaContentRoot> getContentRoots();
GradleProject getGradleProject();
IdeaProject getParent();
IdeaProject getProject();
IdeaCompilerOutput getCompilerOutput();
DomainObjectSet<? extends IdeaDependency> getDependencies();
}
```
除了 Java 相关的配置信息,还有几个点值得关注:
- 描述源码相关的 IdeaContentRoot
- 描述 Gradle 信息的 GradleProject
- 描述依赖的 IdeaDependency
- 描述输出的 IdeaCompilerOutput
这里我们主要关注于 `IdeaContentRoot` 和 `IdeaDependency`
## IdeaContentRoot
IdeaContentRoot,是用于描述源码相关的信息。这里,只需要看一下对应的接口,就能了解对应的信息了:
```java
public interface IdeaContentRoot {
File getRootDirectory();
DomainObjectSet<? extends IdeaSourceDirectory> getSourceDirectories();
DomainObjectSet<? extends IdeaSourceDirectory> getGeneratedSourceDirectories();
DomainObjectSet<? extends IdeaSourceDirectory> getTestDirectories();
DomainObjectSet<? extends IdeaSourceDirectory> getGeneratedTestDirectories();
DomainObjectSet<? extends IdeaSourceDirectory> getResourceDirectories() throws UnsupportedMethodException;
DomainObjectSet<? extends IdeaSourceDirectory> getTestResourceDirectories() throws UnsupportedMethodException;
Set<file> getExcludeDirectories();
}
```
简单来说,就是我们在使用 IDE 的过程中,用于开发的那些要素:源码、测试代码、资源等等。
## IdeaDependency
由于依赖采用的是 `DomainObjectSet<? extends IdeaDependency>`,即继承了这个接口的类都行,于是我找到了:
```java
public interface IdeaSingleEntryLibraryDependency extends IdeaDependency, ExternalDependency {
File getFile();
File getSource();
File getJavadoc();
}
```
不过,我并没有在 Gradle 的代码里找到对应的实现类,而是在 Intellij IDEA 的源码里找到了:`InternalIdeaSingleEntryLibraryDependency`,真是有趣。
## 结论
抽象和描述一个项目并不是一件容易的事情。</file>R8 的编译和使用2020-09-25T11:40:20+00:002020-09-25T11:53:50.241939+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/r8-compile-and-usage/项目上需要使用 R8 来对 Java 代码进行压缩、混淆,并转换为多个 dex 的形式。由于种种原因,需要从头编译源码,并通过 jar 包引用。考虑到可重复过程的问题,我决定写一篇文章记录一下这个过程。
## 编译 R8
R8 的编译还是蛮简单的,主要步骤在源码上有: [https://r8.googlesource.com/r8](https://r8.googlesource.com/r8)。
但是呢,上面少了一个步骤,即安装 `depot_tools`。
1. 安装 depot_tools
```
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
```
2. 添加到环境变量
```
export PATH=$HOME/android/depot_tools:"$PATH"
```
3. 进行编译
```
tools/gradle.py d8 r8
```
这样一来就能得到我们想要的包:
```
build/libs
├── d8.jar
├── d8.jar.zip
├── deps_all.jar
├── r8-src.jar
├── r8.jar
├── r8.jar.zip
├── r8_with_deps.jar
├── r8_with_relocated_deps.jar
└── sources_main.jar
```
有了 jar 包以后,我们要使用就比较简单。
## R8 使用
R8 的使用也相当的简单,只需要 `java -jar build/libs/d8.jar`,从中我们就可以看到对应的参数:
```bash
Usage: d8 [options] [@<argfile>] <input-files>
where <input-files> are any combination of dex, class, zip, jar, or apk files
and each <argfile> is a file containing additional arguments (one per line)
and options are:
--debug # Compile with debugging information (default).
--release # Compile without debugging information.
--output <file> # Output result in <outfile>.
# <file> must be an existing directory or a zip file.
--lib <file|jdk-home> # Add <file|jdk-home> as a library resource.
--classpath <file> # Add <file> as a classpath resource.
--min-api <number> # Minimum Android API level compatibility, default: 1.
--pg-map <file> # Use <file> as a mapping file for distribution.
--intermediate # Compile an intermediate result intended for later
# merging.
--file-per-class # Produce a separate dex file per class.
# Synthetic classes are in their own file.
--file-per-class-file # Produce a separate dex file per input .class file.
# Synthetic classes are with their originating class.
--no-desugaring # Force disable desugaring.
--desugared-lib <file> # Specify desugared library configuration.
# <file> is a desugared library configuration (json).
--main-dex-list <file> # List of classes to place in the primary dex file.
--main-dex-list-output <file>
# Output resulting main dex list in <file>.
--force-enable-assertions[:[<class name="">|<package name="">...]]
--force-ea[:[<class name="">|<package name="">...]]
# Forcefully enable javac generated assertion code.
--force-disable-assertions[:[<class name="">|<package name="">...]]
--force-da[:[<class name="">|<package name="">...]]
# Forcefully disable javac generated assertion code. This
# is the default handling of javac assertion code when
# generating DEX file format.
--force-passthrough-assertions[:[<class name="">|<package name="">...]]
--force-pa[:[<class name="">|<package name="">...]]
# Don't change javac generated assertion code. This
# is the default handling of javac assertion code when
# generating class file format.
--version # Print the version of d8.
--help # Print this message.
```
### 转换 dex
接着,我们可以写一个 hello, world 进行测试:
```
java -jar build/libs/r8_with_deps.jar --output out.jar hello.jar --classpath ~/android/sdk/platforms/android-30/android.jar
```
看它是否能将其转换为我们所需要的 dex 格式。
### 混淆
为了正确地混淆,我们需要添加 `--pg-conf proguard-common.txt` 参数,并添加一些 `keep` 的规则,如:
```
-keep class Main {
static void main(java.lang.String[]);
}
```
以保留我们的类,生成可用的 dex 文件。
### multiDex
除了这个场景,我们还需要考虑 multiDex 的场景,同样的也只需要一个参数 `--main-dex-rules maindexclasses.txt`。
如下是 Android 的相关配置:
```
-keep public class * extends android.app.Instrumentation {
}
-keep public class * extends android.app.Application {
}
-keep public class * extends android.app.Activity {
}
-keep public class * extends android.app.Service {
}
-keep public class * extends android.content.ContentProvider {
}
-keep public class * extends android.content.BroadcastReceiver {
}
-keep public class * extends android.app.backup.BackupAgent {
}
-keep class android.support.multidex.** {
*;
}
```
嗯,就是这么简单。
## DX 历史
顺便一提,在旧版本的 Android 开发环境中,是使用 dx 工具来使用 maindexlist.txt 文件的。
其通过 SDK 工具中的 `mainDexClasses` 对源码进行扫描,生成 `main-dex-list`
会生成一个类似如下的文件,包含所有需要包含在主 dex 的文件:
```
rx/android/concurrency/AndroidSchedulers.class
rx/android/concurrency/HandlerThreadScheduler.class
android/support/v4/view/GravityCompat.class
android/support/v4/view/ViewCompat$AccessibilityLiveRegion.class
android/support/v4/view/MenuCompat.class
android/support/v4/view/ViewCompat$ImportantForAccessibility.class
android/support/v4/view/ViewCompat$OverScroll.class
android/support/v4/view/ViewCompat.class
android/support/v4/view/ViewCompat$LayoutDirectionMode.class
android/support/v4/view/ViewCompat$LayerType.class
android/support/v4/view/ViewCompat$ResolvedLayoutDirectionMode.class
android/support/v4/content/ContextCompat.class
android/support/v4/util/LogWriter.class
android/support/v4/util/SimpleArrayMap.class
android/support/v4/util/DebugUtils.class
android/support/v4/app/ActivityCompat.class
android/support/v4/app/FragmentManagerImpl$2.class
android/support/v4/app/FragmentContainer.class
android/support/v4/app/FragmentTransaction$Transit.class
android/support/v4/app/FragmentManagerImpl$5.class
android/support/v4/app/FragmentActivity$2.class
android/support/v4/app/BackStackRecord$TransitionState.class
...
```
再把这个文件添加到参数中即可:` --main-dex-list`。
同样的,对于旧的格式,我们也可以通过 `--main-dex-list-output` 来生成。只是呢,我们根本不需要这个过程。</package></class></package></class></package></class></package></class></package></class></package></class></file></file></file></file></file></file></file></number></file></file></file|jdk-home></file|jdk-home></file></outfile></file></argfile></input-files></input-files></argfile>自制 Gradle 依赖格式及转换插件2020-08-22T10:33:45+00:002020-08-22T10:34:23.807406+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/custom-gradle-dependency-and-transform/在我们使用 Java + Gradle 开发各类应用的过程中,会发现我们声明的一些包不是 jar 包,诸如 zip、war、aar 等。它也会下载下来,并转换到我们所需要的格式。
这个过程蛮有意思的:
1. 注册对应的 DependencyHandler Transform
2. 创建自定义的 configuration
3. 在接收到对应的 configuration 时,进行依赖转换
4. 在使用时,通过 configuration 获取到对应的制品(artifacts)
5. 在编译的时候,取出这些制品的路径
在我找了好久之后,终于在官方项目的 issue 里找到了一个示例:[https://github.com/gradle/gradle/issues/13200](https://github.com/gradle/gradle/issues/13200) 。这里就基于这个示例来进行讲解。
## 定制 Transfrom
先看这个逻辑:
```java
def artifactType = Attribute.of('artifactType', String)
dependencies.registerTransform(MyTransform.class) {
it.from.attribute(artifactType, "jar")
it.to.attribute(artifactType, "my-custom-type")
}
```
当我们接收到 `jar` 这一类的制品时(`artifact`),会调用 `MyTransform`,并将其转换为 `my-custom-type`。`my-custom-type` 只是一种状态标记,方便于我们后面对其进行二次处理。
## Transform 逻辑
对应的 Transfrom 实现如下:
```java
abstract class MyTransform implements TransformAction<transformparameters.none> {
@InputArtifact
public abstract Provider<filesystemlocation> getPrimaryInput();
@Override
void transform(TransformOutputs transformOutputs) {
File file = getPrimaryInput().get().asFile;
println "Processing $file. File exists = ${file.exists()}"
if (file.exists()) {
File outputFile = transformOutputs.file("copy");
Files.copy(file.toPath(), outputFile.toPath())
} else {
throw new RuntimeException("File does not exist: " + file.canonicalPath);
}
}
}
```
没有什么特殊处理,只是简单的记录一下。
## 自定义 Configuration
自定义 Configuration 也依旧很简单
```java
Configuration myConfiguration = configurations.create("myConfiguration")
dependencies.add(myConfiguration.name, "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.70")
```
## 在 Task 中消费处理完的 Transform
当我们运行 Gradle 的命令时,会先调用依赖处理逻辑,于是就进行了转换。因此,我们可以写一个 task 取出依赖完的依赖,并使用它。
```
tasks.register("consumerTask", ConsumerTask.class) {
it.artifactCollection = myConfiguration.incoming.artifactView { ArtifactView.ViewConfiguration viewConfiguration ->
viewConfiguration.attributes.attribute(artifactType, "my-custom-type")
}.artifacts
it.outputFile.set(new File("build/consumerTask/output/output.txt"))
}
```
对应的 Task 实现:
```java
abstract class ConsumerTask extends DefaultTask {
@Internal
public ArtifactCollection artifactCollection;
@InputFiles
public FileCollection getMyInputFiles() {
return artifactCollection.artifactFiles
}
@OutputFile
public abstract RegularFileProperty getOutputFile();
@TaskAction
public void doTask() {
File outputFile = getOutputFile().get().asFile
outputFile.delete()
outputFile.parentFile.mkdirs()
String outputContent = "";
for(File f: getMyInputFiles().files) {
outputContent += f.canonicalPath + "\n"
}
Files.write(outputFile.toPath(), outputContent.getBytes())
}
}
```
嗯,就是这么简单 :) 。</filesystemlocation></transformparameters.none>自制简易 Gradle 的 Java 编译器插件2020-08-22T09:27:16+00:002020-08-23T06:58:04.062133+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/build-custom-gradle-java-compile-plugin/最近,因为兴趣 + 项目的需要,研究了一下 Gradle 相关源码中关于 Java 编译的实现。也顺便按照相关的 Gradle 插件,做了一个简单的插件,了解了相关的原理。
主要步骤如下:
1. 创建、配置 Gradle 的 configurations
2. 创建 task
3. 在 task 中,获取 configurations
4. 在 task 中,配置编译参数
5. 调用 Gradle 插件中的 JavaCompile
6. 完美
相关的文档主要在:[Defining custom configurations](https://docs.gradle.org/current/userguide/declaring_dependencies.html#sec:defining-custom-configurations)
## 创建自定义的 Gradle Configuration
如果是使用 `build.gradle` 的话,那么步骤相当的简单:
```groovy
configurations {
jasper
}
dependencies {
jasper 'org.apache.tomcat.embed:tomcat-embed-jasper:9.0.2'
}
```
而在这里,我们写的是 Gradle 插件,所以要用 Groovy 来编写,稍微麻烦一些:
```groovy
val compile = createConfiguration("implementation", true)
compile.dependencies.whenObjectAdded(SomeImplementationAction())
val phodalCompile = createConfiguration("phodalImplementation", true)
phodalCompile.dependencies.whenObjectAdded(SomeImplementationAction())
```
这样一来,我们就可以在 task 中,获取到相应的配置。
## 获取 Gradle Configurations
当我们在 Gradle 中引入测试的时候,需要通过 `testImplementation` 来声明测试依赖。在编译的时候,`implementation` 会和 `testImplementation` 一起加入到编译的 classpath 中。所以在我们的场景这下,我自定义了 `phodalImplementation`,以便测试是否能正常获取 依赖:
```groovy
val config: Configuration = configurations.getByName("implementation")
compileClasspaths.add(config)
val compileClasspath: Configuration = configurations.getByName("phodalImplementation")
compileClasspaths.add(compileClasspath)
this.classpath = mergeClassPath(configurations, compileClasspaths)
```
在 mergeClassPath 中,主要是调用 `setExtendsFrom` 来整合依赖:
```kotlin
private fun mergeClassPath(configurations: ConfigurationContainer, mutableSet: MutableSet<configuration>): Configuration {
val finalPath = configurations.maybeCreate("finalCompileClasspath")
finalPath.isVisible = false
finalPath.description = "Resolved configuration for compilation for variant"
finalPath.setExtendsFrom(mutableSet)
finalPath.isCanBeConsumed = false
finalPath.resolutionStrategy.sortArtifacts(ResolutionStrategy.SortOrder.CONSUMER_FIRST)
return finalPath
}
```
接着,我们就可以配置 JavaCompile 了:
## 配置 JavaCompile
对于编译来说,也是蛮简单了,配置一下 `source`、`classpath`、`outputs`、`destinationDir` 之类的就可以了:
```kotlin
this.classpath = mergeClassPath(configurations, compileClasspaths)
this.source = this.project.files(javaSource.toList()).asFileTree
this.outputs.dir("build/classes")
this.destinationDir = File("build/classes")
this.options.isIncremental = true
```
然后在 `compile` 方法中调用 JavaCompile 的编译即可:
```
override fun compile(inputs: InputChanges) {
super.compile(inputs)
}
```
## JavaCompile 的过程
最后,运行到了 Gradle 代码里了:
```java
@Incubating
@TaskAction
protected void compile(InputChanges inputs) {
DefaultJavaCompileSpec spec = createSpec();
if (!compileOptions.isIncremental()) {
performFullCompilation(spec);
} else {
performIncrementalCompilation(inputs, spec);
}
}
```
Gradle 会将上一步中的 Configuration 里的东西取出来,并将 FileCollection 转为 `List<file>`。接着,根据配置选择合适的编译方式:
```java
private static class ProjectScopeCompileServices {
JavaCompilerFactory createJavaCompilerFactory(WorkerDaemonFactory workerDaemonFactory, Factory<javacompiler> javaHomeBasedJavaCompilerFactory, JavaForkOptionsFactory forkOptionsFactory, WorkerDirectoryProvider workerDirectoryProvider, ExecHandleFactory execHandleFactory, AnnotationProcessorDetector processorDetector, ClassPathRegistry classPathRegistry, ActionExecutionSpecFactory actionExecutionSpecFactory) {
return new DefaultJavaCompilerFactory(workerDirectoryProvider, workerDaemonFactory, javaHomeBasedJavaCompilerFactory, forkOptionsFactory, execHandleFactory, processorDetector, classPathRegistry, actionExecutionSpecFactory);
}
JavaToolChainInternal createJavaToolChain(JavaCompilerFactory compilerFactory, ExecActionFactory execActionFactory) {
return new CurrentJvmJavaToolChain(compilerFactory, execActionFactory);
}
JavaToolChainFactory createJavaToolChainFactory(JavaCompilerFactory compilerFactory, ExecActionFactory execActionFactory, JvmVersionDetector jvmVersionDetector) {
return new JavaToolChainFactory(compilerFactory, execActionFactory, jvmVersionDetector);
}
}
```
如使用 `DefaultJavaCompilerFactory` 的话,将会通过 `JavaCompilerArgumentsBuilder` 来直接调用 `javac` 进行编译,并进行相关的参数配置,如:
```java
private void addSourcePathArg(List<string> compilerArgs, MinimalJavaCompileOptions compileOptions) {
Collection<file> sourcepath = compileOptions.getSourcepath();
boolean emptySourcePath = sourcepath == null || sourcepath.isEmpty();
...
args.add("-sourcepath");
args.add(GUtil.asPath(sourcepath));
}
```
嗯,然后我们就编译完成了。</file></string></javacompiler></file></configuration>Homebrew versions安装特定版本软件2014-11-14T15:07:05+00:002015-02-05T07:09:21.026813+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/use-brew-versions-manage-specif-software-version/在之前有一篇文章是[brew versions gradle安装指定版本gradle](http://www.phodal.com/blog/homebrew-version-manage-gradle-version/),结果在重新试了下之后失败了。
##brew versions
出现了下面的错误
brew versions gradle
Error: Unknown command: versions
原因是在更新Mac OS的时候一些东西已经没了
##brew versions install
所以需要tap这个
brew tap homebrew/boneyard
接着就可以使用``brew versions``
Warning: brew-versions is unsupported and will be removed soon.
You should use the homebrew-versions tap instead:
https://github.com/Homebrew/homebrew-versions
2.1 git checkout 5475eb4 /usr/local/Library/Formula/gradle.rb
2.0 git checkout 94fcdae /usr/local/Library/Formula/gradle.rb
1.12 git checkout 8ef0672 /usr/local/Library/Formula/gradle.rb
1.11 git checkout 01f2e6f /usr/local/Library/Formula/gradle.rb
1.10 git checkout c6baa40 /usr/local/Library/Formula/gradle.rb
1.9 git checkout 5bab5e9 /usr/local/Library/Formula/gradle.rb
1.8 git checkout 9214e60 /usr/local/Library/Formula/gradle.rb
1.7 git checkout f826cc9 /usr/local/Library/Formula/gradle.rb
1.6 git checkout fff7c0b /usr/local/Library/Formula/gradle.rb
1.5 git checkout 57931e0 /usr/local/Library/Formula/gradle.rb
brew versions gradle安装指定版本gradle2014-02-13T09:59:53+00:002014-05-14T19:21:55.221364+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/homebrew-version-manage-gradle-version/1. 查看gradle版本
<pre><code class="bash">gradle -v
</code></pre>
2. 我们需要 uninstall gradle
<pre><code class="bash">brew uninstall gradle
</code></pre>
3.查看所有gradle版本
<pre><code class="bash">brew versions gradle
</code></pre>
下面就是所有gradle的版本
<pre><code class="bash">
1.10 git checkout 2b10422 Library/Formula/gradle.rb
1.9 git checkout 5bab5e9 Library/Formula/gradle.rb
1.8 git checkout 9214e60 Library/Formula/gradle.rb
1.7 git checkout f826cc9 Library/Formula/gradle.rb
1.6 git checkout fff7c0b Library/Formula/gradle.rb
1.5 git checkout 57931e0 Library/Formula/gradle.rb
1.4 git checkout 0b7303a Library/Formula/gradle.rb
1.3 git checkout c259bda Library/Formula/gradle.rb
1.2 git checkout 9b7d294 Library/Formula/gradle.rb
1.1 git checkout 7941972 Library/Formula/gradle.rb
1.0 git checkout dff67fb Library/Formula/gradle.rb
1.0-rc-3 git checkout 5f9e348 Library/Formula/gradle.rb
1.0-rc-2 git checkout f72e33f Library/Formula/gradle.rb
1.0-rc-1 git checkout e2438cf Library/Formula/gradle.rb
1.0-milestone-9 git checkout c27c667 Library/Formula/gradle.rb
1.0-milestone-8a git checkout 69eb948 Library/Formula/gradle.rb
1.0-milestone-8 git checkout 34da975 Library/Formula/gradle.rb
1.0-milestone-7 git checkout 6a8c437 Library/Formula/gradle.rb
1.0-milestone-6 git checkout dae625d Library/Formula/gradle.rb
1.0-milestone-5 git checkout baff305 Library/Formula/gradle.rb
1.0-milestone-3 git checkout d9f2e06 Library/Formula/gradle.rb
1.0-milestone-4 git checkout 4b1230c Library/Formula/gradle.rb
1.0-milestone-2 git checkout 6801464 Library/Formula/gradle.rb
1.0-milestone-1 git checkout 0476235 Library/Formula/gradle.rb
0.9.2 git checkout 38b9338 Library/Formula/gradle.rb
0.9.1 git checkout f986d7d Library/Formula/gradle.rb
0.9 git checkout 45e09d7 Library/Formula/gradle.rb
0.8 git checkout e6f608f Library/Formula/gradle.rb
</code></pre>
4. checkout到指定版本
<pre><code class="bash">cd /usr/local
</code></pre>
<pre><code class="bash">git checkout 2b10422 Library/Formula/gradle.rb
</code></pre>
5.安装指定版本gradle
<pre><code class="bash">brew install gradle
</code></pre>CentOS Jetty Gradle Nginx,CentOS部署Java web应用2013-12-19T21:04:40+00:002014-05-14T14:19:30.862324+00:00Phodal Huanghttp://www.phodal.com/blog/author/root/http://www.phodal.com/blog/Centos-gradle-jetty/<p>
偶然间突然奇想,决定把和小伙伴们做的bbs丢到服务器上。于是就这么开始了,花了两三个小时的时间总算是有结果了。
</p>
<p>
只是512M的VPS似乎有点儿,伤不起,然后让我们开始。
</p>
<p>
不是很懂java,不过感觉我只需要关心gradle以及jetty就够了,最后发现,我不需要关心jetty,只需要关心JDK+Gradle
</p>
<p>
<br/>
</p>
<h2>
CentOS JDK
</h2>
<p>
一开始打算用openJDK,无奈的是似乎没有配置好,所以就来到了万恶的Oracle的官网上,同时让我们怀念一下SUN吧。
</p>
<p>
下载地址 <a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html" target="_blank">http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html</a>
</p>
<p>
同意完之后,下载rpm版的JDK,依64位,或者是32位而定了
</p>
<p>
接下来就是要求以及设置JAVA_HOME环境变量了。<span>(转载保留 </span><a href="http://blog.phodal.com/thoughtworks-yue-xiao/" target="_blank">Phodal's Blog</a><span> </span><a href="http://blog.csdn.net/phodal" target="_blank">Phodal's zenthink</a><span>) </span>
</p>
<p>
CentOS JDK
</p>
<p>
</p>
<pre class="plain" name="code">rpm -ivh jdk*.rpm</pre>
<p>
</p>
<p>
设置环境变量
</p>
<p>
</p>
<pre class="plain" name="code">vim /etc/profile</pre>
查看一下自己JDK的PATH,再修改。
<p>
</p>
<p>
</p>
<pre class="plain" name="code">JAVA_HOME=/usr/java/jdk1.7.0_45
JRE_HOME=/usr/java/jdk1.7.0_45/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH
</pre>
应用
<p>
</p>
<p>
</p>
<pre class="plain" name="code">source /etc/profile</pre>
确认是否设置好JAVA_HOME,输出环境变量
<p>
</p>
<p>
</p>
<pre class="html" name="code">echo $PATH</pre>
<br/>
我的结果如下所示
<p>
</p>
<p>
</p>
<pre class="plain" name="code">/usr/lib/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.7.0_45/bin:/usr/java/jdk1.7.0_45/jre/bin:/root/bin
</pre>
<br/>
<p>
</p>
<h2>
Centos Gradle
</h2>
<p>
</p>
<p>
<br/>
Gradle是一个类似Maven和Ant的构建系统,使用Groovy编写构建脚本,能很方便的进行依赖管理和多项目的构建。Gradle集Ant的灵活与强大以及Maven的依赖管理功能和惯例于一身,是一种更高效的构建工具。<br/>
<br/>
与Maven和Ant等基于XML的构建工具相比,Gradle由于使用基于Groovy语言的DSL语法编写构建脚本,使得脚本清晰易懂,同时也变得更加便于维护(如果熟悉Groovy语言的话)。<br/>
</p>
<p>
下载Gradle
</p>
<p>
地址 :<a href="http://www.gradle.org/downloads" target="_blank">http://www.gradle.org/downloads</a>
</p>
<p>
安装这个,我用了比较简单的方法跳了过去。
</p>
<p>
</p>
<pre class="html" name="code">unzip gradle*.zip</pre>
链接
<p>
</p>
<p>
</p>
<pre class="plain" name="code">ln -s PATH/gradle/bin/gradle /bin/gradle</pre>
<br/>
然后
<p>
</p>
<p>
gradle试试
</p>
<p>
<br/>
</p>
<h2>
运行
</h2>
<p>
因为nginx遇到了点小问题,似乎没有代理成功。于是就用修改iptables的方法来测试
</p>
<p>
路径
</p>
<p>
</p>
<pre class="plain" name="code">/etc/sysconfig/iptables</pre>
vim 一下
<p>
</p>
<p>
添加
</p>
<p>
</p>
<pre class="plain" name="code">-A INPUT -p tcp -m tcp --dport 8976 -j ACCEPT
</pre>
<p>
</p>
<p>
接着修改build.gradle上的httpPort为8976
</p>
<p>
</p>
<pre class="plain" name="code">sed -i 's/8080/8976/' build.gradle|grep httpPort</pre>
<p>
不要忘了
</p>
<p>
</p>
<pre class="html" name="code">service iptables restart</pre>
<br/>
<p>
</p>
<p>
最后用的方法比较丑陋,但是可以实现
</p>
<p>
</p>
<pre class="plain" name="code">git fetch origin
git reset --hard origin/master
sed -i 's/8080/8976/' build.gradle|grep httpPort
</pre>
<br/>
<p>
</p>