blob: 72db0c4c1085fd6e5eb27bf4a58fa439b6ce0344 [file] [log] [blame]
Marat Dukhan0a312192015-08-22 17:46:29 -04001#!/usr/bin/env python
2
3import os
4import sys
5import glob
6import argparse
7import ninja_syntax
8
9
10class Configuration:
11
12 def __init__(self, options, ninja_build_file=os.path.join(os.path.dirname(os.path.abspath(__file__)), "build.ninja")):
13 self.output = open(ninja_build_file, "w")
14 self.writer = ninja_syntax.Writer(self.output)
15 self.source_dir = None
16 self.build_dir = None
17 self.artifact_dir = None
18 self.prefix_dir = options.prefix
19 self.include_dirs = []
20 self.object_ext = ".bc"
21
22 # Variables
23 self.writer.variable("nacl_sdk_dir", options.nacl_sdk)
24 self._set_pnacl_vars()
25 self.writer.variable("cflags", "-std=gnu11")
26 self.writer.variable("cxxflags", "-std=gnu++11")
27 self.writer.variable("optflags", "-O3")
28
29 # Rules
30 self.writer.rule("cc", "$pnacl_cc -o $out -c $in -MMD -MF $out.d $optflags $cflags $includes",
31 deps="gcc", depfile="$out.d",
32 description="CC[PNaCl] $descpath")
33 self.writer.rule("cxx", "$pnacl_cxx -o $out -c $in -MMD -MF $out.d $optflags $cxxflags $includes",
34 deps="gcc", depfile="$out.d",
35 description="CXX[PNaCl] $descpath")
36 self.writer.rule("ccld", "$pnacl_cc -o $out $in $libs $libdirs $ldflags",
37 description="CCLD[PNaCl] $descpath")
38 self.writer.rule("cxxld", "$pnacl_cxx -o $out $in $libs $libdirs $ldflags",
39 description="CXXLD[PNaCl] $descpath")
40 self.writer.rule("ar", "$pnacl_ar rcs $out $in",
41 description="AR[PNaCl] $descpath")
42 self.writer.rule("finalize", "$pnacl_finalize $finflags -o $out $in",
43 description="FINALIZE[PNaCl] $descpath")
44 self.writer.rule("translate", "$pnacl_translate -arch $arch -o $out $in",
45 description="TRANSLATE[PNaCl] $descpath")
46 self.writer.rule("run", "$pnacl_sel_ldr $in",
47 description="RUN[PNaCl] $descpath", pool="console")
48 self.writer.rule("install", "install -m $mode $in $out",
49 description="INSTALL $out")
50
51
52 def _set_pnacl_vars(self):
53 if sys.platform == "win32":
54 self.writer.variable("pnacl_toolchain_dir", "$nacl_sdk_dir/toolchain/win_pnacl")
55 self.writer.variable("pnacl_cc", "$pnacl_toolchain_dir/bin/pnacl-clang.bat")
56 self.writer.variable("pnacl_cxx", "$pnacl_toolchain_dir/bin/pnacl-clang++.bat")
57 self.writer.variable("pnacl_ar", "$pnacl_toolchain_dir/bin/pnacl-ar.bat")
58 self.writer.variable("pnacl_finalize", "$pnacl_toolchain_dir/bin/pnacl-finalize.bat")
59 self.writer.variable("pnacl_translate", "$pnacl_toolchain_dir/bin/pnacl-translate.bat")
60 elif sys.platform == "linux2" or sys.platform == "darwin":
61 if sys.platform == "linux2":
62 self.writer.variable("pnacl_toolchain_dir", "$nacl_sdk_dir/toolchain/linux_pnacl")
63 else:
64 self.writer.variable("pnacl_toolchain_dir", "$nacl_sdk_dir/toolchain/mac_pnacl")
65 self.writer.variable("pnacl_cc", "$pnacl_toolchain_dir/bin/pnacl-clang")
66 self.writer.variable("pnacl_cxx", "$pnacl_toolchain_dir/bin/pnacl-clang++")
67 self.writer.variable("pnacl_ar", "$pnacl_toolchain_dir/bin/pnacl-ar")
68 self.writer.variable("pnacl_finalize", "$pnacl_toolchain_dir/bin/pnacl-finalize")
69 self.writer.variable("pnacl_translate", "$pnacl_toolchain_dir/bin/pnacl-translate")
70 else:
71 raise OSError("Unsupported platform: " + sys.platform)
72 self.writer.variable("pnacl_sel_ldr", "$nacl_sdk_dir/tools/sel_ldr.py")
73
74
75 def _compile(self, rule, source_file, object_file):
76 if not os.path.isabs(source_file):
77 source_file = os.path.join(self.source_dir, source_file)
78 if object_file is None:
79 object_file = os.path.join(self.build_dir, os.path.relpath(source_file, self.source_dir)) + self.object_ext
80 variables = {
81 "descpath": os.path.relpath(source_file, self.source_dir)
82 }
83 if self.include_dirs:
84 variables["includes"] = " ".join(["-I" + i for i in self.include_dirs])
85 self.writer.build(object_file, rule, source_file, variables=variables)
86 return object_file
87
88
89 def cc(self, source_file, object_file=None):
90 return self._compile("cc", source_file, object_file)
91
92
93 def cxx(self, source_file, object_file=None):
94 return self._compile("cxx", source_file, object_file)
95
96
97 def _link(self, rule, object_files, binary_file, binary_dir, lib_dirs, libs):
98 if not os.path.isabs(binary_file):
99 binary_file = os.path.join(binary_dir, binary_file)
100 variables = {
101 "descpath": os.path.relpath(binary_file, binary_dir)
102 }
103 if lib_dirs:
104 variables["libdirs"] = " ".join(["-L" + l for l in lib_dirs])
105 if libs:
106 variables["libs"] = " ".join(["-l" + l for l in libs])
107 self.writer.build(binary_file, rule, object_files, variables=variables)
108 return binary_file
109
110
111 def ccld(self, object_files, binary_file, lib_dirs=[], libs=[]):
112 return self._link("ccld", object_files, binary_file, self.build_dir, lib_dirs, libs)
113
114
115 def cxxld(self, object_files, binary_file, lib_dirs=[], libs=[]):
116 return self._link("cxxld", object_files, binary_file, self.build_dir, lib_dirs, libs)
117
118
119 def ar(self, object_files, archive_file):
120 if not os.path.isabs(archive_file):
121 archive_file = os.path.join(self.artifact_dir, archive_file)
122 variables = {
123 "descpath": os.path.relpath(archive_file, self.artifact_dir)
124 }
125 self.writer.build(archive_file, "ar", object_files, variables=variables)
126 return archive_file
127
128 def finalize(self, binary_file, executable_file):
129 if not os.path.isabs(binary_file):
130 binary_file = os.path.join(self.build_dir, binary_file)
131 if not os.path.isabs(executable_file):
132 executable_file = os.path.join(self.artifact_dir, executable_file)
133 variables = {
134 "descpath": os.path.relpath(executable_file, self.artifact_dir)
135 }
136 self.writer.build(executable_file, "finalize", binary_file, variables=variables)
137 return executable_file
138
139 def translate(self, portable_file, native_file):
140 if not os.path.isabs(portable_file):
141 portable_file = os.path.join(self.artifact_dir, portable_file)
142 if not os.path.isabs(native_file):
143 native_file = os.path.join(self.artifact_dir, native_file)
144 variables = {
145 "descpath": os.path.relpath(portable_file, self.artifact_dir),
146 "arch": "x86_64"
147 }
148 self.writer.build(native_file, "translate", portable_file, variables=variables)
149 return native_file
150
151 def run(self, executable_file, target):
152 variables = {
153 "descpath": os.path.relpath(executable_file, self.artifact_dir)
154 }
155 self.writer.build(target, "run", executable_file, variables=variables)
156
157 def install(self, source_file, destination_file, mode=0o644):
158 if not os.path.isabs(destination_file):
159 destination_file = os.path.join(self.prefix_dir, destination_file)
160 variables = {
161 "mode": "0%03o" % mode
162 }
163 self.writer.build(destination_file, "install", source_file, variables=variables)
164 return destination_file
165
166
167parser = argparse.ArgumentParser(description="PThreadPool configuration script")
168parser.add_argument("--with-nacl-sdk", dest="nacl_sdk", default=os.getenv("NACL_SDK_ROOT"),
169 help="Native Client (Pepper) SDK to use")
170parser.add_argument("--prefix", dest="prefix", default="/usr/local")
171
172
173def main():
174 options = parser.parse_args()
175
176 config = Configuration(options)
177
178 root_dir = os.path.dirname(os.path.abspath(__file__))
179
180 config.source_dir = os.path.join(root_dir, "src")
181 config.build_dir = os.path.join(root_dir, "build")
182 config.artifact_dir = os.path.join(root_dir, "artifacts")
183 config.include_dirs = [os.path.join("$nacl_sdk_dir", "include"), os.path.join(root_dir, "include"), os.path.join(root_dir, "src")]
184
185 pthreadpool_object = config.cc("pthreadpool.c")
186 pthreadpool_library = config.ar([pthreadpool_object], "libpthreadpool.a")
187
188 config.source_dir = os.path.join(root_dir, "test")
189 config.build_dir = os.path.join(root_dir, "build", "test")
190 pthreadpool_test_object = config.cxx("pthreadpool.cc")
191 pthreadpool_test_binary = config.cxxld([pthreadpool_object, pthreadpool_test_object], "pthreadpool.bc", libs=["gtest"], lib_dirs=[os.path.join("$nacl_sdk_dir", "lib", "pnacl", "Release")])
192 pthreadpool_test_binary = config.finalize(pthreadpool_test_binary, "pthreadpool.pexe")
193 pthreadpool_test_binary = config.translate(pthreadpool_test_binary, "pthreadpool.nexe")
194 config.run(pthreadpool_test_binary, "test")
195
196 config.writer.default([pthreadpool_library, pthreadpool_test_binary])
197
198 config.writer.build("install", "phony", [
199 config.install(os.path.join(root_dir, "include", "pthreadpool.h"), "include/pthreadpool.h"),
200 config.install(os.path.join(pthreadpool_object), "lib/libpthreadpool.a")])
201
202
203if __name__ == "__main__":
204 sys.exit(main())