【问题标题】:ant gwt compiler task failsant gwt 编译器任务失败
【发布时间】:2012-04-04 15:35:09
【问题描述】:

我正在关注tutorial 创建我的 ant 构建文件,java 编译,而不是 GWT 编译而不是执行正确的操作来构建我的 .war 文件。

我使用 Eclipse 和 GWT-compile 工作,当我运行开发模式时它工作。我也成功部署在tomcat上。

事情是当我运行我的脚本时,编译工作但它在 gwt-compiler 任务上失败。我的蚂蚁构建脚本如下:

<project name="vlp" default="gwt.compile" basedir=".">
    <tstamp />
    <!-- ################# PROPERTIES ################ -->
    <!-- directory properties -->
    <!-- source -->
    <property name="projectName" value="VirtualLabPortal" />
    <property name="src.dir" location="src" />
    <property name="build.dir" location="bin" />
    <property name="src.build.dir" location="${build.dir}/src" />
    <property name="gwt.build.dir" location="${build.dir}/gwt" />
    <property name="gwt.unitCache.dir" location="gwt-unitCache" />
    <!-- libraries -->
    <property name="src.lib.dir" location="war/WEB-INF/lib" />

    <!-- ___________________________________________________________________
        |                                                                   |
        |               Configure path source/test                          |
        |___________________________________________________________________| 
    -->
    <path id="compile.path">
        <fileset dir="${src.lib.dir}" includes="*.jar" />
        <fileset dir="${src.lib.dir}/gwt" includes="*.jar" />
    </path>
    <!-- ___________________________________________________________________
        |                                                                   |
        |               Clean old compiled source/test/war                  |
        |___________________________________________________________________| 
    -->
    <target name="clean" description="Clean all the old build files.">
        <delete dir="${build.dir}" />
        <delete dir="${gwt.unitCache.dir}" />
        <delete file="${projectWar}" />
        <delete file="${src.lib.dir}/${projectJar}" />
    </target>
    <!-- ___________________________________________________________________
        |                                                                   |
        |                       Compile the source                          |
        |(should exclude gwtview code which is compiled by the gwt compiler)|   
        |___________________________________________________________________| 
    -->
    <target name="src.compile" depends="clean" description="Compile the source code when everything has been cleaned.">
        <mkdir dir="${src.build.dir}" />
        <javac encoding="utf-8" destdir="${src.build.dir}" nowarn="true">
            <src path="${src.dir}" />
            <classpath refid="compile.path" />
        </javac>
    </target>
    <!-- ___________________________________________________________________
        |                                                                   |
        |                       Invoke the GWT compiler                     |
        |___________________________________________________________________| 
    -->
    <property name="module.gwt.xml" location="${src.dir}/com/banctecmtl/ca/vlp" />
    <target name="gwt.compile" depends="src.compile">
        <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
            <classpath>
                <!-- src dir is added to ensure the module.xml file(s) are on the classpath -->
                <pathelement location="${module.gwt.xml}" />
                <path refid="compile.path" />
            </classpath>
            <jvmarg value="-Xmx512m" />
            <arg line="${projectName} -logLevel ALL -style OBF -war ${build.dir}" />
        </java>
    </target>
    <!-- ___________________________________________________________________
        |                                                                   |
        |           Copy the config files in the war directory              |
        |___________________________________________________________________| 
    -->
    <property name="config.dir" location="war/config" />
    <target name="copy-resources">
        <copy todir="war/config" preservelastmodified="true">
            <fileset dir="${config.dir}">
                <include name="**.*" />
            </fileset>
        </copy>
    </target>
    <!-- ___________________________________________________________________
        |                                                                   |
        |           Create a Jar to be included in the war                  |
        |___________________________________________________________________| 
    -->
    <property name="projectJar" value="${projectName}.jar" />
    <property name="gwt.client.dir" location="com/banctecmtl/ca/vlp/view/webview" />
    <target name="jar" depends="src.compile">
        <!-- should also depend on gwt.compile -->
        <jar jarfile="${src.lib.dir}/${projectJar}" basedir="${src.build.dir}/">
            <!-- Don't wrap any of the client only code into the JAR
                <exclude name="${gwt.client.dir}/**/*.class"/> -->
            <exclude name="${gwt.client.dir}/**/*.class" />
        </jar>
    </target>
    <!-- ___________________________________________________________________
        |                                                                   |
        |                   Create a War from the source                    |
        |___________________________________________________________________| 
    -->
    <property name="projectWar" value="${projectName}.war" />
    <target name="war" depends="jar,copy-resources">
        <war basedir="war" destfile="${projectWar}" webxml="war/WEB-INF/web.xml">
            <exclude name="WEB-INF/**" />
            <webinf dir="war/WEB-INF/">
                <include name="lib/*.jar" />
                <include name="classes/*.properties" />
                <exclude name="**/gwt-dev.jar" />
                <exclude name="**/gwt-user.jar" />
            </webinf>
        </war>
    </target>

    <!-- ___________________________________________________________________
        |                                                                   |
        |                   Deploy to the production server                 |
        |___________________________________________________________________| 
    -->
    <!-- It is possible you can't run this from eclipse,
     you need to edit the run configurations and add the 
     latest jsch library to the classpath -->
    <property name="user" value="root" />
    <property name="password" value="Banctec01" />
    <property name="prodHost" value="vlp" />
    <property name="dest" value="/usr/share/tomcat6/webapps/ROOT.war" />
    <target name="deploy" depends="war">
        <echo message="Copying to : ${user}@${prodHost}:${dest}" />
        <scp file="${projectWar}" remoteTofile="${user}@${prodHost}:${dest}" password="${password}" trust="true" />
    </target>
