makefile太难了,学不会,自己用Python写个简单的构建工具

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/embinux/article/details/49180325

makefile 太复杂了,学的不精。自己用Python写一个构建工具,经过简单测试,可用



#!/usr/bin/env python  
# -*- coding: utf-8 -*-  
  
import sys  
import argparse  
import os  
import commands  
import re  
  
  
# .c对应的.o文件  
def obj_file_path(srcpath):  
    return srcpath[:-1] + 'o'  
  
  
# 检测.[hc]是否比.o文件新  
def is_newer_than(src, obj):  
    srcmtime = os.stat(src).st_mtime  
    if os.path.exists(obj):  
        objmtime = os.stat(obj).st_mtime  
    else:  
        objmtime = 0  
    return srcmtime > objmtime  
  
  
# 检查是否需要重新编译.c文件  
def need_compile_src(srcpath):  
    output = commands.getoutput('{} -MM {}'.format(cc, srcpath))  
    hlist = output.split(':')[1].strip().split(' ')  
    hfiles = [h for h in hlist if h.endswith('.h')]  
    objpath = obj_file_path(srcpath)

    # 检查依赖的头文件是否更新了
    for h in hfiles:  
        if is_newer_than(h, objpath):  
            return True

    # 检查源文件是否更新了
    if is_newer_than(srcpath, objpath):  
        return True
    
    # 检查配置文件是否更新了
    cfgpath = os.path.abspath('buildconfig')
    execpath = os.path.abspath(execname)
    if is_newer_than(cfgpath, execpath):
        return True

    return False  
      
  
# target build  
def build():  
    # compile  
    needlink = False  
    objfiles = []  
    for srcfile in srcfiles:  
        objfile = obj_file_path(srcfile)  
        objfiles.append(objfile)  
        if need_compile_src(srcfile):  
            needlink = True  
            cccmd = '{} {} -c {} -o {}'.format(cc, cflags, srcfile, objfile)  
            if not quiet:  
                print(cccmd)  
            if os.system(cccmd):  
                sys.exit(1)  
  
    # link  
    if needlink:  
        dependency = ''  
        for objfile in objfiles:  
            dependency += (' ' + objfile)  
        execpath = os.path.abspath(execname);  
        ldcmd = '{} {} {} -o {}'.format(cc, ldflags, dependency, execpath)  
        if not quiet:  
            print(ldcmd)  
        os.system(ldcmd)  
  
  
def remove_file(filepath):  
    if os.path.exists(filepath):  
        if not quiet:  
            print('rm {}'.format(filepath))  
        os.remove(filepath)  
  
  
# target clean  
def clean():  
    # remove obj files  
    for srcfile in srcfiles:  
        objfile = obj_file_path(srcfile)          
        remove_file(objfile)  
  
    # remove exec file  
    execpath = os.path.abspath(execname);  
    remove_file(execpath)  
  
  
# generate the buildconfig file  
def gen_buildconfig():  
    with open('buildconfig', 'w') as cfgfile:  
        cfgfile.writelines('''######## buildconfig ######## 
 
CC=cc                   # eg. cc/gcc/clang 
CFLAGS=-g 
LDFLAGS= 
EXECNAME=main 
 
''')  
  
  
# parse command line opthons  
def args_parser():  
    parser = argparse.ArgumentParser()  
    parser.add_argument('-c', '--config', action='store_true', help='create the buildconfig file')  
    parser.add_argument('-q', '--quiet', action='store_true', help='quiet')  
    parser.add_argument('target', nargs='?', choices=['build', 'clean'], default='build', help='build or clean.')  
    return parser  
  
  
# parse buildconfig file  
def parse_build_config():  
    variables = dict()  
    cfgpath = os.path.abspath('buildconfig');  
    if not os.path.exists(cfgpath):  
        print('先创建一个buildconfig文件')  
        parser.print_help()  
        sys.exit(2)  
  
    with open(cfgpath) as cfgfile:  
        pattern = re.compile(r'#.*$')      
        for line in cfgfile:  
            line = pattern.sub('', line)  
            line = line.strip()  
            pair = line.split('=')  
            if len(pair) == 2:  
                variables[pair[0].strip()] = pair[1].strip()  
    return variables  
  
  
# find all src files  
def src_file_list(srcdir, ext):  
    srcfiles = []  
    for dirpath, dirnames, filenames in os.walk(srcdir):  
        for filename in filenames:  
            fileext = os.path.splitext(filename)[1]  
            if fileext == '.' + ext:  
                srcpath = os.path.join(dirpath, filename)  
                srcfiles.append(srcpath)  
    return srcfiles  
  
  
# main entry  
if __name__ == '__main__':  
    parser = args_parser()  
  
    # parse args  
    args = parser.parse_args()  
    quiet = args.quiet  
    config = args.config  
    if config:  
        gen_buildconfig()  
        sys.exit(0)  
  
    # parse variables  
    variables = parse_build_config();  
    cc = variables.setdefault('CC', 'cc')  
    cflags = variables.setdefault('CFLAGS', '-g')  
    ldflags = variables.setdefault('LDFLAGS', '')  
    execname = variables.setdefault('EXECNAME', 'main')  
  
    # src files  
    srcfiles = src_file_list(os.getcwd(), 'c')  
      
    # make target  
    if args.target == 'build':  
        build()  
    elif args.target == 'clean':  
        clean()

        







使用演示




开启树莓派探索模式





                                    
展开阅读全文

没有更多推荐了,返回首页