• 用python写makefile


    温馨提示:阅读本文的同学最好能了解makefile和python的编写规则。

    不懂的同学能够先保存在收藏夹。以便日后查看。

    事实上之前我一直非常懒,我不想了解makefile规则。由于在linux下开发我一直使用Qt creator。(非常多时候正是一些“懒人”的创造力。解放了我们的双手,显然如今我们还须要用双手写makefile)。Qt creator是一个非常好的IDE。并且能够跨平台开发。可是相比VS,显然还是不够优秀。

    因此非常多开发人员都会选择在Windows下开发C/C++程序,然后部署在Linux下运行。当然我也不例外。所以近期花了几个晚上了解makefile的编写规则。

    開始的时候。我參照网上一些makefile的样例,写了一个初版的makefile。然而这个makefile在编译我的project的时候报错。

    主要出错体如今:

    %.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是根据.proproject文件生成的)。而这个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.endswith(SUFFIX) > 0: 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 + " "); f.write("CXX = " + CXX + " "); f.write("INCPATH = " + INCPATH + " "); f.write("LIBS = " + LIBS + " "); f.write("BINDIR = " + BINDIR +" "); f.write("OBJDIR = " + OBJDIR + " "); f.write("BIN = " + BIN + " "); f.write("SOURCES = " + SOURCES+ " "); f.write("SOURCEFILES = $(notdir $(SOURCES)) "); f.write("OBJECTS = $(addprefix $(OBJDIR), $(patsubst %.cpp,%.o,$(SOURCEFILES))) "); f.write("FLAGS = " + FLAGS + " "); f.write(" "); f.write("all:makedir $(OBJECTS) "); f.write(" $(CXX) $(FLAGS) $(INCPATH) -o $(BIN) $(OBJECTS) $(LIBS); "); f.write(" "); f.write("makedir: "); f.write(' $(shell if [ -n "$(OBJDIR)" -a ! -e "$(OBJDIR)" ];then mkdir -p $(OBJDIR); fi) '); f.write(' $(shell if [ -n "$(BINDIR)" -a ! -e "$(BINDIR)" ];then mkdir -p $(BINDIR); fi) '); f.write(" "); for val in OBJ2SRC: f.write(val[0] + ":" + val[1] +" "); f.write(" rm -f $@ "); f.write(" $(CXX) -fpic -c $(INCPATH) $< -o $@ "); f.write(" "); f.close(); os.system("make"); os.system("mv " + BIN + " " + BINDIR); os.system("cd " + OBJDIR + ";rm -f *.o");


    怎样编写makefile和python,这里不作说明。由于这篇文章不是makefile和python的教程。下面要说明的是SearchFiles函数。

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

     

    这是我要编译的project。当然截图仅仅是其中一部分。

    这个project须要包括的文件除了在DatabaseServer下,还要包括在../common其中(脚本中代码WD.append(ROOTPATH + "/common");)。

    我截图是为了证明。这个脚本是可行的。有人可能会说为什么不写一个測试样例。

    事实上我想说。非常多时候要弄懂一些技术。动手去做或许是最好的方法。假设你有什么问题,欢迎与我讨论!

     

  • 相关阅读:
    Android Studio下载及离线升级方法
    动态调用WebService
    哈哈哈 终于通过自己的努力 把这个模板上长毛的土豆去掉了
    关于“只有注册用户登录后才能阅读该文”
    SQL Server 2008 R2——根据数据查找表名和字段名 根据脏数据定位表和字段
    Windows驱动——虚拟机 虚拟串口 双机调试
    协议——如何制作一个简易的串口通信协议
    问题解决——复合检测项目的定义和使用
    算法——成语首尾接龙 成语接龙
    C++基础——函数指针 函数指针数组
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5360998.html
Copyright © 2020-2023  润新知