设为首页 收藏本站
查看: 3250|回复: 0

[经验分享] 用python写makefile

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-6-18 08:46:16 | 显示全部楼层 |阅读模式
温馨提示:阅读本文的同学最好能了解makefile和python的编写规则。不懂的同学可以先保存在收藏夹,以便日后查看。


其实之前我一直很懒,我不想了解makefile规则,因为在linux下开发我一直使用Qt creator。(很多时候正是一些“懒人”的创造力,解放了我们的双手,显然现在我们还需要用双手写makefile)。Qt creator是一个很好的IDE,而且可以跨平台开发。但是相比VS,显然还是不够优秀。因此很多开发者都会选择在Windows下开发C/C++程序,然后部署在Linux下执行。当然我也不例外。所以最近花了几个晚上了解makefile的编写规则。

开始的时候,我参照网上一些makefile的例子,写了一个初版的makefile。然而这个makefile在编译我的工程的时候报错。

主要出错体现在:

%.o: %.cpp

    $(CXX) -fpic -c $(INCPATH) $< -o $@

当然可以写成

$(objdir)/%.o:$(srcdir)/%.cpp

    $(CXX) -fpic -c $(INCPATH) $< -o $@

原因在于:

1、.o文件与.cpp文件处于不同的目录下。

2、不同的.o文件或不同的.cpp文件处于不同的目录下。

这时我找到两种解决方法:

1、就是用VPATH这个特殊变量,但是我不可能将所有要包含的目录都一一手动包含进来,于是我放弃。

2、就是把所有的编译规则列举出来。