</project>

它失败并出现以下错误:

Buildfile: D:\workspace\vlp\build.xml
clean:
   [delete] Deleting directory D:\workspace\vlp\war\WEB-INF\classes
src.compile:
    [mkdir] Created dir: D:\workspace\vlp\war\WEB-INF\classes
    [javac] D:\workspace\vlp\build.xml:42: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 134 source files to D:\workspace\vlp\war\WEB-INF\classes
    [javac] Note: D:\workspace\vlp\src\com\banctecmtl\ca\vlp\controller\schedule\ScheduledTaskManager.java uses unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
gwt.compile:
     [java] Checking for updates
     [java]    First launch was 134c3e23387
     [java]    Last ping was Mon Apr 23 14:42:48 EDT 2012, min wait is 86400000ms
     [java] Module location: file:/D:/workspace/vlp/src/com/banctecmtl/ca/vlp/VirtualLabPortal.gwt.xml
     [java] Loading inherited module 'com.google.gwt.user.User'
     [java]    Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/user/User.gwt.xml
     [java]    Loading inherited module 'com.google.gwt.animation.Animation'
     [java]       Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/animation/Animation.gwt.xml
     [java]       Loading inherited module 'com.google.gwt.core.Core'
     [java]          Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/core/Core.gwt.xml
     [java]          Loading inherited module 'com.google.gwt.dev.jjs.intrinsic.Intrinsic'
     [java]             Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-dev.jar!/com/google/gwt/dev/jjs/intrinsic/Intrinsic.gwt.xml
     [java]             Loading inherited module 'com.google.gwt.lang.LongLib'
     [java]                Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-dev.jar!/com/google/gwt/lang/LongLib.gwt.xml
     [java]          Loading inherited module 'com.google.gwt.emul.Emulation'
     [java]             Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/emul/Emulation.gwt.xml
     [java]             Loading inherited module 'com.google.gwt.logging.LogImpl'
     [java]                Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/logging/LogImpl.gwt.xml
     [java]          Loading inherited module 'com.google.gwt.xhr.XMLHttpRequest'
     [java]             Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/xhr/XMLHttpRequest.gwt.xml
     [java]             Loading inherited module 'com.google.gwt.core.Core'
     [java]                Module 'com.google.gwt.core.Core' has already been loaded and will be skipped
     [java]          Loading inherited module 'com.google.gwt.core.CompilerParameters'
     [java]             Module location: jar:file:/D:/workspace/vlp/war/WEB-INF/lib/gwt/gwt-user.jar!/com/google/gwt/core/CompilerParameters.gwt.xml
     [java]          [...]
     [java]    Loading inherited module 'com.google.gwt.user.User'
     [java]       Module 'com.google.gwt.user.User' has already been loaded and will be skipped
     [java] Public resources found in...
     [java] Translatable source found in...
     [java] Persistent unit cache dir set to: D:\workspace\vlp\war\..\gwt-unitCache
     [java] Compiling module VirtualLabPortal
     [java] Looking for previously cached Compilation Units in D:\workspace\vlp\war\..\gwt-unitCache
     [java] Loaded 0 units from persistent store.
     [java] Starting UnitWriteThread.
     [java]    Found 0 cached units.  Used 0 / 2413 units from cache.
     [java] [ERROR] Unexpected internal compiler error
     [java] java.lang.RuntimeException: Exception processing units
     [java]     at com.google.gwt.dev.javac.CompilationStateBuilder$CompileMoreLater.compile(CompilationStateBuilder.java:248)
     [java]     at com.google.gwt.dev.javac.CompilationStateBuilder.doBuildFrom(CompilationStateBuilder.java:447)
     [java]     at com.google.gwt.dev.javac.CompilationStateBuilder.buildFrom(CompilationStateBuilder.java:370)
     [java]     at com.google.gwt.dev.cfg.ModuleDef.getCompilationState(ModuleDef.java:360)
     [java]     at com.google.gwt.dev.Precompile.precompile(Precompile.java:252)
     [java]     at com.google.gwt.dev.Precompile.precompile(Precompile.java:233)
     [java]     at com.google.gwt.dev.Precompile.precompile(Precompile.java:145)
     [java]     at com.google.gwt.dev.Compiler.run(Compiler.java:232)
     [java]     at com.google.gwt.dev.Compiler.run(Compiler.java:198)
     [java]     at com.google.gwt.dev.Compiler$1.run(Compiler.java:170)
     [java]     at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:88)
     [java]     at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:82)
     [java]     at com.google.gwt.dev.Compiler.main(Compiler.java:177)
     [java] Caused by: java.lang.NoSuchMethodError: com.google.gwt.dev.jjs.ast.JProgram.serializeTypes(Ljava/util/List;Ljava/io/ObjectOutputStream;)V
     [java]     at com.google.gwt.dev.javac.CompilationUnitImpl.<init>(CompilationUnitImpl.java:68)
     [java]     at com.google.gwt.dev.javac.SourceFileCompilationUnit.<init>(SourceFileCompilationUnit.java:48)
     [java]     at com.google.gwt.dev.javac.CompilationUnitBuilder$ResourceCompilationUnitBuilder.makeUnit(CompilationUnitBuilder.java:154)
     [java]     at com.google.gwt.dev.javac.CompilationUnitBuilder.build(CompilationUnitBuilder.java:266)
     [java]     at com.google.gwt.dev.javac.CompilationStateBuilder$CompileMoreLater$1.run(CompilationStateBuilder.java:223)

