compiler_compilers - CSDN
精华内容
参与话题
  • java Compiler API (java编译api)

    千次阅读 2019-05-23 09:59:50
    在早期的版本中(Java SE5及以前版本)中只能通过tools.jar中的com.sun.tools.javac包来调用Java编译器,但由于tools.jar不是标准的Java库,在使用时必须要设置这个jar的路径。而在Java SE6中为我们提供了标准的包来...

    在早期的版本中(Java SE5及以前版本)中只能通过tools.jar中的com.sun.tools.javac包来调用Java编译器,但由于tools.jar不是标准的Java库,在使用时必须要设置这个jar的路径。而在Java SE6中为我们提供了标准的包来操作Java编译器,这就是javax.tools包。

    编译java文件

    使用Java API来编译Java源代码有非常多方法,目前让我们来看一种最简单的方法,通过JavaCompiler进行编译。

    使用ToolProvider.getSystemJavaCompiler来得到一个JavaCompiler接口的实例。

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    

    JavaCompiler中最核心的方法是run()。通过这个方法能编译java源代码。

    int run(InputStream in, OutputStream out, OutputStream err, String... arguments)
    

    参数分别用来为:

    1. java编译器提供参数
    2. 得到Java编译器的输出信息
    3. 接收编译器的错误信息,
    4. 一个或多个Java源程式文件

    如果run编译成功,返回  0。

    如果前3个参数传入的是null,那么run方法将以标准的输入、输出代替,即System.inSystem.outSystem.err。如果我们要编译一个test.java文件,并将使用标准输入输出,run的使用方法如下:

    int results = tool.run(null, null, null, "F:\\demo\\Test.java");
    

    完整的例子:

    //CompileMain.java
    import javax.tools.JavaCompiler;
    import javax.tools.ToolProvider;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class CompileMain {
    
        public static void main(String[] args) throws IOException {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            int result = compiler.run(null, null, null, "F:\\demo\\Test.java");
            System.out.println(result == 0 ? "编译成功" : "编译失败");
    
    //执行java 命令 , 空参数, 所在文件夹
            Process process = Runtime.getRuntime().exec("java Test",null,new File("F:\\demo\\"));
                   
    
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String str;
            while ((str = bufferedReader.readLine()) != null) {
                System.out.println(str);
            }
        }
    }
    
    public class Test {
    
        public static void main(String[] args) {
            System.out.println("this is a test.java file ,thank you very much");
        }
    
    }
    $ javac CompileMain.java 
    
    $ java CompileMain             
    编译成功
    this is a test.java file ,thank you very much
    

    编译非文件形式源代码

    JDK 6 的编译器 API 的另外一个强大之处在于,它可以编译的源文件的形式并不局限于文本文件JavaCompiler 类依靠文件管理服务可以编译多种形式的源文件。比如直接由内存中的字符串构造的文件,或者是从数据库中取出的文件。这种服务是由 JavaFileManager 类提供的。

    在Java SE6中最佳的方法是使用StandardJavaFileManager类。这个类能非常好地控制输入、输出,并且能通过DiagnosticListener得到诊断信息,而DiagnosticCollector类就是listener的实现。新的 JDK 定义了 javax.tools.FileObject 和 javax.tools.JavaFileObject 接口。任何类,只要实现了这个接口,就可以被 JavaFileManager 识别。

    编译流程

    使用StandardJavaFileManager步骤:

    1. 建立一个DiagnosticCollector实例
    2. 通过JavaCompiler.getStandardFileManager()方法得到一个StandardFileManager对象。
    3. 使用StandardFileManager获取需要编译的源代码。从文件或者字符流中获取源代码。
    4. JavaCompiler.getTask()生成编译任务抽象。
    5. 通过CompilationTask.call()方法编译源代码。
    6. 关闭StandardFileManager

    在使用这种方法调用Java编译时最复杂的方法就是getTask,下面让我们讨论一下getTask方法。这个方法有如下所示的6个参数。

    getTask(Writer out,
            JavaFileManager fileManager,
            DiagnosticListener<? super JavaFileObject> diagnosticListener,
            Iterable<String> options,
            Iterable<String> classes,
            Iterable<? extends JavaFileObject> compilationUnits)
    

    这些参数大多数都可为null。他们的含义所下。

    • out: 用于输出错误的流,默认是System.err
    • fileManager:标准的文件管理。
    • diagnosticListener: 编译器的默认行为。
    • options: 编译器的选项
    • classes:参和编译的class。
    • compilationUnits: 待编译的Java文件,不能为null

    CompilationTask 提供了 setProcessors(Iterable<? extends Processor>processors)方法,用户可以制定处理 annotation 的处理器。

    在使用完getTask前,需要通过StandardJavaFileManager.getJavaFileObjectsFromFiles()StandardJavaFileManager.getJavaFileObjectsFromStrings方法得到待编译的compilationUnits对象。

    也可以通过继承/实现SimpleJavaObject获取带编译的对象。

    调用这两个方法的方式如下:

    Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files)
    Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names)
    
    String[] filenames = …;
    Iterable<? extends JavaFileObject> compilationUnits =
    fileManager.getJavaFileObjectsFromFiles(Arrays.asList(filenames));
    
    JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager,
    diagnostics, options, null, compilationUnits);
    

    最后需要关闭fileManager.close();

    例如:

    package win.hgfdodo.dynamic;
    
    import javax.tools.JavaCompiler;
    import javax.tools.JavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    import java.util.Arrays;
    
    public class JavaFileManagerMain {
        public static void main(String[] args) {
            String fullQuanlifiedFileName = "win.hgfdodo.dynamic.".replaceAll("\\.", java.io.File.separator) + "Calculator.java";
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager fileManager =
                    compiler.getStandardFileManager(null, null, null);
    
            Iterable<? extends JavaFileObject> files =
                    fileManager.getJavaFileObjectsFromStrings(
                            Arrays.asList(fullQuanlifiedFileName));
            JavaCompiler.CompilationTask task = compiler.getTask(
                    null, fileManager, null, null, null, files);
    
            Boolean result = task.call();
            if (result == true) {
                System.out.println("Succeeded");
            }
        }
    }
    
    
    package win.hgfdodo.dynamic;
    
    public class Calculator {
        public int multiply(int multiplicand, int multiplier) {
            return multiplicand * multiplier;
        }
    }
    

    JavaFileObject获取java源程序

    开发者希望生成 Calculator 的一个测试类,而不是手工编写。使用 compiler API,可以将内存中的一段字符串,编译成一个 CLASS 文件。

    定制 JavaFileObject 对象:

    package win.hgfdodo.dynamic;
    
    import javax.tools.SimpleJavaFileObject;
    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    
    public class StringObject extends SimpleJavaFileObject {
        private String content = null;
    
        protected StringObject(String className, String contents) throws URISyntaxException {
            super(new URI(className), Kind.SOURCE);
            this.content = contents;
        }
    
        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
            return content;
        }
    }
    

    SimpleJavaFileObject 是 JavaFileObject 的子类,它提供了默认的实现。继承 SimpleJavaObject 之后,只需要实现 getCharContent 方法。

    接下来,在内存中构造 Calculator 的测试类 CalculatorTest,并将代表该类的字符串放置到 StringObject 中,传递给 JavaCompiler.getTask 方法。

    具体如下:

    package win.hgfdodo.dynamic;
    
    import javax.tools.JavaCompiler;
    import javax.tools.JavaFileObject;
    import javax.tools.StandardJavaFileManager;
    import javax.tools.ToolProvider;
    import java.net.URISyntaxException;
    import java.util.Arrays;
    
    public class StringClassCompilerMain {
        public static void main(String[] args) {
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);
            JavaFileObject testFile = generateTest();
            Iterable<? extends JavaFileObject> classes = Arrays.asList(testFile);
            JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, null, null, null, classes);
            if(task.call()){
                System.out.println("success");
            }else{
                System.out.println("failure!");
            }
    
        }
    
        private static JavaFileObject generateTest() {
            String contents = new String(
                    "package win.hgfdodo.dynamic;" +
                            "class CalculatorTest {\n" +
                            "  public void testMultiply() {\n" +
                            "    Calculator c = new Calculator();\n" +
                            "    System.out.println(c.multiply(2, 4));\n" +
                            "  }\n" +
                            "  public static void main(String[] args) {\n" +
                            "    CalculatorTest ct = new CalculatorTest();\n" +
                            "    ct.testMultiply();\n" +
                            "  }\n" +
                            "}\n");
            StringObject so = null;
            try {
                so = new StringObject("win.hgfdodo.dynamic.CalculatorTest", contents);
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
    
            return so;
    
        }
    }
    

    采集编译器的诊断信息

    收集编译过程中的诊断信息是JDK6新增的内容。诊断信息,通常指错误、警告或是编译过程中的详尽输出。

    JDK 6 通过 Listener 机制,获取这些信息。如果要注册一个 DiagnosticListener,必须使用 CompilationTask 来进行编译,因为 Tool.run 方法没有办法注册 Listener

    步骤:

    1. 构造一个 Listener
    2. 传递给 JavaFileManager 的构造函数;
    3. 编译完成后,获取Diagnostic列表;
    4. 输出诊断信息。

    例子:

    package win.hgfdodo.dynamic;
    
    import javax.tools.*;
    import java.net.URISyntaxException;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Locale;
    
    public class StringClassCompilerMain {
        public static void main(String[] args) {
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>();
            StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);
            JavaFileObject testFile = generateTest();
            Iterable<? extends JavaFileObject> classes = Arrays.asList(testFile);
            JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, collector, null, null, classes);
            if(task.call()){
                System.out.println("success");
            }else{
                System.out.println("failure!");
            }
    
            List<Diagnostic<? extends JavaFileObject>> diagnostics = collector.getDiagnostics();
            for (Diagnostic<? extends JavaFileObject> diagnostic: diagnostics){
                System.out.println("line:"+ diagnostic.getLineNumber());
                System.out.println("msg:"+ diagnostic.getMessage(Locale.ENGLISH));
                System.out.println("source:"+ diagnostic.getSource());
    
            }
        }
    
        private static JavaFileObject generateTest() {
            String contents = new String(
                    "package win.hgfdodo.dynamic;" +
                            "class CalculatorTest {\n" +
                            "  public void testMultiply() {\n" +
                            "    Calculator c = new Calculator()\n" +
                            "    System.out.println(c.multiply(2, 4));\n" +
                            "  }\n" +
                            "  public static void main(String[] args) {\n" +
                            "    CalculatorTest ct = new CalculatorTest();\n" +
                            "    ct.testMultiply();\n" +
                            "  }\n" +
                            "}\n");
            StringObject so = null;
            try {
                so = new StringObject("win.hgfdodo.dynamic.CalculatorTest", contents);
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
    
            return so;
    
        }
    }
    

    generateTest方法在构造Calculator时,将行尾;去掉,造成java 源文件错误,在编译时,会输出:

    line:3
    msg:需要';'
    source:win.hgfdodo.dynamic.StringObject[win.hgfdodo.dynamic.CalculatorTest]
    

    运行时编译和运行java类

    运行时编译运行图解

    CharSequenceJavaFileObject -- 存储源代码

    package win.hgfdodo.compiler;
    
    import javax.tools.SimpleJavaFileObject;
    import java.io.IOException;
    import java.net.URI;
    
    /**
     * 字符串java源代码。JavaFileObject表示
     */
    public class CharSequenceJavaFileObject extends SimpleJavaFileObject {
    
        //表示java源代码
        private CharSequence content;
    
        protected CharSequenceJavaFileObject(String className, String content) {
            super(URI.create("string:///" + className.replaceAll("\\.", "/") + Kind.SOURCE.extension), Kind.SOURCE);
            this.content = content;
        }
    
        /**
         * 获取需要编译的源代码
         * @param ignoreEncodingErrors
         * @return
         * @throws IOException
         */
        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
            return content;
        }
    }
    

    JavaClassObject 保存编译结果

    package win.hgfdodo.compiler;
    
    import javax.tools.SimpleJavaFileObject;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.URI;
    
    /**
     * 存储编译后的字节码
     */
    public class JavaClassObject extends SimpleJavaFileObject {
    
        /**
         * Compiler编译后的byte数据会存在这个ByteArrayOutputStream对象中,
         * 后面可以取出,加载到JVM中。
         */
        private ByteArrayOutputStream byteArrayOutputStream;
    
        public JavaClassObject(String className, Kind kind) {
            super(URI.create("string:///" + className.replaceAll("\\.", "/") + kind.extension), kind);
            this.byteArrayOutputStream = new ByteArrayOutputStream();
        }
    
        /**
         * 覆盖父类SimpleJavaFileObject的方法。
         * 该方法提供给编译器结果输出的OutputStream。
         * 
         * 编译器完成编译后,会将编译结果输出到该 OutputStream 中,我们随后需要使用它获取编译结果
         *
         * @return
         * @throws IOException
         */
        @Override
        public OutputStream openOutputStream() throws IOException {
            return this.byteArrayOutputStream;
        }
    
        /**
         * FileManager会使用该方法获取编译后的byte,然后将类加载到JVM
         */
        public byte[] getBytes() {
            return this.byteArrayOutputStream.toByteArray();
        }
    }
    

    JavaFileManager 处理编译结果

    JavaFileManager提供了编译结果存储编译类的加载

    package win.hgfdodo.compiler;
    
    import javax.tools.FileObject;
    import javax.tools.ForwardingJavaFileManager;
    import javax.tools.JavaFileManager;
    import javax.tools.JavaFileObject;
    import java.io.IOException;
    import java.security.SecureClassLoader;
    
    /**
     * 输出字节码到JavaClassFile
     */
    public class ClassFileManager extends ForwardingJavaFileManager {
    
        /**
         * 存储编译后的代码数据
         */
        private JavaClassObject classJavaFileObject;
    
        protected ClassFileManager(JavaFileManager fileManager) {
            super(fileManager);
        }
    
        /**
         * 编译后加载类
         * <p>
         * 返回一个匿名的SecureClassLoader:
         * 加载由JavaCompiler编译后,保存在ClassJavaFileObject中的byte数组。
         */
        @Override
        public ClassLoader getClassLoader(Location location) {
            return new SecureClassLoader() {
                @Override
                protected Class<?> findClass(String name) throws ClassNotFoundException {
                    byte[] bytes = classJavaFileObject.getBytes();
                    return super.defineClass(name, bytes, 0, bytes.length);
                }
            };
        }
    
        /**
         * 给编译器提供JavaClassObject,编译器会将编译结果写进去
         */
        @Override
        public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
            this.classJavaFileObject = new JavaClassObject(className, kind);
            return this.classJavaFileObject;
        }
    
    }
    

    DynamicCompiler -- 自定义编译器

    DynamicCompiler实现将源代码编译并加载的功能。

    package win.hgfdodo.compiler;
    
    import javax.tools.*;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 运行时编译
     */
    public class DynamicCompiler {
        private JavaFileManager fileManager;
    
        public DynamicCompiler() {
            this.fileManager = initManger();
        }
    
        private JavaFileManager initManger() {
            if (fileManager != null) {
                return fileManager;
            } else {
                JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
                DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
                fileManager = new ClassFileManager(javaCompiler.getStandardFileManager(diagnosticCollector, null, null));
                return fileManager;
            }
        }
    
        /**
         * 编译源码并加载,获取Class对象
         * @param fullName
         * @param sourceCode
         * @return
         * @throws ClassNotFoundException
         */
        public Class compileAndLoad(String fullName, String sourceCode) throws ClassNotFoundException {
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            List<JavaFileObject> javaFileObjectList = new ArrayList<JavaFileObject>();
            javaFileObjectList.add(new CharSequenceJavaFileObject(fullName, sourceCode));
            boolean result = javaCompiler.getTask(null, fileManager, null, null, null, javaFileObjectList).call();
            if (result) {
                return this.fileManager.getClassLoader(null).loadClass(fullName);
            } else {
                return Class.forName(fullName);
            }
        }
    
        /**
         * 关闭fileManager
         * @throws IOException
         */
        public void closeFileManager() throws IOException {
            this.fileManager.close();
        }
    
    }
    

    测试

    package win.hgfdodo.compiler;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    
    public class DynamicCompilerTest {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
            StringBuilder src = new StringBuilder();
            src.append("package win.hgfdodo.compiler;");
            src.append("public class DynaClass {\n");
            src.append("    public String toString() {\n");
            src.append("        return \"Hello, I am \" + ");
            src.append("this.getClass().getSimpleName();\n");
            src.append("    }\n");
            src.append("}\n");
    
            String fullName = "win.hgfdodo.compiler.DynaClass";
    
            DynamicCompiler compiler = new DynamicCompiler();
            Class clz = compiler.compileAndLoad(fullName, src.toString());
    
            System.out.println(clz.getConstructor().newInstance());
            compiler.close();
        }
    }
    

    编译加载win.hgfdodo.compiler.DynaClass后,创建新的对象,并调用toString()输出:

    Hello, I am DynaClass
    

    参考

    1. javafile compiler, classloader and run

     

    本文根据博客https://my.oschina.net/hgfdoing/blog/3052263

    修改而来,注意, 编译.java源码, 和执行.class 都需要制定文件夹,这里我使用了绝对路径

    2019年5月23日09:59:23

    展开全文
  • java compiler 设置

    2012-08-07 15:19:34
    如下图所示,我们在给工程设置 java compiler的时候,都是通过界面设置。   在工程目录下.setting文件夹下生成了,org.eclipse.jdt.core.prefs的文件。选中Enable project specific settings   #Sat Jun 12...

        如下图所示,我们在给工程设置  java  compiler的时候,都是通过界面设置。 




     在工程目录下.setting文件夹下生成了,org.eclipse.jdt.core.prefs的文件。选中Enable project specific settings

     

    #Sat Jun 12 11:01:27 CST 2010
    eclipse.preferences.version=1
    org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
    org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
    org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
    org.eclipse.jdt.core.compiler.compliance=1.4
    org.eclipse.jdt.core.compiler.debug.lineNumber=generate
    org.eclipse.jdt.core.compiler.debug.localVariable=generate
    org.eclipse.jdt.core.compiler.debug.sourceFile=generate
    org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
    org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
    org.eclipse.jdt.core.compiler.source=1.3
     知道这个设置文件,可以在创建工程的工程模版中加入此文件,设置工程的默认编译jdk 版本
    展开全文
  • 逻辑综合工具DesignCompiler使用教程

    千次阅读 2019-07-18 12:04:37
    逻辑综合工具Design Compiler使用教程 图形界面design vision操作示例 逻辑综合主要是将HDL语言描述的电路转换为工艺库器件构成的网表的过程。综合工具目前比较主流的是synopsys公司Design Compiler,我们在设计实践...

    逻辑综合工具Design Compiler使用教程

    图形界面design vision操作示例

    逻辑综合主要是将HDL语言描述的电路转换为工艺库器件构成的网表的过程。综合工具目前比较主流的是synopsys公司Design Compiler,我们在设计实践过程中采用这一工具。Design compiler有两种工作模式,一种是tcl模式,另一种为图形模式。在设计中为增强直观性,采用图形界面design vision。TCL命令行模式可在设计过程中摸索熟悉,并使之成为习惯。tcl模式在启动工具之前,准备工作有四项:设计的HDL源文件、采用的工艺库文件、设计的约束文件、工具的启动文件。图形界面模式最少需要前两项,这里不作多说明。

    1. 启动工具

    登陆Linux之后进入的目录即是用户的家目录,在家目录下建立dcLab作为本次实验dc的操作主目录。在dcLab目录下,建立设计存放目录如source、约束文件目录如constrn、输出网表文件目录ntlst、报告输出目录rpt、log文件目录log、dc启动目录work,等等。
    实验室中的工作站存放有umc公司和tsmc公司的0.18um标准单元库的所有文件,存放在目录:/usr/eda/designKit/下面,设计过程中需要查找的话注意路径与示例中的图片上所示路径稍有不同。
    Design compiler工具在工作站中已经安装完毕,且用户的环境变量和license也已设置完成,登录之后直接启动工具即可。如果打开终端之后无法启动工具,可能就是license没有启动,需要首先采用命令:start_slic启动license,然后design vision才能正常开启与工作。建立相关的工程目录之后,进入本次实验的工作目录:~/dcLab/work后,采用启动命令:design_vision&,启动工具后相应的界面如下图1所示。
    在该界面中,最上方为菜单项和工具栏,用于设计过程中的各项操作。当窗口中选中不同的对象时,不同的菜单项和工具项会被激活。工具栏下面就是主窗口,用于显示不同的设计对象、各种报告等。再下方为log/history窗口,log
    页面显示操作响应,history界面回显菜单操作相应的tcl命令,操作过程中一定要对照查看,尽快熟悉tcl模式。最下方有design_vision-xg-t提示的就是tcl命令输入的位置,可以尝试将history页面的回显键入,查看响应。
    在这里插入图片描述
    图1 design vision启动界面
    启动工具之后就可以工作了,主要可分为四部分内容:对工程进行启动项设置、对设计进行面积/功耗/时序/环境/drc等约束、对设计进行综合、查看报告并保存结果。

    2. 配置工程启动文件

    工具启动之后,需要设置相应的工程启动文件,用于设定搜索路径、相关库文件等内容,对应工作目录下的.synopsys_dc.setup文件(该文件应该位于工具启动目录~/dcLab/work下,dc启动过程中会自动读取该文件的内容用来配置工程启动项。
    我们此时假设该文件不存在,当设置完成之后,可以将之保存,以后重启工具就可以不必设置了)。选择菜单项File—>Setup…,出现Application Setup窗口,如下图2所示。启动项相关的内容就在该表项中设置,用户可以直接填入相关内容,或者点击各栏右侧的查找按钮(标有…的小框)找到相应路径或
    者文件的位置。
    在这里插入图片描述
    图2 setup设置窗口
    在该窗口中可以看到打有红星()标号的项目是必须设置的,但是一般填上四项:search path、Link library、Target library*、symbol library*。首先来设置搜索路径,该项主要用来指明设计中工具所需文件的路径,应该包括源代码文件路径、工艺库文件(如果源代码有pad,则也应该包括pad库文件所在路径)、工具提供的中间库文件(gtech、designWare)路径、以及操作过程中需要读取的中间文件所在路径等。点击search path条目右侧的查找按钮,就会出现set search path 表格窗口,如下图3所示。
    在这里插入图片描述
    图3 search path设置窗口
    表格窗口已有的几项保留不动,其中第一项的点符号(.)表示当前工作目录,其余3项为工具提供的通用(gtech)库、ip单元库(design ware)以及符号(symbol)库和仿真模型库所在位置。点击Add…按钮,添加搜索路径(注意
    工作站上的软件工具、库文件均存放在/usr/eda目录下,与本例位置/opt/eda/稍有不同),如下图4所示。
    在这里插入图片描述
    图4 添加search path窗口
    选择标准单元工艺库所在的目录,点击OK完成一条搜索路径的设置,回到图3 界面,此时表格窗口中会多出一项刚刚添加的路径。同样,点击Add…按钮添加其余的搜索路径:symbol所在路径、设计代码所在路径、约束文件所在路径、io工艺库所在路径等。完成路径设置后,图3 所示的search path设置窗口会变成如下图5所示。点击OK按钮完成set search path工作。
    在这里插入图片描述
    图5 完成search path的表格窗口
    以上工作对应的tcl命令:set search_path “path”,其中path内容就是上
    述的路径(如”…/code …/constrn /usr/eda/designKit/umn18/sc-x/synopsys”)。
    完成搜索路径的设置后,要进行工艺库相关的文件配置。其实配置好搜索路径后可以直接将相应的库文件写入对应的表格项,同一项中各文件中间用空格分开即可。这里为了熟悉工具,仍然逐项查找填写。在图2界面中,点击Link library右侧的查找按钮,出现Set Link Libraries的表格窗口,如下图6所示。
    在这里插入图片描述
    图6 链接库的表格窗口
    在上图中第一项不要改动,表示的是链接对象为当前内存。同上面设置search path一样,点击Add…按钮,查找库文件(注意工作站上的路径位置与本例不同),出现的界面如下图7所示。
    在这里插入图片描述
    图7 链接库的查找与选择
    选中库文件后(注意link library和后面的target library采用的是synopsys的数据库文件格式db或者ddc,该文件是二进制格式;欲了解其内容可以察看
    相对应的lib文本文件,试着读一下会了解更多),点击open按钮,回到图6的界面,其中增加了一项刚刚选择的库文件,如下图8所示的界面,至此完成一个库文件的设定。
    在这里插入图片描述
    图8 选定slow.db链接库
    在标准单元库中选定slow.db和fast.db两个库文件,io单元库中也一样。一般在逻辑综合中最大延时是最重要的约束,因此也可以直接采用slow或者worst case库,而不标明fast或者best case库。本例中将其加上,主要用于对照时序报告察看二者的区别。
    设置完成链接库之后,形成如下图9所示的表格图窗,其中最后一项为工具自带的design ware IP库,用于复杂功能逻辑优化(?)。
    在这里插入图片描述
    图9 链接库文件选定图窗
    因为在前面设置了search path,其中包括了上述工艺相关库的路径,因此在设置link library和后面的target library的时候,可以直接写上库的文件名称而略
    去路径,工具可以自动完成相应文件的搜索,去除路径之后的链接库文件如下图10所示。
    在这里插入图片描述
    图10 无路径的链接库文件选定图窗
    在上图10或者图9中,点击OK按钮完成连接库的设定。设置链接库的操作可以直接采用tcl命令set link_library ”library” 来完成,其中引号中的就是刚才设定的几个库文件,用空格分开,简单吧。
    目标库的设定(target library)同link library操作一样,而且除了没有表示内存的星号(*)之外,内容也是完全一样的。选定或者填写结果如下图11所示。
    在这里插入图片描述
    图11 目标库的设定图窗
    目标库设置采用的tcl命令为:set target_library “lib”,其中lib的内容即为刚才设置的几个库文件(例“fast.db slow.db”)。
    然后再进行符号(symbol)库的设定,符号库主要是用来在gui窗口中查看电路时使用的,表示基本单元器件的视图。同target library一样,也可以直接写
    入库名,忽略路径。因该umc库中没有symbol文件,故采用工具中自带的symbol库文件。选择窗口、库名称见下图12。
    在这里插入图片描述
    图12 目标库的设定图窗
    符号库设置的tcl命令为:set symbol_library “lib”。在图12中点击ok按钮,完成设置symbol库。
    至此setup内容已经完成设置,结果如下图13所示。
    在这里插入图片描述
    图13 setup设定窗口
    在图13中,点击OK按钮,完成启动项内容的设置。随后该设置可以在菜单命令中导出:File—>Save info—>Design Setup,将该文件保存为设计启动配置文件.synopsy_dc.setup,直接放在work目录下。下次再在该目录下启动工具的时候就不必重新配置,点击File—>Setup…,就可以看到表格中的各项已经配置完成了。

    3.设计读入

    完成启动项配置后就要将设计倒入工具,选择菜单命令:File—>Read…,出现Read Design窗口。查找设计代码所在路径,选中所有需要的设计代码,如下图14所示。点击Open按钮,完成代码读入。
    在这里插入图片描述
    图14 setup设定窗口
    在读入代码的过程中,注意dv下方的log窗口回显与报告,如下图15。同时点选history键,查看相应的tcl命令:read(或者read_verilog)。
    在这里插入图片描述
    图15 读入设计时的窗口
    读入设计之后,当前的设计会是读如过程中最后一个代码文件对应的设计,
    要将顶层设计设为当前设计。在dv主界面的工具栏下方的工具条下下拉选项选中、设置当前设计,我们这里是dcLabCore。同样注意history栏中的tcl命令:set current_design dcLabCore,记住对应的操作。
    在这里插入图片描述
    图16 当前设计设定
    完成当前设计的设定后,以后的操作就是针对该设计进行的。下面要做的就是将设计与库链接起来。选择菜单命令:File—>Link Design。出现Link Design窗口,如下图所示。注意Search path与Link library两项与前述启动项中的设置是否一致。
    在这里插入图片描述
    图17 Link Design窗口
    点击OK按钮完成设计与库的链接。此时要注意log窗口的链接过程的操作回显,及时修改错误与告警。
    完成链接后要对设计进行检查。选择菜单命令:Design—>Check Design,出现如下窗口,点击OK按钮,对设计进行检查。注意log栏中的报告。
    在这里插入图片描述
    图18 Check Design窗口
    至此,读入设计的工作完成。在这过程中,源代码中的各种与综合相关的问题都会被检查出来,注意随时查看报告并修改直到被综合器接受。下面就要对设计进行约束了。

    4.设计约束与编译

    在dv的主界面中,因为已经读入设计,此时很多菜单和工具栏已经激活。在图16中,先选中Logical Hierarchy中的dcLabCore项,点击工具栏中的Create Symbol View(或者菜单项Schematic—>New Symbol View 选项),出现当前设计的symbol,我们的约束就要在当前设计中添加。
    这里之所以先创建一个symbol,因为很多设计的约束,比如创建时钟(create clock)、输入输出延时(set input_delay/output_delay)、驱动与负载(set drive/load)、时钟无关路径(set false_path)等等,都是针对设计的端口的(port),图形化的
    界面操作起来容易些。得到的symbol如下图19所示。
    在这里插入图片描述
    图19 创建当前设计的symbol
    首先创建时钟,在symbol中选中clk_cal端口,然后选择菜单项Attributes—> Specify Clock…,注意灰色的Port name项应该为clk_cal;如果不是,不要关闭Specify Clock窗口,再在symbol上选中该端口,就会发现port name相应改变。
    时钟的约束这里设定主要有四项,一项是时钟的名称,要方便易记、意义明确就好;二项是时钟的周期,由频率决定,这里clk_cal为50M,故周期20ns(时间单位在库中定义);三项是时钟的波形,定义一个时钟周期内高电平所处的时间区间;四项是将时钟网络设定为don’t touch,也就是在综合的过程中,时钟线上不要添加包括驱动buffer在内的任何器件。时钟信号clk_cal的选择与填写过
    程如下图20所示。
    在这里插入图片描述
    图20 创建时钟clk_cal
    注意在Don’t touch network选项前打勾。点击OK按钮完成时钟clk_cal的创建。时钟的参数这里就不解释了。同样的方法创建时钟clk_cd,如下图。
    在这里插入图片描述
    图21 创建时钟clk_cd
    时钟信号clk_cd频率80M,故此周期12ns,同clk_cal一样,将上升沿设定在波形中间。以上操作对应tcl命令:create_clock。
    创建完成时钟之后,就要进行输入(set input_delay)和输出延时(output_delay)的约束,因为该约束是相对于时钟信号的。在symbol界面中,按住键盘ctr键,用鼠标选择addi1/addi2/multi1/multi2/cacul_ind端口(因为这些端口是和同一时钟clk_cal绑定的,设计中输入由时钟clk_cal驱动的触发器中),选择Attributes—> Operating Environment —>Input Delay菜单项,填写、选中相应的项目。如下图所示。
    在这里插入图片描述
    图21 创建相对时钟clk_cal的输入延时
    通常输入延时计算为时钟周期的60%,也就是说留出60%的外部裕量。注意图中Relative to clock项的时钟选择要与设计中的定义一致。
    同样完成相对于时钟信号clk_cd的端口codei、codec_ind的输入延时,选择、填写后的界面如下图21所示。上述操作对应的tcl命令为:set input_delay “port”,
    其中port即为相应于时钟的端口。
    在这里插入图片描述
    图21 创建相对时钟clk_cd的输入延时
    完成输入延时之后进行输出延时的设定(output_delay)。选中symbol中的端口caculo(它是由时钟信号clk_cal驱动输出),选择菜单项Attributes —> Operating Environment —>Output Delay,填写、选择如下图的内容,点击Apply按钮完成设置。
    在这里插入图片描述
    图21 创建相对时钟clk_cal的输出延时
    同样完成输出信号decdo的输出延时的设定,注意该信号是和时钟clk_cd绑定的。以上操作定应tcl命令:set output_delay。
    现在除了输入信号sub_en和输出信号sub_ovfl以外,所有的信号(除rstn)都进行了约束。现在来进行余下这两个端口信号的约束。在symbol中选中这两个端口,选择菜单项Attributes—>Optimization Constraints—>Timing Constraints,出现Timing Constraints窗口,如下图所示选择填写,完成约束。对应的tcl命令为:set max_delay。
    在这里插入图片描述
    图22 约束输入与输出间的最大延时
    这里采用set max_delay的方法是因为输入端口信号sub_en到输出信号端口sub_ovfl之间没有时序逻辑,只有组合逻辑,因此要约束输入端口到输出端口之间的最大延时(最小延时除非有需要,否则可以不加以约束)。
    时序约束中还需要将无关路径区分开来,采用set_false_path的方法。所谓无关路径,就是告诉综合器某两条或者多条路径之间没有时序关系,可以不必理会、优化这些路径间的电路。设计中。sub_en端口的信号送入纯组合逻辑,而且与时钟clk_cal和clk_cd不存在相位依赖关系,故此这里设置为false path。在symbol界面中选定sub_en端口和clk_cal、clk_cd端口,选择菜单项:Attributes
    —>Optimization Directive—>Timing Paths,出现如下窗口,From栏中留有sub_en项,To栏中留有clk_cal和clk_cd两项,选中False path项。
    在这里插入图片描述
    图23 无关路径设置
    下面来设置驱动与负载(drive/load)。首先选中symbol中的输入信号端口,如下图所示。选择菜单项Attributes—> Operating Environment—>Drive Strength,出现Drive Strength窗口。按照下图填写、选择相应的内容,完成驱动设置。
    在这里插入图片描述
    图24-a 配置输入驱动
    在这里插入图片描述
    图24-b 配置输入驱动
    在symbol界面选中三个输出端口,选择菜单项Attributes—> Operating Environment—>Load,出现Load窗口。注意选中三个输出信号端口。在Capacitive load栏中填容性负载数值。
    在这里插入图片描述
    图25 输出负载约束
    以上操作对应tcl命令:set drive/load。
    现在来设置操作环境(Operating Conditions)的设置。选择菜单项Attributes—> Operating Environment—> Operating Conditions,出现如下窗口。
    在这里插入图片描述
    图26 操作环境的设置
    按照图示选择相应的内容,按按钮OK完成操作环境的设置。对应的tcl命令为:set operating_conditions。
    同样的,完成wire Load的设置:选择Attributes—> Operating Environment—> Wire Load菜单项,选择umc18_wl20模型。对应的tcl命令:set wire_load。
    在这里插入图片描述
    图27 线载模型的设置
    下面进行design rule的设定,主要是fanout和transition。选择菜单项Attributes—> Optimization Constraints—> Design Constraints,出现下图所示界面,只填写图示的两项即可。对应的tcl命令:set max_fanout/transition。
    在这里插入图片描述
    图28 fanout与transition的设置
    至此,设计相关约束设置完成,可以对设计进行综合了。选择菜单项Design—> Compile Design,出现设计编译窗口,如图选择,点击OK按钮编译设计。
    在这里插入图片描述
    图29 设计编译界面
    编译的过程会随着设计的复杂变慢,编译的过程中注意log窗口的输出。完成编译后,需要查看各种报告。

    5.查看报告与设计输出

    很多时候综合并不是一次就通过的,在这过程中有可能时序不满足约束要求,或者约束设置的不合理,或者设计本身有问题等,需要查看报告、调试。这里最重要的一个报告是约束报告。选择菜单项Design—>Report Constraints,出现如下图30所示的界面。
    在这里插入图片描述
    图30 约束报告选择界面
    勾选想要查看的内容,点击OK按钮,可以看到与约束相关的报告。简单的一个报告如下图31所示。
    查看报告的选项大多位于菜单Design和Timing之下。在完成综合之后,如果Report Constraints没有发现错误和不期望的告警,可以尝试将这些报告项输出,具体查看一下,非常有助于了解设计、熟悉工具。同时可以对照库中的.lib
    文件查看一些参数。
    在这里插入图片描述
    图31 约束报告结果
    如果没有报告错误,就可以将设计保存下来。选择菜单项File—>Save as,可以将设计保存为各种格式。
    在这里插入图片描述
    图32 保存设计界面
    同样可以保存启动项文件和约束文件:选择菜单项File—>Save info—> Constraints/Design setup,保存相应文件。
    6..synopsys_dc.setup文件与dcLab.con文件
    a. 启动项文件
    文件.synopsys_dc.setup应位于当前的工作目录中,Linux/Unix下为隐含文件。这里先给出一典型的.synopsys_dc.setup文件,如下所示。
    在这里插入图片描述
    文件.synopsys_dc.setup第一项内容设定工具工作过程中需要搜索的路径位置(search_path),一般包括源代码的目录、库文件(工艺库模型文件、symbol文件)的目录、约束/运行脚本的目录、某些中间文件的目录以及在工具的安装目录配置的启动搜索目录,包括gtech库等目录。
    文件.synopsys_dc.setup第二项内容一般用来设定目标库(target_library),也就是工艺库的名称,综合过程中工具会自动在搜索目录中寻找,来完成综合工作。第三项内容一般用来设定链接库(link_library),用于解析设计电路中的最小颗粒单元,其中,*,用来表示内存。
    文件.synopsys_dc.setup第四项内容用来设定symbol库,也就是design vision
    可以看到的网表图形。其余的内容还可以包括命名规则、别名定义等,可以任意设定,示例中没有一一给出。
    b.设计的约束文件
    约束文件主要用于优化设计电路的,主要内容有:读入/分析源文件、设定设计的工作条件/环境/设计规则、时序条件、面积约束、综合策略等。
    首先是读入源代码,也就是HDL文本描述的设计文件,此处不用制定目录,design compiler会在搜索目录($search_path)中搜索。tcl语句如下:

    read_verilog {dcLabCore.v dcLabTop.v iopads.v}
    读入设计原文件后,一般设定当前设计,这样约束条件才可有针对性施加:
    current_design dcLabCore
    设定当前设计后,要完成链接,也就是将设计与库链接起来,用于映射过程中搜寻相应的单元,完成综合。tcl语句: link
    检查设计,主要是检查完成转换(translate)的设计: check_design。然后设定输出网表的格式规则,输出未优化的设计:
    set verilogout_no_tri true
    change_names -rule verilog -hier
    write -f ddc -hier –out ../output/dcLabCore.ddc
    然后对设计设定时序约束,这是最重要的一项约束,用于设定设计的工作速度的。针对不同的设计部分,有不同的约束方法。这里假设设计为全同步设计,单时钟工作,复杂情况参考design compiler的手册即可。以下语句设定时钟及属性、输入信号的时间裕量:
    create_clock –name clk_cal -period 20 [get_ports clk_cal]
    #名称clk_cal,对应端口clk_cal,50M工作频率
    set_clock_uncertainty -setup 0.2 [get_clocks clk_cal] #时钟的不确定时间
    set_clock_latency -source -max 0.3 [get_clocks clk_cal]#时钟输入延时
    set_clock_latency -max 0.1 [get_clocks clk_cal]#时钟延时
    set_clock_transition -max 0.2 [get_clocks clk_cal]#时钟上升/下降时间
    set_dont_touch_network [get_ports "clk* rstn"]
    #不对时钟复位信号优化
    set_ideal_network [get_ports "clk* rstn"] #延时分析时认为时钟复位无延时
    set_input_delay -max 12 -clock clk_cal [get_ports "add* mult*"]#输入信号裕量
    set_output_delay -max 12 -clock clk_cal [get_ports "caculo"] #输出时间裕量
    完成时序约束后,要对设计的工作环境、设计规则等进行约束,如下约束语句:
    set_wire_load_mode top
    #设定线载模型的模式
    set_wire_load_model -library slow -name umc_wl20 -max
    #线载模型,要粗略综合一下估出面积,再设定
    以下是设计规则的约束:
    set_driving_cell -lib_cell FFEDQHD4X -pin Q [get_ports all_inputs]
    #驱动能力的约束
    set max_cap [expr [load_of slow/AND2HD4XSPG/A] * 5]
    set_load [expr 3 * $max_cap] [all_outputs] #设计负载设定
    set_fanout_load 10 [all_outputs] #扇出负载
    然后是综合的策略,简单的设计比较容易,这里不展开:
    compile -map_effort medium -incremental_mapping
    输出综合报告、输出综合网表、综合数据以及标准延时文件:
    rc > log/rc.log #时序报告
    write -f verilog -hier -out output/dcLabTop.sv #输出网表
    write -f ddc -hier -out output/dcLabTop.ddc#综合数据文件
    write_sdf -version 2.1 mapped/light_controller.sdf #标准延时文件
    

    上述内容为约束文件主要内容,同学们可以讲示例中的约束保存下来自己细看一下。

    展开全文
  • 介绍Compiler的构造比较无趣,不如先过后面的,在用到compiler的时候再做讲解。  这一节主要讲这行代码: // 不管这里 compiler = new Compiler(); compiler.context = options.context; compiler....
    介绍Compiler的构造比较无趣,不如先过后面的,在用到compiler的时候再做讲解。


      这一节主要讲这行代码:


    // 不管这里
    compiler = new Compiler();
    compiler.context = options.context;
    compiler.options = options;
    // 看这里
    new NodeEnvironmentPlugin().apply(compiler);
      这个构造了一个NodeEnvironmentPlugin对象并调用apply对compiler进行操作。


      流程图:






      模块源码如下:


    复制代码
    "use strict";


    const NodeWatchFileSystem = require("./NodeWatchFileSystem");
    const NodeOutputFileSystem = require("./NodeOutputFileSystem");
    const NodeJsInputFileSystem = require("enhanced-resolve/lib/NodeJsInputFileSystem");
    const CachedInputFileSystem = require("enhanced-resolve/lib/CachedInputFileSystem");


    class NodeEnvironmentPlugin {
        apply(compiler) {
            // 可以缓存输入的文件系统
            compiler.inputFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 60000);
            const inputFileSystem = compiler.inputFileSystem;
            // 输出文件系统
            compiler.outputFileSystem = new NodeOutputFileSystem();
            // 监视文件系统
            compiler.watchFileSystem = new NodeWatchFileSystem(compiler.inputFileSystem);
            // 添加事件流before-run
            compiler.plugin("before-run", (compiler, callback) => {
                if (compiler.inputFileSystem === inputFileSystem)
                    inputFileSystem.purge();
                callback();
            });
        }
    }
    module.exports = NodeEnvironmentPlugin;
    复制代码
      除去添加事件流,其余几步都是在compiler对象上挂载node的fs文件系统,详细的API用法可以去nodejs官网看文档:https://nodejs.org/dist/latest-v8.x/docs/api/


      这里只做简介:


    NodeJsInputFileSystem


    复制代码
    var fs = require("graceful-fs");


    module.exports = NodeJsInputFileSystem;
    // 获取文件信息
    NodeJsInputFileSystem.prototype.stat = fs.stat.bind(fs);
    // 读取目录内容
    NodeJsInputFileSystem.prototype.readdir = function readdir(path, callback) {
        // files 是目录中不包括 '.' 和 '..' 的文件名的数组
        fs.readdir(path, function(err, files) {
            callback(err, files && files.map(function(file) {
                // 对文件名进行NFC格式化
                return file.normalize ? file.normalize("NFC") : file;
            }));
        });
    };
    // 读取文件
    NodeJsInputFileSystem.prototype.readFile = fs.readFile.bind(fs);
    // 读取链接
    NodeJsInputFileSystem.prototype.readlink = fs.readlink.bind(fs);
    // 同步方法
    NodeJsInputFileSystem.prototype.statSync = fs.statSync.bind(fs);
    NodeJsInputFileSystem.prototype.readdirSync = function readdirSync(path) {/**/};
    NodeJsInputFileSystem.prototype.readFileSync = fs.readFileSync.bind(fs);
    NodeJsInputFileSystem.prototype.readlinkSync = fs.readlinkSync.bind(fs);
    复制代码
      可以看到,这里只是对引入的graceful-js的部分方法进行bind绑定,大概看一下graceful-fs的内容:


    复制代码
    var fs = require('fs')


    // ...工具方法


    module.exports = patch(require('./fs.js'))
    if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) {
        module.exports = patch(fs)
    }


    module.exports.close =
    www.yixingsyle.cn fs.close = (function(fs$close) { /*...*/ })(fs.close)


    module.exports.closeSync = fs.closeSync = (function(fs$closeSync) { /*...*/ })(fs.closeSync)


    function patch(fs) {
        // fs方法二次封装
        return fs
    }
    复制代码
      跟名字一样,内部调用了一个patch对fs模块进行二次封装,变得更加'优雅'。


     


    NodeOutputFileSystem


    复制代码
    "use strict";


    const fs = require("fs");
    const path = require("path");
    const mkdirp = require("www.2018yulpt.com mkdirp");


    class NodeOutputFileSystem {
        constructor() {
            // 新建多层级文件夹
            this.mkdirp = mkdirp;
            // 新建单个文件夹
            this.mkdir = fs.mkdir.bind(fs);
            // 删除文件夹
            this.rmdir = fs.rmdir.bind(fs);
            // 删除文件
            this.unlink = fs.unlink.www.rbuluoyl.cn/ bind(fs);
            // 将内容写进某个文件
            this.writeFile = fs.writeFile.bind(fs);
            // 略
            this.join = path.join.bind(path);
        }
    }


    module.exports = NodeOutputFileSystem;
    复制代码
      这个模块就十分亲民,都是原生的nodeAPI,并没有进行包装。


     


    NodeWatchFileSystem
    复制代码
    "use strict";


    const Watchpack = require("watchpack");


    class NodeWatchFileSystem {
        constructor(inputFileSystem) {
                this.inputFileSystem = inputFileSystem;
                this.watcherOptions = {
                    aggregateTimeout: 0
                };
                this.watcher =www.rbuluoyl.cn/ new Watchpack(this.watcherOptions);
            }
            // 对文件进行监视
        watch(files, dirs, missing, www.t1yl1.com/ startTime, options, callback, callbackUndelayed) { /*...*/ }
    }


    module.exports = NodeWatchFileSystem;
    复制代码
      模块内容比较简单,引入一个inputFileSystem进行初始化监视对象,原型上只有一个watch方法。(实际内容非常深入和繁杂,后面再讲)


      


      这个模块主要是为了接下来输出打包文件做准备,主要内容大部分是nodejs相关。


      不过没关系,都是用JS写的。


    有木有大佬带带我入门V8引擎
    展开全文
  • Compiler

    千次阅读 2013-09-09 16:07:19
    http://en.wikipedia.org/wiki/Compiler ...Compiler From Wikipedia, the free encyclopedia This article is about the computing term. For the anime, see Compiler (anime). A
  • 几款好的C/C++编译器(编译器而非IDE)

    万次阅读 多人点赞 2018-11-10 17:38:39
    几款好的C/C++编译器(编译器而非IDE)
  • 编译器介绍

    千次阅读 2018-03-14 11:54:35
    源文件经过编译器编译...编译器是一系列工具的集合,如arm平台使用的交叉编译器arm-linux-gcc包括arm-linux-cpp(compiler preprocessor预处理)、arm-linux-cc1(c compiler编译)、arm-linux-as(assembly 汇编)...
  • java compiler没有1.8怎么办

    万次阅读 热门讨论 2018-01-11 22:50:02
    1.打开eclipse->选择help->点击 install from catalog 加载完成后,点击搜索 Java 8 : 选择第一个点击安装,安装完成后,重启eclipse,打开java compiler 就可以选择1.8了。
  • No CMAKE_CXX_COMPILER could be found
  • 右键点击项目&gt;Properties&gt;Java Compiler&gt;将Compiler compliance level改为1.8
  • Tengine安装./configure: error: C compiler cc is not found

    万次阅读 多人点赞 2016-05-20 16:19:53
    CentOS 6.5 下 安装 Tengine 执行配置命令./configure 时提示以下错误:checking for OS + Linux 2.6.32-431.el6.x86_64 x86_64checking for C compiler ... not found解决:执行以下命令:yum -y install gcc ...
  • maven项目会用maven-compiler-plugin默认的jdk版本来进行j编译,如果不指明版本就容易出现版本不匹配的问题,可能导致编译不通过的问题。解决办法:在pom文件中配置maven-compiler-plugin插件(以jdk1.8)。 1、...
  • configure: error: C compiler cannot create executables错误解决

    万次阅读 热门讨论 2009-06-13 18:30:00
    我们在编译软件的时候,是不是经常遇到下面的错误信息呢? checking build system type... i686-pc-linux-gnuchecking host system type...... gccchecking for C compiler default output file name...c
  • codeblocks找不到编译器

    万次阅读 2017-12-22 12:30:32
    刚装了codeblocks运行不了,..."HelloWorld - Debug": The compiler's setup (GNUGCC Compiler) is invalid, so Code::Blocks cannot find/run the compiler. Probably the toolchain path within the compiler opti
  • sudo apt-get install build-essential (这个命令是安装编译工具)
  • see the compiler error output for details.解决修改build.gradle文件下的dependencies下的classpath配置版本。如下图所示:在这里修改Androidstudio classpath对应的版本就OK了。例如我的是3.0.1,如下所示:...
  • gcc compiler is not in your $PATHit means either you dont have gcc installed or it's not in your $PATH variableto install gcc use this: (run as root)redhat base:yum groupinstall "Development ...
  • 属于编译器没有进行安装,可以根据你的系统选择在命令行中运行下面的命令。 RedHat-based yum install gcc gcc-c++ Debian/Ubuntu-based apt-get install cmake gcc g++ ...如果你权限不够,在命令前面加上sudo...
  • The CXX compiler identification is unknown 引起这个错误的原因是 CMake 找不到 C++ 的编译器,检查 VS 的安装目录是否有 cl.exe 以及 rc.exe 和 rcdll.dll。 如果没有 cl.exe,那么可能是只安装了VS,没有安
  • ./configure: error: C compiler cc is not found 确认自己是安装了gcc的。 在网上查了很多资料都不管用。最后解决方法: whereis gcc gcc: /usr/bin/gcc /usr/lib/gcc cd /usr/bin/ ls -alh...
1 2 3 4 5 ... 20
收藏数 293,886
精华内容 117,554
关键字:

compiler