Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ant 创建跨平台Java SWT应用程序_Ant_Cross Platform_Jar_Swt_Package - Fatal编程技术网

Ant 创建跨平台Java SWT应用程序

Ant 创建跨平台Java SWT应用程序,ant,cross-platform,jar,swt,package,Ant,Cross Platform,Jar,Swt,Package,我已经使用SWT编写了一个JavaGUI。我使用ANT脚本(下面的片段)打包应用程序 这将生成一个jar,在Windows上我可以双击它来运行GUI。缺点是我不得不显式地将windows SWT包打包到我的jar中 我希望能够在其他平台(主要是Linux和OS X)上运行我的应用程序。最简单的方法是创建特定于平台的jar,将适当的SWT文件打包到单独的jar中 有更好的方法吗?有可能创建一个可以在多个平台上运行的JAR吗?用linux指定的swt JAR文件替换src=“lib/org.ec

我已经使用SWT编写了一个JavaGUI。我使用ANT脚本(下面的片段)打包应用程序


这将生成一个jar,在Windows上我可以双击它来运行GUI。缺点是我不得不显式地将windows SWT包打包到我的jar中

我希望能够在其他平台(主要是Linux和OS X)上运行我的应用程序。最简单的方法是创建特定于平台的jar,将适当的SWT文件打包到单独的jar中


有更好的方法吗?有可能创建一个可以在多个平台上运行的JAR吗?

用linux指定的swt JAR文件替换src=“lib/org.eclipse.swt.win32.win32.x86_3.5.2.v3557f.JAR“我刚刚遇到了同样的问题。我还没有尝试过,但我计划为所有平台包括
swt.jar
的版本,并在
main
方法的开头动态加载正确的版本

更新:成功了
build.xml
包括所有JAR:

<zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_linux_gtk_x86.jar"/>
<zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_macosx_x86.jar"/>
<zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_win32_x86.jar"/>
<zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_linux_gtk_x64.jar"/>
<zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_macosx_x64.jar"/>
<zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_win32_x64.jar"/>

[编辑]对于那些寻找“jar-in-jar类加载器”的人来说:它包含在Eclipse的JDT(基于Eclipse构建的JavaIDE)中。用归档器打开org.eclipse.jdt.ui_*version_number*.jar,您将在jar loader.zip中找到一个文件
jar。

我有一个工作实现,现在从

此方法现在可用作ANT任务:

[编辑]SWTJar现已更新为使用上述Alexey Romanov的解决方案

首先,我构建一个包含所有应用程序类的jar

<!-- UI (Stage 1) -->   
<jarjar jarfile="./build/tmp/intrace-ui-wrapper.jar">
  <fileset dir="./build/classes" includes="**/shared/*.class" />
  <fileset dir="./build/classes" includes="**/client/gui/**/*.class" />
  <zipfileset excludes="META-INF/*.MF" src="lib/miglayout-3.7.3.1-swt.jar"/>
</jarjar>

接下来,我构建了一个jar来包含以下所有内容:

  • 罐子
    • 我刚造的罐子
    • 所有的SWT罐子
  • 班级
    • “Jar-In-Jar”类加载器类
    • 一个特殊的加载器类-见下文
下面是build.xml中的片段

<!-- UI (Stage 2) -->
<jarjar jarfile="./build/jars/intrace-ui.jar">
  <manifest>
    <attribute name="Main-Class" value="org.intrace.client.loader.TraceClientLoader" />
    <attribute name="Class-Path" value="." />
  </manifest>
  <fileset dir="./build/classes" includes="**/client/loader/*.class" />
  <fileset dir="./build/tmp" includes="intrace-ui-wrapper.jar" />
  <fileset dir="./lib" includes="swt-*.jar" />
  <zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/>
</jarjar>

这个加载器类使用jar-in-jar加载器创建一个类加载器,从两个jar中加载类

  • 正确的SWT罐
  • 应用程序包装器jar
