发新话题
打印

[D语言 编译器] 另一个D programming language编译工具ybud

另一个D programming language编译工具ybud

知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070708

点击下面网址查看原文:
http://www.d-programming-language-china.org

tag:D programming language,D语言编译器

理想的D programming language编译工具应该是这样:
假如D程序源文件目录是D:\d
D程序源文件dcode.d var.d

1 如果目录下有dcode.rc文件

如果没有dcode.res文件,应该自动调用资源编辑器编译出res文件

2 如果目录下有dcode.bat文件

则自动调用dcode.bat,然后退出。
存在dcode.bat说明该程序需要个性化编译。
这项功能可以扩展为存在dcode.make文件则...

多数时候我们是这样编译的,有时在编译器里按F7编译,有时要切换到程序目录双击dcode.bat,或者用dsss, build, rebuild。
切换来切换去烦不烦。

3 如果目录下有dcode.def

就在编译命令的文件列表里自动加上dcode.def。

4 不要在源文件外写编译配置文件好不好

不需要bat编译配置文件,也不需要dsss.conf编译配置文件。
一般的编译选项是约定的,不需要重复千百次。
特殊的编译选项写在源文件里好了,干吗要切换到程序目录,新建编译配置文件,再写编译规则,找目录,进入目录...太麻烦了。

5 F7就是debug模式build

