Marat Dukhan | 0a31219 | 2015-08-22 17:46:29 -0400 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | import os |
| 4 | import sys |
| 5 | import glob |
| 6 | import argparse |
| 7 | import ninja_syntax |
| 8 | |
| 9 | |
| 10 | class 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 | |
| 167 | parser = argparse.ArgumentParser(description="PThreadPool configuration script") |
| 168 | parser.add_argument("--with-nacl-sdk", dest="nacl_sdk", default=os.getenv("NACL_SDK_ROOT"), |
| 169 | help="Native Client (Pepper) SDK to use") |
| 170 | parser.add_argument("--prefix", dest="prefix", default="/usr/local") |
| 171 | |
| 172 | |
| 173 | def 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 | |
| 203 | if __name__ == "__main__": |
| 204 | sys.exit(main()) |