source: 2014/24/build_games.py @ 8315

Revision 5036, 6.4 KB checked in by anlakane, 5 years ago (diff)
Line 
1# -*- coding: latin-1 -*-
2"""
3Builds all the .csproj-projects in all subdirectories, copies
4compiled games to directory games and optionally writes the
5results of the build.
6"""
7
8from __future__ import with_statement
9import sys
10import os
11from os.path import *
12import shutil
13from shutil import *
14from glob import *
15from subprocess import *
16from datetime import *
17import re
18
19no_pong = False
20should_write_results = True
21
22output_dir = abspath("pelit")
23build_result_dir = abspath("build")
24lib_dir_x86 = abspath("lib")
25personal_dirs = [d for d in os.listdir(".") if isdir(d) and d not in ("lib", basename(output_dir), ".svn")]
26projects_that_did_not_build = []
27users_that_did_not_build = []
28msbuild = "msbuild"
29
30
31
32def check_requirements():
33    global msbuild
34    if not exists("lib\\Jypeli.dll"):
35        raise Exception("lib\\Jypeli.dll expected")
36    return_code = call(msbuild + " /? 1> NUL 2> NUL", shell=True)
37    if return_code != 0:
38        msbuild = join(os.getenv("SystemRoot"), "Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe")
39        if not exists(msbuild):
40            raise Exception("MSBuild not found in " + msbuild)
41
42
43def create_output_directory():
44    if not exists(output_dir):
45        os.mkdir(output_dir)
46    for d in personal_dirs:
47        if not exists(join(output_dir, d)):
48            os.mkdir(join(output_dir, d))
49
50def create_build_result_directory():
51    if not exists(build_result_dir):
52        os.mkdir(build_result_dir)
53
54
55def parse_last_changed_date(svn_info_output):
56    match = re.search("Last Changed Date: (\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d) (\\d\\d):(\\d\\d)", svn_info_output)
57    if not match:
58        #raise Exception("Last Changed Date not found from svn info output!")
59        return datetime(year=2000, month=1, day=1, hour=0, minute=0)
60    year = int(match.group(1))
61    month = int(match.group(2))
62    day = int(match.group(3))
63    hour = int(match.group(4))
64    minute = int(match.group(5))
65    return datetime(year=year, month=month, day=day, hour=hour, minute=minute)
66
67
68def build_games():
69    for d in personal_dirs:
70        path = abspath(d)
71        time = datetime(2000, 1, 1)
72        if should_write_results and exists(join(path, ".svn")):
73            call("svn update " + path, shell=True)
74        outputs = Popen("svn info " + path, stdout=PIPE).communicate()
75        time = parse_last_changed_date(outputs[0])
76        try:
77            build_games_in_personal_dir(path, time)
78        except Exception, e:
79            print
80            print "NOT SUCCESSFUL FOR USER ", d, ": ", e
81            users_that_did_not_build.append(d)
82
83
84counter = 1
85
86
87def get_weekday_name(n):
88    if n == 0: return "Maanantai"
89    if n == 1: return "Tiistai"
90    if n == 2: return "Keskiviikko"
91    if n == 3: return "Torstai"
92    if n == 4: return "Perjantai"
93    if n == 5: return "Lauantai"
94    if n == 6: return "Sunnuntai"
95    raise Exception("Invalid weekday number")
96
97
98def write_result(author, name, success, last_changed_date):
99    global counter
100    with open(join(build_result_dir, str(counter)+".txt"), "w") as f:
101        f.write(author+"\n")
102        f.write(name+"\n")
103        result = "success"
104        if not success:
105            result = "fail"
106        f.write(result+"\n")
107        formatted_time = get_weekday_name(last_changed_date.weekday()) + last_changed_date.strftime(" %H:%M")
108        f.write(formatted_time+"\n")
109    counter += 1
110
111
112def build_games_in_personal_dir(personal_dir, last_changed_date):
113    for root, dirs, files in os.walk(personal_dir):
114        if '.svn' in dirs:
115            dirs.remove('.svn')
116        # projects = glob(join(root, '*.csproj'))
117        projects = glob(join(root, '*.csproj'))
118        if projects:
119            if len(projects) > 1:
120                print "NOTE: There is more than one project file in", root
121
122            try:
123                project_name = splitext(basename(projects[0]))[0]
124                author = basename(personal_dir)
125
126                if re.search("consoleapplication", project_name, flags=re.IGNORECASE):
127                    continue
128
129                if no_pong and re.search("^pong", project_name, flags=re.IGNORECASE):
130                    continue
131
132                success = build(projects[0])
133
134                if should_write_results:
135                    write_result(author, project_name, success, last_changed_date)
136
137                if success:
138                    dst_dir = join(output_dir, author)
139                    copy_game(project_name, root, dst_dir)
140                    print author + ": " + project_name
141                else:
142                    projects_that_did_not_build.append(projects[0])
143            except Exception, e:
144                print
145                print "PROJECT CAUSED EXCEPTION:", project_name, " :", e
146                projects_that_did_not_build.append(projects[0])
147
148
149def build(project_file_path):
150    build_cmd = msbuild + ' /nologo /verbosity:quiet /p:XnaProfile=Reach /p:Configuration=Release /p:"ReferencePath=%s" /t:Build "%s"' % (lib_dir_x86, project_file_path)
151    return call(build_cmd, shell=True) == 0
152
153
154def copy_game(project_name, project_dir, dst_dir):
155    bin = join(project_dir, "bin\\x86\\Release")
156    if not exists(bin):
157        print "NO BIN DIR FOUND IN", project_dir
158    dst = join(dst_dir, project_name)
159    if exists(dst):
160        rmtree(dst)
161    copytree(bin, dst, ignore=shutil.ignore_patterns('.svn', '*.pdb', 'jypeli.xml'))
162
163
164def parse_arguments():
165    for arg in sys.argv[1:]:
166        if arg == "--write-results":
167            global should_write_results
168            should_write_results = True
169        elif arg == "--no-pong":
170            global no_pong
171            no_pong = True
172        else:
173            raise Exception("Unknown argument: " + arg)
174
175
176def main():
177    try:
178        parse_arguments()
179        check_requirements()
180        create_output_directory()
181        if should_write_results: create_build_result_directory()
182        build_games()
183    except KeyboardInterrupt:
184        print "BUILD CANCELLED"
185    except Exception, e:
186        print
187        print "NOT SUCCESSFUL:", e
188        return 1
189
190    print 'Build failed for users (%d):' % len(users_that_did_not_build)
191    for p in users_that_did_not_build:
192        print p
193
194    print
195    print 'Build failed for projects (%d):' % len(projects_that_did_not_build)
196    for p in projects_that_did_not_build:
197        print p
198
199
200if __name__ == '__main__':
201    sys.exit(main())
Note: See TracBrowser for help on using the repository browser.