Merge pull request #485 from petrh/fedora-rpmbuild
[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', 'amd64', 'cl.exe')]
89     else:
90         cl = [os.path.join(vcdir, 'bin', 'cl.exe')]
91     args = cl + ['/nologo', '/EHsc', '/DNOMINMAX']
92 else:
93     args = shlex.split(os.environ.get('CXX', 'g++'))
94     cflags.extend(['-Wno-deprecated',
95                    '-DNINJA_PYTHON="' + sys.executable + '"',
96                    '-DNINJA_BOOTSTRAP'])
97     if options.windows:
98         cflags.append('-D_WIN32_WINNT=0x0501')
99         conf_args.append("--platform=mingw")
100     if options.x64:
101         cflags.append('-m64')
102 args.extend(cflags)
103 args.extend(ldflags)
104 binary = 'ninja.bootstrap'
105 if options.windows:
106     binary = 'ninja.bootstrap.exe'
107 args.extend(sources)
108 if vcdir:
109     args.extend(['/link', '/out:' + binary])
110 else:
111     args.extend(['-o', binary])
112
113 if options.verbose:
114     print(' '.join(args))
115
116 try:
117     run(args)
118 except:
119     print('Failure running:', args)
120     raise
121
122 verbose = []
123 if options.verbose:
124     verbose = ['-v']
125
126 if options.windows:
127     print('Building ninja using itself...')
128     run([sys.executable, 'configure.py', '--with-ninja=%s' % binary] +
129         conf_args)
130     run(['./' + binary] + verbose)
131
132     # Copy the new executable over the bootstrap one.
133     shutil.copyfile('ninja.exe', binary)
134
135     # Clean up.
136     for obj in glob.glob('*.obj'):
137         os.unlink(obj)
138
139     print("""
140 Done!
141
142 Note: to work around Windows file locking, where you can't rebuild an
143 in-use binary, to run ninja after making any changes to build ninja itself
144 you should run ninja.bootstrap instead.  Your build is also configured to
145 use ninja.bootstrap.exe as the MSVC helper; see the --with-ninja flag of
146 the --help output of configure.py.""")
147 else:
148     print('Building ninja using itself...')
149     run([sys.executable, 'configure.py'] + conf_args)
150     run(['./' + binary] + verbose)
151     os.unlink(binary)
152     print('Done!')