我最终选择第二种解决方法。因为之前遇到这个困难时,我特意去了解Qt生成的makefile(其实这个makefile是依据.pro工程文件生成的)。而这个makefile正是将所有的编译规则都列举出来。于是就有下面这个python脚本。其实开始的时候我想用shell来做这一步工作的,但是我看到sed和awk,我头都晕,之前还一直抵触学习sed和awk。因此最后选择了python。

    #encoding: utf-8  
      
    import os  
    import os.path  
    import sys  
      
    #sys.exit(0);  
    #########################################################################################################################  
    #  
    #   本脚本的作用是:通过配置必要的信息,用python来生成makefile。(技术支持:www.guimigame.com)  
    #   @FILENAME       执行脚本输出makefile文件名  
    #   @BIN            生成可执行文件名  
    #   @SUFFIX         源文件后缀  
    #   @ROOTPATH       “根”目录路径(脚本工作目录的上一层)  
    #   @PWD            当前工作目录  
    #   @WD             工作目录,如果程序有多个工作目录请一一用append加上  
    #   @BINDIR         可执行文件输出目录  
    #   @OBJDIR         中间文件输出目录  
    #   @INCROOTPATH    头文件包含路径的“根路径”,方便INCPATH的编写  
    #   @LIBROOTPATH    包含库的“根”路径,方便LIBS的编写  
    #   @INCPATH        头文件包含路径  
    #   @SYSLIBS        包含的系统库  
    #   @LIBS           编译程序需要包含的库  
    #   @CXX            一般填写gcc/g++  
    #   @FLAGS          gcc/g++的编译标志  
    #  
    #########################################################################################################################  
    FILENAME    = 'makefile';  
    BIN         = "DatabaseServer";  
    SUFFIX      = ".cpp";  
      
    ROOTPATH    = os.path.dirname(os.path.dirname(os.path.abspath(__file__)));  
    PWD         = os.getcwd();  
      
    WD          = [];  
    WD.append(PWD);  
    WD.append(ROOTPATH + "/common");  
      
      
    BINDIR      = PWD + "/Bin/";  
    OBJDIR      = BINDIR + "obj/";  
      
    INCROOTPATH = "-I " + ROOTPATH;  
    LIBROOTPATH = "-L " + ROOTPATH;  
      
    INCPATH     = INCROOTPATH + "/common" + " " + INCROOTPATH + "/lib/include";  
    SYSLIBS     = " -lmysqlclient -lpthread"  
    LIBS        = LIBROOTPATH + "/lib/linux " + "-lTimeManager -lServerConfig -lGameSocket -lCommon -lTinyxml" + SYSLIBS;  
    CXX         = "g++";  
    FLAGS       = '-g -Wall';  
      
    #########################################################################################################################  
    #  
    #   以下不需要再配置  
    #  
    #########################################################################################################################  
      
    OBJFILE     = '';  
    OBJ2SRC     = [];  
      
    SOURCES     = "";  
      
    def SearchFiles(path):  
        global OBJFILE;  
        global OBJ2SRC;  
        global SOURCES;  
        global SUFFIX;  
        listFile = os.listdir(path);  
        for file in listFile:  
            if os.path.isdir(os.path.join(path, file)):  
                SearchFiles(os.path.join(path, file));  
            elif file.find(SUFFIX) > 0:  
                if file.find(SUFFIX + "~") > 0:  
                    continue;  
                OBJFILE = file;  
                OBJFILE = OBJFILE.replace(SUFFIX,'.o');  
                OBJ2SRC.append([OBJDIR + OBJFILE,path + "/" + file]);  
                SOURCES += path + "/" + file + " ";  
              
    for dir in WD:  
        SearchFiles(dir);  
      
    if os.path.exists(FILENAME):  
        os.remove(FILENAME);  
      
    f = open(FILENAME,'w');  
      
    f.write("PWD                = " + PWD + "\n");  
    f.write("CXX                = " + CXX + "\n");  
    f.write("INCPATH            = " + INCPATH + "\n");  
    f.write("LIBS               = " + LIBS + "\n");  
    f.write("BINDIR             = " + BINDIR +"\n");  
    f.write("OBJDIR             = " + OBJDIR + "\n");  
    f.write("BIN                = " + BIN + "\n");  
    f.write("SOURCES            = " + SOURCES+ "\n");  
    f.write("SOURCEFILES        = $(notdir $(SOURCES))\n");  
    f.write("OBJECTS            = $(addprefix $(OBJDIR), $(patsubst %.cpp,%.o,$(SOURCEFILES)))\n");  
    f.write("FLAGS              = " + FLAGS + "\n");  
    f.write("\n");  
      
    f.write("all:makedir $(OBJECTS)\n");  
    f.write("   $(CXX) $(FLAGS) $(INCPATH) -o $(BIN) $(OBJECTS) $(LIBS);\n");  
    f.write("\n");  
      
    f.write("makedir:\n");  
    f.write('   $(shell if [ -n "$(OBJDIR)" -a ! -e "$(OBJDIR)" ];then mkdir -p $(OBJDIR); fi)\n');  
    f.write('   $(shell if [ -n "$(BINDIR)" -a ! -e "$(BINDIR)" ];then mkdir -p $(BINDIR); fi)\n');  
    f.write("\n");   
      
    for val in OBJ2SRC:  
        f.write(val[0] + ":" + val[1] +"\n");  
        f.write("   rm -f $@\n");  
        f.write("   $(CXX) -fpic -c $(INCPATH) $< -o $@\n");  
        f.write("\n");  
      
    f.close();  
      
    os.system("make");  
    os.system("mv " + BIN + " " + BINDIR);  
    os.system("cd " + OBJDIR + ";rm -f *.o");  



如何编写makefile和python,这里不作说明。因为这篇文章不是makefile和python的教程。以下要说明的是SearchFiles函数。

通过遍历之前设定的工程工作目录,调用SearchFiles遍历该目录下所有的源文件(.cpp),及设定目标文件(.o)的绝对路径,最终是tuple的形式保存到OBJ2SRC数组中;还有的是将所有源文件保存在SOURCES中。当然这个过程中会递归遍历所有子目录,查找到所有的源文件。最终在for val in OBJ2SRC:遍历所有的数据;列出所有的源文件(.cpp)生成所对应的目标文件(.o),将编译规则写进makefile。
SouthEast.jpg

这是我要编译的工程,当然截图只是其中一部分。这个工程需要包含的文件除了在DatabaseServer下,还要包含在../common当中(脚本中代码WD.append(ROOTPATH + "/common");)。我截图是为了证明,这个脚本是可行的。有人可能会说为什么不写一个测试例子。其实我想说,很多时候要弄懂一些技术,动手去做也许是最好的方法。如果你有什么问题,欢迎与我讨论!





运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-20758-1-1.html 上篇帖子: Python模拟HTTP Post上传文件 下篇帖子: 使用命令xrandr设置当前系统的显示分辨率及显示的旋转脚本 python
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表