Merge pull request #458 from rgeary1/minor
[platform/upstream/ninja.git] / bootstrap.py
1 #!/usr/bin/env python
2 # Copyright 2011 Google Inc. All Rights Reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from __future__ import print_function
17
18 from optparse import OptionParser
19 import sys
20 import os
21 import glob
22 import errno
23 import shlex
24 import shutil
25 import subprocess
26
27 os.chdir(os.path.dirname(os.path.abspath(__file__)))
28
29 parser = OptionParser()
30 parser.add_option('--verbose', action='store_true',
31                   help='enable verbose build',)
32 parser.add_option('--x64', action='store_true',
33                   help='force 64-bit build (Windows)',)
34 (options, conf_args) = parser.parse_args()
35
36 def run(*args, **kwargs):
37     returncode = subprocess.call(*args, **kwargs)
38     if returncode != 0:
39         sys.exit(returncode)
40
41 # Compute system-specific CFLAGS/LDFLAGS as used in both in the below
42 # g++ call as well as in the later configure.py.
43 cflags = os.environ.get('CFLAGS', '').split()
44 ldflags = os.environ.get('LDFLAGS', '').split()
45 if sys.platform.startswith('freebsd'):
46     cflags.append('-I/usr/local/include')
47     ldflags.append('-L/usr/local/lib')
48
49 print('Building ninja manually...')
50
51 try:
52     os.mkdir('build')
53 except OSError:
54     e = sys.exc_info()[1]
55     if e.errno != errno.EEXIST:
56         raise
57
58 sources = []
59 for src in glob.glob('src/*.cc'):
60     if src.endswith('test.cc') or src.endswith('.in.cc'):
61         continue
62     if src.endswith('bench.cc'):
63         continue
64
65     filename = os.path.basename(src)
66     if filename == 'browse.cc':  # Depends on generated header.
67         continue
68
69     if sys.platform.startswith('win32'):
70         if src.endswith('-posix.cc'):
71             continue
72     else:
73         if src.endswith('-win32.cc'):
74             continue
75
76     sources.append(src)
77
78 if sys.platform.startswith('win32'):
79     sources.append('src/getopt.c')
80
81 vcdir = os.environ.get('VCINSTALLDIR')
82 if vcdir:
83     if options.x64:
84         cl = [os.path.join(vcdir, 'bin', 'amd64', 'cl.exe')]
85     else:
86         cl = [os.path.join(vcdir, 'bin', 'cl.exe')]
87     args = cl + ['/nologo', '/EHsc', '/DNOMINMAX']
88 else:
89     args = shlex.split(os.environ.get('CXX', 'g++'))
90     cflags.extend(['-Wno-deprecated',
91                    '-DNINJA_PYTHON="' + sys.executable + '"',
92                    '-DNINJA_BOOTSTRAP'])
93     if sys.platform.startswith('win32'):
94         cflags.append('-D_WIN32_WINNT=0x0501')
95     if options.x64:
96         cflags.append('-m64')
97 args.extend(cflags)
98 args.extend(ldflags)
99 binary = 'ninja.bootstrap'
100 if sys.platform.startswith('win32'):
101     binary = 'ninja.bootstrap.exe'
102 args.extend(sources)
103 if vcdir:
104     args.extend(['/link', '/out:' + binary])
105 else:
106     args.extend(['-o', binary])
107
108 if options.verbose:
109     print(' '.join(args))
110
111 try:
112     run(args)
113 except:
114     print('Failure running:', args)
115     raise
116
117 verbose = []
118 if options.verbose:
119     verbose = ['-v']
120
121 if sys.platform.startswith('win32'):
122     print('Building ninja using itself...')
123     run([sys.executable, 'configure.py', '--with-ninja=%s' % binary] +
124         conf_args)
125     run(['./' + binary] + verbose)
126
127     # Copy the new executable over the bootstrap one.
128     shutil.copyfile('ninja.exe', binary)
129
130     # Clean up.
131     for obj in glob.glob('*.obj'):
132         os.unlink(obj)
133
134     print("""
135 Done!
136
137 Note: to work around Windows file locking, where you can't rebuild an
138 in-use binary, to run ninja after making any changes to build ninja itself
139 you should run ninja.bootstrap instead.  Your build is also configured to
140 use ninja.bootstrap.exe as the MSVC helper; see the --with-ninja flag of
141 the --help output of configure.py.""")
142 else:
143     print('Building ninja using itself...')
144     run([sys.executable, 'configure.py'] + conf_args)
145     run(['./' + binary] + verbose)
146     os.unlink(binary)
147     print('Done!')