多数时候我们是在debug模式下编译,应该是按一键就行了。( 本文出处: http://www.d-programming-language-china.org )

6 Ctrl + F7就是release编译

release 编译时可以自动调用upx压缩程序,或者把程序复制到指定目录。( 本文出处: http://www.d-programming-language-china.org )

7 编译库和编译bin应该是自动识别的

建立dmd\src\other目录,这个目录下的子目录名和lib文件名一一对应。
另外指定一个目录,这个目录下都编译成exe。
在编译工具里配置好这二个或更多个目录后,我们还需要在编译配置文件里写编译规则:type=library或type=binary吗
编译工具自己知道你要编译的是exe还是lib。

8 不要新造和D语言编译器和链接器不同的编译规则,开关

我们只要学习一种规则,那就是标准D编译器和链接器的编译规则。
bbs.d-programming-language-china.org写的ybud编译工具,所有的编译规则都是直接用D本身的规则。

总结一下,理想的d programming language编译工具应该是一键编译,不管是编译库还是编译exe,不管是dos程序还是windows程序,不管程序有无资源文件,不需要在D源程序文件以外的地方写任何编译规则文件。

基于以上几条,bbs.d-programming-language-china.org对现有的D programming language 编译工具的智能化程度严重不满。并花了一天时间初步写了ybud编译工具。现在还很不完善。比如目前版本只能适用于编译exe文件,不能用于编译库文件。因为库文件不是经常需要编译的。也许 yidabu会在后来实现这个功能。( 本文出处: http://www.d-programming-language-china.org )

下面是全部代码,你要编译通过,应该只需要很小的修改。

module ybud;
/*
    Author: yidabu, D programming language, China http://www.d-programming-language-china.org
    DMD:    1.018
    date:    20070708
*/
import std.regexp;
import std.file;
import std.utf;
import std.path;
import std.string;
import win32.shellapi : ShellExecuteW;
import win32.winuser;
import ydb.ini;
import dfl.application;        //for startupPath;

pragma(lib,"ydb.lib");
pragma(lib,"dfl_debug.lib");
pragma(lib,"shell32.lib");

int main(string[] args)
{
    int result;

    string ybudpath;    //ybud.exe fullpath
    string ybuddir;    //ybud.exe dir
    string filedir;        //D:\d
    string filename;        //D:\d\test.d
    string fileBaseName;    //test.d
    string fileShortName;    //test
    string batcontent;        //
    string buildflags;        //
    string rc;                //test.rc
    string res;            //test.res
    string run;        //test.bat
    string def;        //test.def
    string batpath;    //test_ybud.bat
    string src;        //=std.file.read(test.d)
    string inipath;    //...\ybud.ini

    string rcc;        //...\rcc.exe
    string upx;        //...\\upx.exe
    string copyto;        //...\down\...

    try
    {
        assert(args.length > 2, "argument number must larger than 2");
        filename = args[1];
        assert(std.file.exists(filename), "not exists " ~ filename);
        buildflags = args[2];
        if (args[2] == "debug")
            buildflags = "-debug -w -O -unittest -version=IE4";
        else if (args[2] == "release")
            buildflags = "-release -w -O -release -version=IE4";
        else
            assert(0, "args[2] must -debug or -release");
        ybudpath = Application.executablePath();
        ybuddir = std.path.getDirName(ybudpath) ~ r"\";
        filedir = std.path.getDirName(filename) ~ r"\";
        fileShortName = std.path.getBaseName(filename);
        fileShortName = fileShortName[0..$-2];                //test
        fileBaseName = std.path.getBaseName(filename);    //test.d
        rc = fileShortName ~ ".rc";        //test.rc
        res = fileShortName    ~ ".res";    //test.res
        run = fileShortName ~ ".bat";    //test.bat
        batpath = fileShortName ~ "_ybud.bat";        //test_ybud.bat
        def = fileShortName ~ ".def";            //test.def
        inipath = ybuddir ~ "ybud.ini";        //..\ybud.ini
        batcontent = "dmd " ~     fileBaseName;

        Ini ini = new Ini(inipath);

        if (ini["config"] is null ) ini.addSection("config");
        if (ini["config"]["rcc"] is null) ini["config"]["rcc"] = "";
        if (ini["config"]["upx"] is null) ini["config"]["upx"] = "";
        if (ini["config"]["copyto"] is null) ini["config"]["copyto"] = "";
        rcc = ini["config"]["rcc"];
        upx = ini["config"]["upx"];
        copyto = ini["config"]["copyto"];
        if (!rcc || rcc.length < 2 || !std.file.exists(rcc)) rcc = null;
        if (!upx || upx.length < 2 || !std.file.exists(upx)) upx = null;
        if (!copyto || copyto.length < 2 || !std.file.exists(copyto)) copyto = null;
        ini.save();
        delete ini;

        if (std.file.exists(rc) && rcc && !std.file.exists(res))
        {
            ShellExecuteW(null, toUTF16z("open"), toUTF16z(rcc), toUTF16z("-32 " ~ rc), toUTF16z(filedir), SW_HIDE);
            debug printf("now create res: %.*s \n");
        }

        if (std.file.exists(run))
        {
            ShellExecuteW(null, toUTF16z("open"), toUTF16z(run), toUTF16z(null), toUTF16z(filedir), SW_SHOW);
            debug printf("run %.*s \n", run);
            return 0;
        }

        string[] files;
        bool cb(DirEntry* de)
        {
            if (de.isdir)
                std.file.listdir(de.name, &cb);
            else
            {
                if (std.path.getExt(de.name) != "d") return true;
                if (de.name == filename) return true;
                batcontent ~=" " ~ std.string.replace(de.name, filedir,"");
            }
            return true;
        }
        std.file.listdir(filedir, &cb);

        if (std.file.exists(res)) batcontent ~= " " ~ res;
        if (std.file.exists(def)) batcontent ~= " " ~ def;

        string pattern = r"////buildflags\s*=\s*(.+)\s*";
        if (auto m = std.regexp.search(src, pattern, "i")) buildflags ~= m.match(1);
        batcontent ~= " " ~ buildflags;
        src =cast(string) std.file.read(filename);
        pattern = r"////" ~ args[2] ~ r"((.|\s)+?)////";
        if (auto m = std.regexp.search(src, pattern, "mgi"))
        {
            batcontent ~= m.match(1);
        }
        batcontent ~= "\r\npause\r\nerase *.obj *.map";
        if (args[2] == "release" && upx)
        {
            batcontent ~= "\r\nerase " ~ fileShortName ~ "_u.exe";
            batcontent ~= "\r\n" ~ upx ~ " --best -o" ~ fileShortName ~ "_u.exe " ~ fileShortName ~ ".exe" ;

        }
        if (args[2] == "release" && copyto)
        {
            string sexe = std.file.exists(fileShortName ~ "_u.exe") ? fileShortName ~ "_u.exe" : fileShortName ~ ".exe";
            if (auto m = std.regexp.search(src, r"////copyto\s*=?\s*(.*)\s*", "i"))
            {
                string t = m.match(1);
                debug printf("copyto %.*s \n", t);
                if ( t.length >5 ) // std.file.exists(t) failed ?
                {
                    copyto = m.match(1);
                }
                batcontent ~= "\r\ncopy " ~ sexe ~ " " ~ copyto ~ r"\" ~ fileShortName ~ ".exe";
                debug printf("copyto %.*s \n",copyto);
            }
        }

        std.file.write(batpath, batcontent);
        assert(std.file.exists(batpath));
        ShellExecuteW(null, toUTF16z("open"), toUTF16z(batpath), null, toUTF16z(filedir), SW_SHOW);
    }
    catch(Exception e)
    {
        printf("catch %.*s\n", e.msg);
        result = 1;
    }
    return result;
}
//=main

编译得到ybud.exe, 然后在文本编辑器scite的d.properties中如下设置:

QUOTE:
//F7
command.build.*.d=yourpath\ybud\ybud.exe $(FilePath) debug
//Ctrl + F7
command.compile.*.d=yourpath\ybud\ybud.exe $(FilePath) release
command.go.*.d=$(FileName)
command.go.subsystem.$(file.patterns.d)=1

debug模式编译就按F7,release模式编译就按Ctrl+F7
特定的编译开关就以////buildflags=的形式写在源程序里。
首次运行会创建ybud.ini,配置好ini文件,就可以自动编译资源文件。在release模式自动压缩exe程序,自动把exe复制到另外的目录。
要复制到另外目录,需要在源程序里加上////copyto
如果不是复制到ini里的默认目录,则是////copyto=yourdir

( lastupdate:20070708 最新文章请访问http://www.d-programming-language-china.org )

关于一大步成功社区:
yidabu提倡在交流中学习,在分享中提高
收集感兴趣的知识,写下心得,通过网络与别人一起分享
理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的
网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台

TOP

这个是您写的编仪器????
告诉到底怎么用啊!我安了写编译器就是不知道怎么用!

TOP

即将发布SciTE4d , 其中整合了ybud, 实现一键编译, 但是基于DSSS, 必须会熟练使用DSSS

TOP

发新话题