b56eb86b5d932f72333eac60d97f5d4dbe1156bb
[mass-build.git] / kdebuildpy.py
1 #!/usr/bin/python
2 import vcs, build_system, imp
3 import argparse, os, sys, subprocess
4 from collections import OrderedDict
5
6 # read command-line arguments
7 parser = argparse.ArgumentParser(description='Build KDE')
8 parser.add_argument("-c, --config",
9                     dest="config", default="config.py",
10                     help="kdebuildpy config file")
11 parser.add_argument("--reconfigure",
12                     action="store_true", dest="reconfigure",
13                     help="Force configuration to be run")
14 parser.add_argument("--phases", choices=["update", "configure", "compile"], nargs='*', metavar='PHASE',
15                     dest="phases", default=["update", "configure", "compile"],
16                     help="For each module, run the given phases in the given order. Possible phases are: update, configure, compile")
17 parser.add_argument("--resume-from", metavar='MODULE',
18                     dest="resume_from",
19                     help="Resume building from the given repository")
20 parser.add_argument("modules",  metavar='MODULE', nargs='*',
21                     help="Manually specify modules to be built")
22 args = parser.parse_args()
23
24 # load config
25 config = imp.load_source('config', args.config).__dict__
26 os.remove(args.config+'c') # remove compiled python file
27 projects = OrderedDict() # all projects
28 workProjects = [] # projects we work on
29
30 # an entire Project
31 class Project:
32         def __init__(self, config, folder, module):
33                 self.folder = folder
34                 self.name = module['name']
35                 # VCS
36                 vcsName = module.get('vcs', 'kde+git')
37                 if vcsName == 'kde+git':
38                         self.vcs = vcs.KDEGit(self.sourceFolder(), module['name'], module['version'])
39                 elif vcsName == 'kde+svn':
40                         self.vcs = vcs.KDESVN(self.sourceFolder(), module['svn-path'])
41                 else:
42                         raise Exception("Unknown VCS type "+vcsName)
43                 # build system
44                 if config.get('buildDeb', False):
45                         self.buildSystem = build_system.AutoDebuild(self.sourceFolder(), self.buildFolder(), module, self.vcs, config)
46                 else:
47                         buildSystemName = module.get('build-system', 'cmake')
48                         if buildSystemName == 'cmake':
49                                 self.buildSystem = build_system.CMake(self.sourceFolder(), self.buildFolder(), module, config)
50                         else:
51                                 raise Exception("Unknown build system type "+buildSystemName)
52         
53         def sourceFolder(self):
54                 return os.path.join(self.folder, self.name)
55         
56         def buildFolder(self):
57                 return os.path.join(config['buildDir'], self.sourceFolder())
58
59 # return the position of the given item in the list
60 def findInList(list, item):
61         for i in xrange(len(list)):
62                 if list[i] == item:
63                         return i
64         raise Exception("%s not found in list" % str(item))
65
66 # populate list of projects
67 def loadProjects(config, modules, folder=''):
68         for module in modules:
69                 if 'folder' in module: # a subpath
70                         loadProjects(config, module['modules'], os.path.join(folder, module['folder']))
71                 else: # a proper project
72                         if module['name'] in projects:
73                                 raise Exception("Duplicate module name "+module['name'])
74                         projects[module['name']] = Project(config, folder, module)
75
76 # now check what we have to do
77 loadProjects(config, config['modules'])
78 if args.modules:
79         if args.resume_from is not None:
80                 raise Exception("Can not use --resume-from and manually specify modules")
81         for module in args.modules:
82                 if not module in projects:
83                         raise Exception("Project %s does not exist" % module)
84                 workProjects.append(projects[module])
85 elif args.resume_from is None:
86         workProjects = projects.values() # all the projects
87 else:
88         if not args.resume_from in projects:
89                 raise Exception("Project %s does not exist" % args.resume_from)
90         startWith = projects[args.resume_from]
91         startIndex = findInList(projects.values(), startWith)
92         workProjects = projects.values()[startIndex:]
93
94 # and do it!
95 for project in workProjects:
96         try:
97                 for phase in args.phases:
98                         if phase == 'update':
99                                 print "Updating",project.sourceFolder()
100                                 project.vcs.update()
101                         elif phase == 'configure':
102                                 print "Configuring",project.sourceFolder()
103                                 project.buildSystem.configure(force=args.reconfigure)
104                         elif phase == 'compile':
105                                 print "Compiling",project.sourceFolder()
106                                 project.buildSystem.build()
107                                 print "Installing",project.sourceFolder()
108                                 project.buildSystem.install()
109                         else:
110                                 raise Exception("Invalid phase "+phase)
111         except (subprocess.CalledProcessError, KeyboardInterrupt) as e:
112                 print >> sys.stderr
113                 print >> sys.stderr
114                 if isinstance(e, KeyboardInterrupt): # str(e) would be the empty string
115                         print >> sys.stderr, "Interruped by user while processing %s" % (project.name)
116                 else:
117                         print >> sys.stderr, "Error while processing %s: %s" % (project.name, str(e))
118                 print >> sys.stderr
119                 sys.exit(1)