fix windows build after depslog
[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'] + conf_args)
131     run(['./' + binary] + verbose)
132
133     # Copy the new executable over the bootstrap one.
134     shutil.copyfile('ninja.exe', binary)
135
136     # Clean up.
137     for obj in glob.glob('*.obj'):
138         os.unlink(obj)
139
140     print("""
141 Done!
142
143 Note: to work around Windows file locking, where you can't rebuild an
144 in-use binary, to run ninja after making any changes to build ninja itself
145 you should run ninja.bootstrap instead.""")
146 else:
147     print('Building ninja using itself...')
148     run([sys.executable, 'configure.py'] + conf_args)
149     run(['./' + binary] + verbose)
150     os.unlink(binary)
151     print('Done!')