温馨提示:阅读本文的同学最好能了解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 + "\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函数。

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

 

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

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

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

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

用python写makefile的更多相关文章

  1. 如何自己编译apue.3e中代码 & 学习写makefile

    本来是搜pthread的相关资料,看blog发现很多linux程序员都看的一本神书<APUE>,里面有系统的两章内容专门讲pthread(不过是用c语言做的代码示例,这个不碍事,还是归到原 ...

  2. Python写各大聊天系统的屏蔽脏话功能原理

    Python写各大聊天系统的屏蔽脏话功能原理 突然想到一个视频里面弹幕被和谐的一满屏的*号觉得很有趣,然后就想用python来试试写写看,结果还真玩出了点效果,思路是首先你得有一个脏话存放的仓库好到时 ...

  3. python写红包的原理流程包含random,lambda其中的使用和见简单介绍

    Python写红包的原理流程 首先来说说要用到的知识点,第一个要说的是扩展包random,random模块一般用来生成一个随机数 今天要用到ramdom中unifrom的方法用于生成一个指定范围的随机 ...

  4. 怎么写makefile?(转)

    跟我一起写 Makefile 陈皓 第一章.概述 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和 pr ...

  5. Python写地铁的到站的原理简易版

    Python地铁的到站流程及原理(个人理解) 今天坐地铁看着站牌就莫名的想如果用Python写其工作原理 是不是很简单就小试牛刀了下大佬们勿喷纯属小弟个人理解 首先来看看地铁上显示的站牌如下: 就想这 ...

  6. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  7. 跟我一起写 Makefile

    转自 陈皓 的博客:http://blog.csdn.net/haoel/article/details/2886 1. 概述 2. 关于程序的编译和链接 3. Makefile 介绍 4. Make ...

  8. 【转载】Linux下makefile详解--跟我一起写 Makefile

    概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...

  9. 读书笔记汇总 --- 用Python写网络爬虫

    本系列记录并分享:学习利用Python写网络爬虫的过程. 书目信息 Link 书名: 用Python写网络爬虫 作者: [澳]理查德 劳森(Richard Lawson) 原版名称: web scra ...

随机推荐

  1. 移动端和web端前端UI库—Frozen UI、WeUI、SUI Mobile

    web http://www.pintuer.com/ 拼图 http://www.h-ui.net/ http://www.layui.com/  很厉害的一个个人产品 http://amazeui ...

  2. [转] 苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文

    转自holydancer的CSDN专栏,原文地址:http://blog.csdn.net/holydancer/article/details/9219333 首先得描述一下各个证书的定位,作用,这 ...

  3. 第二百三十五天 how can I 坚持

    其实昨天听遗憾的,尽头看了新闻,有好多人都出去赏雪了,可惜了,最遗憾的是没有叫上你一块去. 晚上喝了点酒,抽了两根烟,以前基本不喝酒,就别提抽烟了,陈小春的<算你狠>,该如何是好. 经常在 ...

  4. c++10 Seattle Clang error

    升级到C++Builder RAD 10 Settle 一些错误解决方法,使用LLVM  CLang编译器,BCC32C http://docwiki.embarcadero.com/RADStudi ...

  5. Quora 用了哪些技术(转)

    原文:http://dbanotes.net/arch/quora_tech.html 很多团队都在学习.研究 Quora .前段时间看到这篇 Quora’s Technology Examined  ...

  6. ubuntu下设置开机自动挂载硬盘

    我们在linux中常常用mount命令把硬盘分区或者光盘挂载到文件系统中./etc/fstab就是在开机引导的时候自动挂载到linux的文件系统. 如果给计算机配了一块新磁盘,已经分区,格式化,挂载, ...

  7. 关于iTunes11.1 不能刷自制固件的解决方案

    由于iTunes升级到11.1后, 苹果在程序里限制了不允许刷自制固件, 所以想刷自制固件暂时只能降级iTunes到11.1版本之前, 这里提供iTunes 11.0.5 的下载地址: Windows ...

  8. CodeForces 709B Checkpoints (数学,最短路)

    题意:给定你的坐标,和 n 个点,问你去访问至少n-1个点的最短路是多少. 析:也是一个很简单的题,肯定是访问n-1个啊,那么就考虑从你的位置出发,向左访问和向右访问总共是n-1个,也就是说你必须从1 ...

  9. 数据库:mongodb与关系型数据库相比的优缺点

      与关系型数据库相比,MongoDB的优点:①弱一致性(最终一致),更能保证用户的访问速度:举例来说,在传统的关系型数据库中,一个COUNT类型的操作会锁定数据集,这样可以保证得到“当前”情况下的精 ...

  10. Java Service Wrapper配置详解

    #encoding=UTF-8 # Configuration files must begin with a line specifying the encoding # of the the fi ...