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