自動化編譯工具

最近接手一個新的C++項目,寫了一個自動化編譯的腳本,包含單元測試的編譯與執行。

腳本文件:Compile.py

# encoding:utf-8
import os
import datetime
import xml.etree.ElementTree as ET


class Target:
    def __init__(self):
        self.name = ""
        self.build_dir = ""
        self.result_dir = ""
        self.target_type = ""
        self.bit = ""
        self.version = ""

    def __str__(self):
        return "name = %s, build_dir= %s, result_dir = %s, target_type = %s, bit = %s, version = %s"\
               % (self.name, self.build_dir, self.result_dir, self.target_type, self.bit, self.version)


def get_xml_dict(source_file, target_list, unittest_list):
    tree = ET.parse(source_file)
    root = tree.getroot()
    for child in root:
        if child.tag == "targets" and child.get("compile") == "True":
            for item in child:
                target = Target()
                target.name = item.get("name")
                target.build_dir = item.get("build_dir")
                target.result_dir = child.get("result_dir")
                target.target_type = item.get("target_type")
                target.bit = item.get("bit")
                target.version = item.get("version")
                target_list.append(target)
        elif child.tag == "unit_tests" and child.get("compile") == "True":
            for item in child:
                target = Target()
                target.name = item.get("name")
                target.build_dir = item.get("build_dir")
                target.result_dir = child.get("result_dir")
                target.target_type = item.get("target_type")
                target.bit = item.get("bit")
                target.version = item.get("version")
                unittest_list.append(target)
    return root.get("build_type"), root.get("svn_path"), root.get("svn_version"), root.get("result_dir")


def compile_target(build_type, target, result_file):
    print "Begin Compile Target: %s" % target.name

    root_dir = os.getcwd()
    os.chdir(target.build_dir)
    write_version_file(target.version)
    compile_file = "compile.bat"
    write_compile_file(compile_file, target.name, target.bit, build_type)
    ret = os.system(compile_file)

    os.chdir(root_dir)
    if ret != 0:
        result = "Failed"
    else:
        result = "Success"
    result_file.write("\nCompile %s %s.\n" % (target.name, result))


def pack(target, result_dir):
    result_dir = result_dir + "\\" + target.result_dir
    if not os.path.exists(result_dir):
        os.mkdir(result_dir)
    target_dir = result_dir + "\\" + target.name
    if not os.path.exists(target_dir):
        os.mkdir(target_dir)
    build_info_dir = target_dir + "\\build_info"
    if not os.path.exists(build_info_dir):
        os.mkdir(build_info_dir)

    if target.target_type == "dll":
        os.system("copy %s\\%s.dll %s" % (target.build_dir, target.name, target_dir))
        os.system("copy %s\\%s.lib %s" % (target.build_dir, target.name, target_dir))
    elif target.target_type == "exe":
        os.system("copy %s\\%s.exe %s" % (target.build_dir, target.name, target_dir))

    os.system("copy %s\\%s.pdb %s" % (target.build_dir, target.name, build_info_dir))
    os.system("copy %s\\%s_error.txt %s" % (target.build_dir, target.name, build_info_dir))


def exec_unittest(unittest_list, result_dir, result_file):
    total_size = len(unittest_list)
    if total_size == 0:
        return 0
    pass_count = 0
    fail_count = 0
    for unit_test in unittest_list:
        target_dir = result_dir + "\\" + unit_test.result_dir + "\\" + unit_test.name
        cmd = target_dir + "\\" + unit_test.name + ".exe"
        ret = os.system(cmd)
        if ret == 0:
            result = "passed"
            pass_count += 1
        else:
            result = "failed"
            fail_count += 1
        result_file.write("\nExec unittest %s %s" % (unit_test.name, result))
    result_file.write("\n\nExec %d unittest, %d passed, %d failed.\n\n" % (total_size, pass_count, fail_count))


def svn_check_out(svn_path, svn_version, result_dir):
    svn_path = svn_path.encode("gbk")
    if svn_version == "":
        cmd = "svn checkout %s ./" % svn_path
    else:
        cmd = "svn checkout %s ./ -r %s" % (svn_path, svn_version)

    os.system("svn info %s > %s\\svn_info.txt" % (svn_path, result_dir))
    os.system("echo %s >> %s\\svn_info.txt" % (cmd, result_dir))
    os.system(cmd)


def get_dest_dir():
    now = datetime.datetime.now()
    dest_dir = "%04d%02d%02d_%02d%02d%02d" % (now.year, now.month, now.day, now.hour, now.minute, now.second)
    return dest_dir


def write_version_file(version):
    version_items = version.split('.')
    print version_items
    version_file = open("../src/version.h", "w")
    version_file.write("#define MainVer %s\n" % version_items[0])
    version_file.write("#define SubVer %s\n" % version_items[1])
    version_file.write("#define PubVer %s\n" % version_items[2])
    version_file.write("#define BuildVer %s\n" % version_items[3])
    date_time = datetime.datetime.now()
    version_file.write("#define UpdateDate %04d%02d%02d\n" % (date_time.year, date_time.month, date_time.day))


def write_compile_file(compile_file, name, bit, build_type):
    env_cmd = 'call "%%VS_HOME%%/VC/vcvarsall.bat" %s\n' % bit
    cmake_cmd = 'cmake -DCMAKE_BUILD_TYPE=%s .. -G"NMake Makefiles"\n' % build_type
    nmake_cmd = 'nmake 2>>%s_error.txt\n' % name

    command_file = open(compile_file, "w")
    command_file.write(env_cmd)
    command_file.write(cmake_cmd)
    command_file.write(nmake_cmd)
    command_file.close()


def main():
    target_list = []
    unittest_list = []
    build_type, svn_path, svn_version, result_dir = get_xml_dict("compile.xml", target_list, unittest_list)

    root_dir = os.getcwd()
    dest_dir = get_dest_dir()
    os.mkdir(dest_dir)
    os.chdir(dest_dir)
    if not os.path.exists(result_dir):
        os.mkdir(result_dir)
    os.system("copy ..\\compile.xml %s" % result_dir)

    svn_check_out(svn_path, svn_version, result_dir)

    result_file_name = result_dir + '\\' + 'result.txt'
    result_file = open(result_file_name, mode="a")
    for item in target_list:
        compile_target(build_type, item, result_file)
        pack(item, result_dir)

    for item in unittest_list:
        compile_target(build_type, item, result_file)
        pack(item, result_dir)

    exec_unittest(unittest_list, result_dir, result_file)
    result_file.close()
    os.system("type %s" % result_file_name)

    os.chdir(root_dir)


if __name__ == '__main__':
    main()

配置文件:Compile.xml

<?xml version="1.0" encoding="utf-8"?>
<root build_type="debug" svn_path="svn://127.0.0.1/trunk/" svn_version="" result_dir="result">
	<targets result_dir="targets" compile="True">
		<target name="MDLL_SWSSL_Step" build_dir=".\target\MDLL_SWSSL_Step\build" target_type="dll" bit="x86" version="1.0.0.0"/>
	</targets>
	<unit_tests result_dir="unittests" compile="True">
		<unit_test name="MDLL_SWSSL_Step_test" build_dir=".\unittest\target\MDLL_SWSSL_Step_test\build" target_type="exe" bit="x86" version="1.0.0.0"/>
	</unit_tests>
</root>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章