我是马甲
    
    
    
		
        浏览(0) + 
        2007-09-14 17:01:58 发表
        
编辑 
         
        
        
        
        关键字: 
        
 
        
 
        
        
        
                
        来自 http://sofire.javaeye.com/blog/112465 dmd 的东西还需要它自己的 link.exe ,而这个文件在dmc中,还要另外下载 -- 至少是在目前的版本中如此. -------------------------------------------------- Dmd编译器学习笔记  关键字:   D语言 dmd 编译器 complier      Dmd编译器学习笔记 英文原文在这里:  http://digitalmars.com/d/dcompiler.html  在这里有一篇翻译文章:  http://sofire.javaeye.com/blog/111667  不过,主要是关于windows的;我更关心Linux下的使用。  顺便看看两者有啥区别。 相关文件  注意:  Linux的dmd配置文件是dmd.conf  Windows的配置文件是sc.ini  /dmd/bin/dmd D 编译器的可执行文件  /dmd/bin/dumpobj Elf file dumper  /dmd/bin/obj2asm Elf文件反汇编器  /dmd/bin/dmd.conf 全局配置文件(复制到 /etc/dmd.conf)  /dmd/lib/libphobos.a D运行库(复制到 /usr/lib/libphobos.a)  DMD的安装  下载dmd程序:http://ftp.digitalmars.com/dmd.zip,解压到~/dmd目录 复制dmd.conf文件到/etc目录 代码 cp ~/dmd/bin/dmd.conf /etc    给下面的文件添加执行权限 代码 chmod u+x ~/dmd/bin/{dmd,dumpobj,obj2asm,rdmd}    把~/dmd/bin添加到PATH环境变量;或者把它们复制到/usr/local/bin目录下(不要只复制可执行程序) 复制库文件到/usr/lib目录 代码 cp ~/dmd/lib/libphobos.a /usr/lib    以上安装过程比较简单,只有PATH环境变量设置正确了,就应该没有什么问题 编译参数和开关  命令的格式:  代码 dmd   files...  -switches...     [Windows]支持以下类型的文件:  代码 Extension      File Type      none           D source files      .d             D source files      .di            D interface files      .obj           Object files to link in      .lib           Object code libraries to search      .exe           Name output executable file      .def           module definition file      .res           resource file      [Linux]支持以下类型的文件:  代码 Extension      File Type    none           D source files    .d             D source files    .di            D interface files    .o             Object files to link in    .a             Library files to link in    好像不支持.so文件--这一点不肯定  编译开关之一  代码 -debug        编译调试代码       -debug=level        编译调试代码:code <= level       -debug=ident        编译调试代码:标识符为ident       -version=level        生成版本代码:>=level       -version=ident        生成版本代码:==ident            -unittest        编译单元测试代码(还有断言)       -cov        添加覆盖率分析指令;运行程序后,会生成.lst文件       -release        生成发行版本;会去掉契约和断言等信息    -debug / -version  debug、version的使用方法很相似  代码 //debug.d    import std.stdio;       void main()    {        debug    { writefln("debug"); }        debug(1) { writefln("debug(1)"); }        debug(2) { writefln("debug(2)"); }           debug(ERROR) { writefln("debug(ERROR)"); }        debug(WARN)  { writefln("debug(WARN)"); }           version(HOME)      { writefln("version(HOME)"); }        version(BUSINESS)  { writefln("version(BUSINESS)"); }           version(WINDOWS) {} else { writefln("version(!WINDOWS)"); }    }    编译并运行之:  代码 # dmd -debug -run debug.d    debug    debug(1)    version(!WINDOWS)       # dmd -debug=1 -run debug.d    debug    debug(1)    version(!WINDOWS)       # dmd -debug=2 -run debug.d    debug    debug(1)    debug(2)    version(!WINDOWS)       # dmd -debug=ERROR -run debug.d    debug(ERROR)    version(!WINDOWS)       # dmd -debug=WARN -run debug.d    debug(WARN)    version(!WINDOWS)       # dmd -version=HOME -run debug.d    version(HOME)    version(!WINDOWS)       # dmd -version=BUSINESS -version=WINDOWS -run debug.d    version(BUSINESS)    -unittest  代码 //unittest.d    import std.stdio;       class A    {        int i;        this(int v) {            i = v;        }              unittest {            A a = new A(1);            assert(a.i == 1);             assert(a.i != 0);         }       }       int add(int a, int b)    {        return a - b;        // 这里没有unittest    }       void main()    {        // 这里没有unittest    }       unittest {        assert(add(1, 2) == 3);     }    先正常编译,没有语法错误:  代码 # dmd -run unittest.d    再编译单元测试代码  代码 # dmd -unittest -run unittest.d     Error: AssertError Failure unittest(30)    30行有错误?add函数写错了:(  -cov  看看覆盖率分析选项:  代码 //cov.d    import std.stdio;       void main()    {        for (int i; i < 2; i++)        {            if (i < 5)                writefln("i < 5");            else                writefln("i >= 5");        }    }    编译并运行:  代码 # dmd -cov -run cov.d    i < 5    i < 5    得到覆盖率分析文件:cov.lst:(注意:编译完并不会有这个文件;运行程序后才会生成)  代码        |//cov.d           |import std.stdio;           |           |void main()           |{          6|    for (int i; i < 2; i++)           |    {          2|        if (i < 5)          2|            writefln("i < 5");           |        else    0000000|            writefln("i >= 5");           |    }           |}    cov.d is 75% covered    第6行运行了6次--自己算算是不是;  第11行运行了0次--搜索000000字符串,就能轻松找到没有覆盖到地方;  更多详情参考:http://digitalmars.com/d/code_coverage.html  -release  用法很简单,不举例了 编译开关之二  代码 -D        生成文档       -Dddocdir        把文档生成到docdir目录;注意是 -Dd            -Dffilename        指定文档的文件名;    编译命令很简单:  代码 dmd -D debug.d    关于文档的更多信息参考:http://sofire.javaeye.com/blog/111881  编译开关之三  代码 -H        生成.di接口文件       -Hddir        把接口文件生成到dir目录;注意是 -Hd       -Hffilename        指定接口文件名;注意是 -Hf    关于接口,看一段翻译:  当处理源文件中的import声明时,编译器会搜索import对应的源文件,从中提取出需要的信息。  编译器同时也会搜索D接口文件,D接口文件中只包含模块中需要导入的内容,而不是整个模块。  使用D接口文件的好处是:  D接口文件更小,和D源文件相比处理起来更快。  可以隐藏源代码。比如以接口文件和object库的方式提供源程序,而不是提供全部源代码。  D接口文件可以在编译D源文件时用-H开关创建,D接口文件的后缀是.di。  当编译器分解import声明时,搜索寻找.di形式的D接口文件,再寻找D源文件。  D接口文件有点和C++头文件相似,但这不是必需的,它不属于D语言,只是编译器的一个功能,只是用来优化程序的构建。  dmd -H生成的接口文件包括了源代码;只是去掉了注释,断言等信息;具体怎么回事,待弄明白了再来改这里(TODO)  编译开关之四  代码 -c        只编译,不链接;简单点说就是只生成.o文件,不生成可执行文件       -Ipath        指定import路径;多个路径之间用分号(;)分割;允许有多个-I,并按照-I指定的路径顺序进行搜索       -Jpath        指定D源程序中import表达式的搜索路径;多个路径之间用分号(;)分割;        允许有多个-J,并按照-J指定的路径顺序进行搜索       -Llinkerflag         把linkerflag传递给连接程序(linker),比如: -L-L/usr/lib       -o-        不生成.o文件,一般和-H、-D一起使用       -offilename        指定输出文件名;可以是可执行程序,也可以是其他文件;注意是:-of       -odobjdir        把.o文件生成到objdir目录;默认是生成到当前目录;注意是:-od       -op        默认生成的object文件(.o)会在当前目录;添加-op参数则会生成到源文件所在目录    -c  代码 dmd debug.d     # 生成debug可执行文件    dmd -c debug.d  # 生成debug.o文件    dmd编译器默认是编译成.o文件后,再和其他库连接成可执行文件;  某些情况下不需要编译成可执行文件,比如没有main函数--也编译不成  这时就可以只编译成.o文件  bud等程序build工具,可以自动判断文件是否有main函数,并生成相应的文件;  但dmd编译器不是这样的;所以,熟悉了dmd编译器后,可以只使用bud等工具来编译程序 -I / -J  代码 import std.stdio;               // -I    void main()    {        auto b = import("x.d");     // -J    }    自己体会它们的用途吧:)  注意:如果在搜索路径下有同名文件的话,可能出现奇怪的问题;避免出现这种情况,或者改变参数的顺序 -Llinkerflag  一般是-L-L 和 -L-l参数,指定lib路径和库文件  比如:-L-L/usr/local/lib -L-lsqlite3  对linker不熟悉,回头在详细写这块 -o-  如果只想生成文档,连.o文件都不想要;则-o- 就是你想要的了 -offilename  默认情况下,是根据源文件名来确定后续文件的文件名;  比如foo.d 会生成 foo.o 与 foo 文件;  通过-of参数可以改变输出文件的名字:  dmd -ofbar.exe foo.d 它不会自动添加后缀:  dmd -c -ofbar foo.d  生成文件是 bar,而不是bar.o,这可能不是你想要的 -odobjdir -op  .o文件默认生成在当前目录下;  -od 是指定生成目录,-od.和默认相同  -op 是把.o生成到源文件所在目录  具体生成到什么目录下,就看自己的爱好了;  喜欢干净,就用-od吧;对了,-run参数能生成更干净的代码;) 编译开关之五  代码 -O        优化生成的代码,使程序运行得更快       -g        添加调试信息       -gc        添加C风格的调试信息(为旧的gdb)       -inline        用内联函数的方式进行优化;相当于C的inline       -fPIC        生成位置无关代码       -d        允许废弃的特征       -profile        profile the runtime performance of the generated code         参见:http://www.digitalmars.com/ctg/trace.html    这几个参数,要么很简单,要么不懂含义;也懒得去研究具体的意思了。  其中的-g参数涉及到使用调试器;我喜欢用writefln调试;唉,回头再研究吧。 编译开关之六  代码 --help        打印帮助       -quiet        安静模式,不输出无关紧要的信息       -v        显示编译细节       -w        显示编译警告    编译开关之七  代码 -run srcfile args...        编译,链接,然后运行程序srcfile;args...(到命令行结束)都是程序的参数;        它不会保留.o和可执行程序(No .o or executable file is left behind)    文章开始就有怎么使用的例子  需要注意的是参数的顺序,因为很多写法都是错误的,正确的是:  代码 dmd 相关文件 编译开关 -run 含main的源文件 程序参数1 程序参数2    各种参数放在-run前面,然后是含有main的源程序,再后面的内容会全部传递给运行程序,作为参数  链接Linking  在dmd编译成功后,它会再调用连接程序;用-c参数可以不进行连接  连接的实际处理程序其实是gcc;这样能保证和gcc编译的模块兼容 环境变量  CC  默认是用gcc进行连接,可以通过设置CC环境变量,使用其他连接器 DFLAGS  The value of DFLAGS is treated as if it were appended to the command line to dmd.  没有弄明白它是怎么回事;( dmd.conf初始化文件  dmd会按照下面的目录顺序查找  当前工作目录 环境变量HOME指定的目录 dmd命令所在目录,即bin目录 /etc目录 dmd.conf的内容看起来像这样:  代码 ; dmd.conf 是dmd的配置文件    ; 分号是注释符号    ; %%包含的名字会用相应的环境变量替换    ; %@P%会被本文件的路径替换,即dmd.conf文件所在路径    [Environment]    DFLAGS="-I%@P%/../src/phobos"    DDOCFILE=candydoc/proj.ddoc    格式是 NAME=value;NAME即使是小写,也会被处理成大写;  里面的DFLAGS的值会覆盖环境变量指定的值 和Windows版本的区别  字符串文章量是只读的;对它写会导致段错误 配置文件是dmd.conf,而不是sc.ini Windows有一个@cmdfile开关 Windows有一个-nofloat开关 环境变量上有些不一样 总结:  和gcc比起来,参数少多了 ;)  虽然可以用bud进行编译,但理解dmd还是必要的。  反正也不复杂,花点时间学习一下还算值得。
         
        
        
        		
		        
                
                
     
    
 
	
	
     
    
       
    
    我是马甲
    
    
    
    
    
    		    
    
          
              
    	http://www.dnaic.com/d/doc/d/index.html D 程序设计语言   中文文档.
     
    
     
 
	 
	
    NEWBT官方QQ群1: 276678893 
    可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧. 
    但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件. 
    验证问题说明申请入群原因即可.