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