BUILD FAILED
D:\workspace\vlp\build.xml:60: Java returned: 1

Total time: 36 seconds

我发现把gwt-compiler类名改成DevMode就是构建成功了。使用:classname="com.google.gwt.dev.DevMode" 而不是 classname="com.google.gwt.dev.Compiler"

编辑:我重构了上面的 XML。 build.xml 清除所有 bin 目录。我还将javac 指向bin/src 目录,Google Web Toolkit 编译器输出指向:bin/gwt。编译器还是不行……

编辑:我立即从谷歌开发者网站下载了最新的 SDK,并覆盖了在我的类路径和我的 Eclipse 插件中找到的旧库。仍然无法使用 ant 构建脚本。

有人知道这里可能是什么问题吗?

【问题讨论】:

  • 我唯一能想到的是你使用了一些奇怪的 GWT SDK 版本,或者你的类路径中有多个版本的 GWT SDK。因此,请检查您使用的是 GWT 2.4,并且 gwt-compile 任务的类路径不包含某些 GWT sdk 版本
  • 我的库中的 gwt-dev 和 gwt-user jar 来自我的 Eclipse 插件,即使我的 Eclipse 可以使用 GWT 编译,我也会尝试下载新的。

标签: gwt compiler-construction ant


【解决方案1】:

我只能说com.google.gwt.dev.jjs.ast.JProgram.serializeTypes(Ljava/util/List;Ljava/io/ObjectOutputStream;)V方法只在gwt-dev 2.4.0中引入。 gwt-dev 2.3.0 中不存在。

这意味着在某个地方,在类路径中,有两个 gwt-dev 版本。其中之一是 2.4.0,这就是 com.google.gwt.dev.javac.CompilationUnitImpl 正在寻找该方法的原因。另一个是 2.3.0 或更早版本,这就是找不到该方法的原因(JProgram 类是由编译器使用旧版本加载的)。

尝试彻底查找它们。或者尝试开始一个新的环境,在其中你密切关注正在发生的事情。

