Merge pull request #499 from lht/patch-1
[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 # TODO: make this --platform to match configure.py.
35 parser.add_option('--windows', action='store_true',
36                   help='force native Windows build (when using Cygwin Python)',
37                   default=sys.platform.startswith('win32'))
38 (options, conf_args) = parser.parse_args()
39
40 def run(*args, **kwargs):
41     returncode = subprocess.call(*args, **kwargs)
42     if returncode != 0:
43         sys.exit(returncode)
44
45 # Compute system-specific CFLAGS/LDFLAGS as used in both in the below
46 # g++ call as well as in the later configure.py.
47 cflags = os.environ.get('CFLAGS', '').split()
48 ldflags = os.environ.get('LDFLAGS', '').split()
49 if sys.platform.startswith('freebsd'):
50     cflags.append('-I/usr/local/include')
51     ldflags.append('-L/usr/local/lib')
52
53 print('Building ninja manually...')
54
55 try:
56     os.mkdir('build')
57 except OSError:
58     e = sys.exc_info()[1]
59     if e.errno != errno.EEXIST:
60         raise
61
62 sources = []
63 for src in glob.glob('src/*.cc'):
64     if src.endswith('test.cc') or src.endswith('.in.cc'):
65         continue
66     if src.endswith('bench.cc'):
67         continue
68
69     filename = os.path.basename(src)
70     if filename == 'browse.cc':  # Depends on generated header.
71         continue
72
73     if options.windows:
74         if src.endswith('-posix.cc'):
75             continue
76     else:
77         if src.endswith('-win32.cc'):
78             continue
79
80     sources.append(src)
81
82 if options.windows:
83     sources.append('src/getopt.c')
84
85 vcdir = os.environ.get('VCINSTALLDIR')
86 if vcdir:
87     if options.x64:
88         cl = [os.path.join(vcdir, 'bin', 'x86_amd64', 'cl.exe')]
89         if not os.path.exists(cl[0]):
90             cl = [os.path.join(vcdir, 'bin', 'amd64', 'cl.exe')]
91     else:
92         cl = [os.path.join(vcdir, 'bin', 'cl.exe')]
93     args = cl + ['/nologo', '/EHsc', '/DNOMINMAX']
94 else:
95     args = shlex.split(os.environ.get('CXX', 'g++'))
96     cflags.extend(['-Wno-deprecated',
97                    '-DNINJA_PYTHON="' + sys.executable + '"',
98                    '-DNINJA_BOOTSTRAP'])
99     if options.windows:
100         cflags.append('-D_WIN32_WINNT=0x0501')
101         conf_args.append("--platform=mingw")
102     if options.x64:
103         cflags.append('-m64')
104 args.extend(cflags)
105 args.extend(ldflags)
106 binary = 'ninja.bootstrap'
107 if options.windows:
108     binary = 'ninja.bootstrap.exe'
109 args.extend(sources)
110 if vcdir:
111     args.extend(['/link', '/out:' + binary])
112 else:
113     args.extend(['-o', binary])
114
115 if options.verbose:
116     print(' '.join(args))
117
118 try:
119     run(args)
120 except:
121     print('Failure running:', args)
122     raise
123
124 verbose = []
125 if options.verbose:
126     verbose = ['-v']
127
128 if options.windows:
129     print('Building ninja using itself...')
130     run([sys.executable, 'configure.py', '--with-ninja=%s' % binary] +
131         conf_args)
132     run(['./' + binary] + verbose)
133
134     # Copy the new executable over the bootstrap one.
135     shutil.copyfile('ninja.exe', binary)
136
137     # Clean up.
138     for obj in glob.glob('*.obj'):
139         os.unlink(obj)
140
141     print("""
142 Done!
143
144 Note: to work around Windows file locking, where you can't rebuild an
145 in-use binary, to run ninja after making any changes to build ninja itself
146 you should run ninja.bootstrap instead.  Your build is also configured to
147 use ninja.bootstrap.exe as the MSVC helper; see the --with-ninja flag of
148 the --help output of configure.py.""")
149 else:
150     print('Building ninja using itself...')
151     run([sys.executable, 'configure.py'] + conf_args)
152     run(['./' + binary] + verbose)
153     os.unlink(binary)
154     print('Done!')