一旦我们有了这个类加载器,我们就可以使用反射启动实际的应用程序main方法

public class TraceClientLoader
{
  public static void main(String[] args) throws Throwable
  {    
    ClassLoader cl = getSWTClassloader();
    Thread.currentThread().setContextClassLoader(cl);    
    try
    {
      try
      {
        System.err.println("Launching InTrace UI ...");
        Class<?> c = Class.forName("org.intrace.client.gui.TraceClient", true, cl);
        Method main = c.getMethod("main", new Class[]{args.getClass()});
        main.invoke((Object)null, new Object[]{args});
      }
      catch (InvocationTargetException ex)
      {
        if (ex.getCause() instanceof UnsatisfiedLinkError)
        {
          System.err.println("Launch failed: (UnsatisfiedLinkError)");
          String arch = getArch();
          if ("32".equals(arch))
          {
            System.err.println("Try adding '-d64' to your command line arguments");
          }
          else if ("64".equals(arch))
          {
            System.err.println("Try adding '-d32' to your command line arguments");
          }
        }
        else
        {
          throw ex;
        }
      }
    }
    catch (ClassNotFoundException ex)
    {
      System.err.println("Launch failed: Failed to find main class - org.intrace.client.gui.TraceClient");
    }
    catch (NoSuchMethodException ex)
    {
      System.err.println("Launch failed: Failed to find main method");
    }
    catch (InvocationTargetException ex)
    {
      Throwable th = ex.getCause();
      if ((th.getMessage() != null) &&
          th.getMessage().toLowerCase().contains("invalid thread access"))
      {
        System.err.println("Launch failed: (SWTException: Invalid thread access)");
        System.err.println("Try adding '-XstartOnFirstThread' to your command line arguments");
      }
      else
      {
        throw th;
      }
    }
  }

  private static ClassLoader getSWTClassloader()
  {
    ClassLoader parent = TraceClientLoader.class.getClassLoader();    
    URL.setURLStreamHandlerFactory(new RsrcURLStreamHandlerFactory(parent));
    String swtFileName = getSwtJarName();      
    try
    {
      URL intraceFileUrl = new URL("rsrc:intrace-ui-wrapper.jar");
      URL swtFileUrl = new URL("rsrc:" + swtFileName);
      System.err.println("Using SWT Jar: " + swtFileName);
      ClassLoader cl = new URLClassLoader(new URL[] {intraceFileUrl, swtFileUrl}, parent);

      try
      {
        // Check we can now load the SWT class
        Class.forName("org.eclipse.swt.widgets.Layout", true, cl);
      }
      catch (ClassNotFoundException exx)
      {
        System.err.println("Launch failed: Failed to load SWT class from jar: " + swtFileName);
        throw new RuntimeException(exx);
      }

      return cl;
    }
    catch (MalformedURLException exx)
    {
      throw new RuntimeException(exx);
    }                   
  }

  private static String getSwtJarName()
  {
    // Detect OS
    String osName = System.getProperty("os.name").toLowerCase();    
    String swtFileNameOsPart = osName.contains("win") ? "win" : osName
        .contains("mac") ? "osx" : osName.contains("linux")
        || osName.contains("nix") ? "linux" : "";
    if ("".equals(swtFileNameOsPart))
    {
      throw new RuntimeException("Launch failed: Unknown OS name: " + osName);
    }

    // Detect 32bit vs 64 bit
    String swtFileNameArchPart = getArch();

    String swtFileName = "swt-" + swtFileNameOsPart + swtFileNameArchPart
        + "-3.6.2.jar";
    return swtFileName;
  }