【讨论】:

    【解决方案2】:

    tl;dr:这是由于 CompilerDevMode 在类上下文不足或不正确的情况下提供的链接器存在差异

    跟踪问题

    我注意到您拥有的复制品存在于当前GWT trunk 中。具体来说,它在这段代码中失败了:

    ArrayList<CompilationUnit> resultUnits = new ArrayList<CompilationUnit>();
          do {
            // Compile anything that needs to be compiled.
            buildQueue = new LinkedBlockingQueue<CompilationUnitBuilder>();
            final ArrayList<CompilationUnit> newlyBuiltUnits = new ArrayList<CompilationUnit>();
            final CompilationUnitBuilder sentinel = CompilationUnitBuilder.create((GeneratedUnit) null);
            final Throwable[] workerException = new Throwable[1];
            Thread buildThread = new Thread() {
              @Override
              public void run() {
                try {
                  do {
                    CompilationUnitBuilder builder = buildQueue.take();
                    if (builder == sentinel) {
                      return;
                    }
                    // Expensive, must serialize GWT AST types to bytes.
                    CompilationUnit unit = builder.build(); // <-- Right here.
                    newlyBuiltUnits.add(unit);
                  } while (true);
                } catch (Throwable e) {
                  workerException[0] = e;
                }
              }
            };
    

    展开堆栈比您的跟踪更远,我们在工厂和十层代码中反弹,直到我们最终找到UnifyAst.java。而且,你瞧:

    ...
    mapApi(enclosingType);
    
    // Now the method should be there.
    method = methodMap.get(sig);
    if (method == null) {
      // TODO: error logging
      throw new NoSuchMethodError(sig);
    }
    assert !method.isExternal();
    return method;
    ...
    

    这是 GWT 的预编译阶段调用的唯一 NoSuchMethodError 实例。

    Compiler 和 DevMode 链接的区别

    酷。现在我们已经深入了解了为什么会爆炸,让我们弄清楚为什么DevMode 有效而Compiler 无效。我们注意到两者都导入了相同的 Util.java 副本,因此技术上,这两种类型都可以静态地用于我们的 Java 编译器(但不是 GWT 编译器)。

    检查链接器,我们注意到Compiler 直接使用Link.link

    Link.link(logger.branch(TreeLogger.TRACE, logMessage), module,
              generatedArtifacts, allPerms, resultFiles, options.getWarDir(),
              options.getDeployDir(), options.getExtraDir(), precompileOptions); 
    

    DevMode 使用更简洁的静态调用,并在 StandardLinkerContext 的实例中填充单独的传递:

    link(loadLogger, module);
    
    ...
    
    @Override
    protected synchronized void produceOutput(TreeLogger logger, StandardLinkerContext linkerStack,
          ArtifactSet artifacts, ModuleDef module, boolean isRelink) throws UnableToCompleteException {
    
        ...
        linkerStack.produceOutput(linkLogger, artifacts, Visibility.Public, outFileSet);
        linkerStack.produceOutput(linkLogger, artifacts, Visibility.Deploy, deployFileSet);
        linkerStack.produceOutput(linkLogger, artifacts, Visibility.Private, extraFileSet);
        ...
    }
    

    太棒了!那么,我该如何解决呢?

    正如在写这篇文章的中间所接受的那样,yair provides one such diagnosis for the issue, 指出,在两个 GWT 版本的上下文中,预编译步骤对于冲突的类身份是非鲁棒的。 precompilation.getGeneratedArtifacts(); 引入错误或不足的对象的其他类可见性问题也可能导致此重现。

    假设 yair 已获得接受的答案状态,我将假设问题现已解决。但是对于其他浏览这篇文章的人来说,其他类路径或可见性问题可能会导致这个确切的问题再次出现。

    【讨论】:

    • 当我添加这个问题时,我是一名商业学生,不幸的是我不在公司内部,所以我不知道它是否适用于我的特殊情况,但非常感谢解释。
    【解决方案3】:

    GWT 编译器不支持 java.io.ObjectOutputStream 类。
    在使用 Java 类之前,您必须参考 https://developers.google.com/web-toolkit/doc/latest/RefJreEmulation#Package_java_io 以确保 GWT 支持它。

    【讨论】:

    • 好吧,我没有注意到堆栈跟踪的这一部分:P,我会尝试找到它不起作用的地方,但我想知道为什么它在 DevMode 中构建
    • 问题是我从不使用这个对象,序列化部分是编译器业务。
    • 好吧,那么我想当 ant 调用 gwtc 时你的类路径中有一些奇怪的东西
    • 不,这不是问题。再次检查卡住的错误。错误在 GWT 编译器本身的深处,很可能与 GWT 应用程序的源代码无关
    【解决方案4】:

    你 fork 一个 JVM 来运行 Gwt 编译器,bin 目录在 ClassPath 中。

    由于 Eclipse 在开发模式下编译,bin 中的剩余类可能会阻止编译器正确处理某些源文件。

    在调用 Ant 目标之前,应确保 bin 目录为空。那么它可能会过去。

    我建议您使用两个目标目录:一个用于从 Java 源编译的类,另一个用于 GWT 生成的文件。然后目标war 会将两者都收集到WAR 中。

    【讨论】:

      猜你喜欢
      • 2013-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 2014-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多