  private static String getArch()
  {
    // Detect 32bit vs 64 bit
    String jvmArch = System.getProperty("os.arch").toLowerCase();
    String arch = (jvmArch.contains("64") ? "64" : "32");
    return arch;
  }
}
公共类TraceClientLoader
{
公共静态void main(字符串[]args)抛出可丢弃的
{    
ClassLoader cl=getSWTClassloader();
Thread.currentThread().setContextClassLoader(cl);
尝试
{
尝试
{
System.err.println(“启动内部UI…”);
Class c=Class.forName(“org.intrace.client.gui.TraceClient”,true,cl);
方法main=c.getMethod(“main”,新类[]{args.getClass()});
invoke((Object)null,新对象[]{args});
}
捕获(调用TargetException ex)
{
if(例如getCause()instanceof unsatifiedLinkError)
{
System.err.println(“启动失败:(未满足链接错误)”;
字符串arch=getArch();
如果(“32”。等于(拱))
{
System.err.println(“尝试将“-d64”添加到命令行参数中”);
}
否则,如果(“64”。等于(拱))
{
System.err.println(“尝试将“-d32”添加到命令行参数中”);
}
}
其他的
{
掷骰子;
}
}
}
捕获(ClassNotFoundException ex)
{
System.err.println(“启动失败:找不到主类-org.intrace.client.gui.TraceClient”);
}
catch(NoSuchMethodException-ex)
{
System.err.println(“启动失败:找不到主方法”);
}
捕获(调用TargetException ex)
{
Throwable th=ex.getCause();
如果((th.getMessage()!=null)&&
th.getMessage().toLowerCase()包含(“无效线程访问”))
{
System.err.println(“启动失败:(SWTException:无效线程访问)”;
System.err.println(“尝试将“-XstartOnFirstThread”添加到命令行参数中”);
}
其他的
{
掷骰子;
}
}
}
私有静态类加载器getSWTClassloader()
{
ClassLoader父级=TraceClientLoader.class.getClassLoader();
setURLStreamHandlerFactory(新的RsrcURLStreamHandlerFactory(父级));
字符串swtFileName=getSwtJarName();
尝试
{
URL intraceFileUrl=新URL(“rsrc:intraceUI wrapper.jar”);
URL swtFileUrl=新URL(“rsrc:+swtFileName”);
System.err.println(“使用SWT Jar:+swtFileName”);
ClassLoader cl=新的URLClassLoader(新的URL[]{FileURL,swtFileUrl},父级);
尝试
{
//检查我们现在可以加载SWT类了
Class.forName(“org.eclipse.swt.widgets.Layout”,true,cl);
}
捕获(ClassNotFoundException exx)
{
System.err.println(“启动失败:无法从jar加载SWT类:“+swtFileName”);
抛出新的运行时异常(exx);
}
返回cl;
}
捕获(格式错误的异常异常exx)
{
抛出新的运行时异常(exx);
}                   
}
私有静态字符串getSwtJarName()
{
//检测操作系统
字符串osName=System.getProperty(“os.name”).toLowerCase();
字符串swtFileNameOsPart=osName.contains(“win”)?“win”:osName
.contains(“mac”)?“osx”:osName.contains(“linux”)
||包含(“nix”)?“linux”:“;
如果(“.”等于(swtFileNameOsPart))
{
抛出新运行时异常(“启动失败:未知操作系统名称:“+osName”);
}
//检测32位对64位
字符串swtFileNameArchPart=getArch();
字符串swtFileName=“swt-”+swtFileNameOsPart+swtFileNameArchPart
+“-3.6.2.jar”;
返回swtFileName;
}
私有静态字符串getArch()
{
//检测32位对64位
字符串jvmArch=System.getProperty(“os.arch”).toLowerCase();
s
<!-- UI (Stage 2) -->
<jarjar jarfile="./build/jars/intrace-ui.jar">
  <manifest>
    <attribute name="Main-Class" value="org.intrace.client.loader.TraceClientLoader" />
    <attribute name="Class-Path" value="." />
  </manifest>
  <fileset dir="./build/classes" includes="**/client/loader/*.class" />
  <fileset dir="./build/tmp" includes="intrace-ui-wrapper.jar" />
  <fileset dir="./lib" includes="swt-*.jar" />
  <zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/>
</jarjar>
public class TraceClientLoader
{
  public static void main(String[] args) throws Throwable
  {    
    ClassLoader cl = getSWTClassloader();
    Thread.currentThread().setContextClassLoader(cl);    
    try
    {
      try
      {
        System.err.println("Launching InTrace UI ...");
        Class<?> c = Class.forName("org.intrace.client.gui.TraceClient", true, cl);
        Method main = c.getMethod("main", new Class[]{args.getClass()});
        main.invoke((Object)null, new Object[]{args});
      }
      catch (InvocationTargetException ex)
      {
        if (ex.getCause() instanceof UnsatisfiedLinkError)
        {
          System.err.println("Launch failed: (UnsatisfiedLinkError)");
          String arch = getArch();
          if ("32".equals(arch))
          {
            System.err.println("Try adding '-d64' to your command line arguments");
          }
          else if ("64".equals(arch))
          {
            System.err.println("Try adding '-d32' to your command line arguments");
          }
        }
        else
        {
          throw ex;
        }
      }
    }
    catch (ClassNotFoundException ex)
    {
      System.err.println("Launch failed: Failed to find main class - org.intrace.client.gui.TraceClient");
    }
    catch (NoSuchMethodException ex)
    {
      System.err.println("Launch failed: Failed to find main method");
    }
    catch (InvocationTargetException ex)
    {
      Throwable th = ex.getCause();
      if ((th.getMessage() != null) &&
          th.getMessage().toLowerCase().contains("invalid thread access"))
      {
        System.err.println("Launch failed: (SWTException: Invalid thread access)");
        System.err.println("Try adding '-XstartOnFirstThread' to your command line arguments");
      }
      else
      {
        throw th;
      }
    }
  }

  private static ClassLoader getSWTClassloader()
  {
    ClassLoader parent = TraceClientLoader.class.getClassLoader();    
    URL.setURLStreamHandlerFactory(new RsrcURLStreamHandlerFactory(parent));
    String swtFileName = getSwtJarName();      
    try
    {
      URL intraceFileUrl = new URL("rsrc:intrace-ui-wrapper.jar");
      URL swtFileUrl = new URL("rsrc:" + swtFileName);
      System.err.println("Using SWT Jar: " + swtFileName);
      ClassLoader cl = new URLClassLoader(new URL[] {intraceFileUrl, swtFileUrl}, parent);

      try
      {
        // Check we can now load the SWT class
        Class.forName("org.eclipse.swt.widgets.Layout", true, cl);
      }
      catch (ClassNotFoundException exx)
      {
        System.err.println("Launch failed: Failed to load SWT class from jar: " + swtFileName);
        throw new RuntimeException(exx);
      }

      return cl;
    }
    catch (MalformedURLException exx)
    {
      throw new RuntimeException(exx);
    }                   
  }

  private static String getSwtJarName()
  {
    // Detect OS
    String osName = System.getProperty("os.name").toLowerCase();    
    String swtFileNameOsPart = osName.contains("win") ? "win" : osName
        .contains("mac") ? "osx" : osName.contains("linux")
        || osName.contains("nix") ? "linux" : "";
    if ("".equals(swtFileNameOsPart))
    {
      throw new RuntimeException("Launch failed: Unknown OS name: " + osName);
    }

    // Detect 32bit vs 64 bit
    String swtFileNameArchPart = getArch();

    String swtFileName = "swt-" + swtFileNameOsPart + swtFileNameArchPart
        + "-3.6.2.jar";
    return swtFileName;
  }

  private static String getArch()
  {
    // Detect 32bit vs 64 bit
    String jvmArch = System.getProperty("os.arch").toLowerCase();
    String arch = (jvmArch.contains("64") ? "64" : "32");
    return arch;
  }
}
lib/swt_win_32.jar
lib/swt_win_64.jar
lib/swt_linux_32.jar
lib/swt_linux_64.jar