| """This file contains BUILD extensions for generating source code from LLVM's table definition files using the TableGen tool. |
| |
| See http://llvm.org/cmds/tblgen.html for more information on the TableGen |
| tool. |
| TODO(chandlerc): Currently this expresses include-based dependencies as |
| "sources", and has no transitive understanding due to these files not being |
| correctly understood by the build system. |
| """ |
| |
| def _dict_add(*dictionaries): |
| """Returns a new `dict` that has all the entries of the given dictionaries. |
| |
| If the same key is present in more than one of the input dictionaries, the |
| last of them in the argument list overrides any earlier ones. |
| |
| This function is designed to take zero or one arguments as well as multiple |
| dictionaries, so that it follows arithmetic identities and callers can avoid |
| special cases for their inputs: the sum of zero dictionaries is the empty |
| dictionary, and the sum of a single dictionary is a copy of itself. |
| |
| Re-implemented here to avoid adding a dependency on skylib. |
| |
| Args: |
| *dictionaries: Zero or more dictionaries to be added. |
| |
| Returns: |
| A new `dict` that has all the entries of the given dictionaries. |
| """ |
| result = {} |
| for d in dictionaries: |
| result.update(d) |
| return result |
| |
| def gentbl(name, tblgen, td_file, td_srcs, tbl_outs, library = True, **kwargs): |
| """gentbl() generates tabular code from a table definition file. |
| |
| Args: |
| name: The name of the build rule for use in dependencies. |
| tblgen: The binary used to produce the output. |
| td_file: The primary table definitions file. |
| td_srcs: A list of table definition files included transitively. |
| tbl_outs: A list of tuples (opts, out), where each opts is a string of |
| options passed to tblgen, and the out is the corresponding output file |
| produced. |
| library: Whether to bundle the generated files into a library. |
| **kwargs: Keyword arguments to pass to subsidiary cc_library() rule. |
| """ |
| if td_file not in td_srcs: |
| td_srcs += [td_file] |
| includes = [] |
| for (opts, out) in tbl_outs: |
| outdir = out[:out.rindex("/")] |
| if outdir not in includes: |
| includes.append(outdir) |
| rule_suffix = "_".join(opts.replace("-", "_").replace("=", "_").split(" ")) |
| native.genrule( |
| name = "%s_%s_genrule" % (name, rule_suffix), |
| srcs = td_srcs, |
| outs = [out], |
| tools = [tblgen], |
| message = "Generating code from table: %s" % td_file, |
| cmd = (("$(location %s) " + "-I external/llvm/include " + |
| "-I external/llvm/tools/clang/include " + |
| "-I $$(dirname $(location %s)) " + "%s $(location %s) -o $@") % ( |
| tblgen, |
| td_file, |
| opts, |
| td_file, |
| )), |
| ) |
| |
| # For now, all generated files can be assumed to comprise public interfaces. |
| # If this is not true, you should specify library = False |
| # and list the generated '.inc' files in "srcs". |
| if library: |
| native.cc_library( |
| name = name, |
| textual_hdrs = [f for (_, f) in tbl_outs], |
| includes = includes, |
| **kwargs |
| ) |
| |
| def llvm_target_cmake_vars(native_arch, target_triple): |
| return { |
| "LLVM_HOST_TRIPLE": target_triple, |
| "LLVM_DEFAULT_TARGET_TRIPLE": target_triple, |
| "LLVM_NATIVE_ARCH": native_arch, |
| } |
| |
| def _quote(s): |
| """Quotes the given string for use in a shell command. |
| |
| This function double-quotes the given string (in case it contains spaces or |
| other special characters) and escapes any special characters (dollar signs, |
| double-quotes, and backslashes) that may be present. |
| |
| Args: |
| s: The string to quote. |
| |
| Returns: |
| An escaped and quoted version of the string that can be passed to a shell |
| command. |
| """ |
| return ('"' + |
| s.replace("\\", "\\\\").replace("$", "\\$").replace('"', '\\"') + |
| '"') |
| |
| def cmake_var_string(cmake_vars): |
| """Converts a dictionary to an input suitable for expand_cmake_vars. |
| |
| Ideally we would jist stringify in the expand_cmake_vars() rule, but select() |
| interacts badly with genrules. |
| |
| TODO(phawkins): replace the genrule() with native rule and delete this rule. |
| |
| Args: |
| cmake_vars: a dictionary with string keys and values that are convertable to |
| strings. |
| |
| Returns: |
| cmake_vars in a form suitable for passing to expand_cmake_vars. |
| """ |
| return " ".join([ |
| _quote("{}={}".format(k, str(v))) |
| for (k, v) in cmake_vars.items() |
| ]) |
| |
| def expand_cmake_vars(name, src, dst, cmake_vars): |
| """Expands #cmakedefine, #cmakedefine01, and CMake variables in a text file. |
| |
| Args: |
| name: the name of the rule |
| src: the input of the rule |
| dst: the output of the rule |
| cmake_vars: a string containing the CMake variables, as generated by |
| cmake_var_string. |
| """ |
| expand_cmake_vars_tool = "@org_tensorflow//third_party/llvm:expand_cmake_vars" |
| native.genrule( |
| name = name, |
| srcs = [src], |
| tools = [expand_cmake_vars_tool], |
| outs = [dst], |
| cmd = ("$(location {}) ".format(expand_cmake_vars_tool) + cmake_vars + |
| "< $< > $@"), |
| ) |
| |
| # TODO(phawkins): the set of CMake variables was hardcoded for expediency. |
| # However, we should really detect many of these via configure-time tests. |
| |
| # The set of CMake variables common to all targets. |
| cmake_vars = { |
| # LLVM features |
| "ENABLE_BACKTRACES": 1, |
| "LLVM_BINDIR": "/dev/null", |
| "LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING": 0, |
| "LLVM_ENABLE_ABI_BREAKING_CHECKS": 0, |
| "LLVM_ENABLE_THREADS": 1, |
| "LLVM_ENABLE_ZLIB": 1, |
| "LLVM_HAS_ATOMICS": 1, |
| "LLVM_INCLUDEDIR": "/dev/null", |
| "LLVM_INFODIR": "/dev/null", |
| "LLVM_MANDIR": "/dev/null", |
| "LLVM_NATIVE_TARGET": 1, |
| "LLVM_NATIVE_TARGETINFO": 1, |
| "LLVM_NATIVE_TARGETMC": 1, |
| "LLVM_NATIVE_ASMPRINTER": 1, |
| "LLVM_NATIVE_ASMPARSER": 1, |
| "LLVM_NATIVE_DISASSEMBLER": 1, |
| "LLVM_PREFIX": "/dev/null", |
| "LLVM_VERSION_MAJOR": 0, |
| "LLVM_VERSION_MINOR": 0, |
| "LLVM_VERSION_PATCH": 0, |
| "PACKAGE_NAME": "llvm", |
| "PACKAGE_STRING": "llvm tensorflow-trunk", |
| "PACKAGE_VERSION": "tensorflow-trunk", |
| "RETSIGTYPE": "void", |
| } |
| |
| # The set of CMake variables common to POSIX targets. |
| posix_cmake_vars = { |
| # Headers |
| "HAVE_DIRENT_H": 1, |
| "HAVE_DLFCN_H": 1, |
| "HAVE_ERRNO_H": 1, |
| "HAVE_EXECINFO_H": 1, |
| "HAVE_FCNTL_H": 1, |
| "HAVE_INTTYPES_H": 1, |
| "HAVE_PTHREAD_H": 1, |
| "HAVE_SIGNAL_H": 1, |
| "HAVE_STDINT_H": 1, |
| "HAVE_SYS_IOCTL_H": 1, |
| "HAVE_SYS_MMAN_H": 1, |
| "HAVE_SYS_PARAM_H": 1, |
| "HAVE_SYS_RESOURCE_H": 1, |
| "HAVE_SYS_STAT_H": 1, |
| "HAVE_SYS_TIME_H": 1, |
| "HAVE_SYS_TYPES_H": 1, |
| "HAVE_TERMIOS_H": 1, |
| "HAVE_UNISTD_H": 1, |
| "HAVE_ZLIB_H": 1, |
| |
| # Features |
| "HAVE_BACKTRACE": 1, |
| "BACKTRACE_HEADER": "execinfo.h", |
| "HAVE_DLOPEN": 1, |
| "HAVE_FUTIMES": 1, |
| "HAVE_GETCWD": 1, |
| "HAVE_GETPAGESIZE": 1, |
| "HAVE_GETRLIMIT": 1, |
| "HAVE_GETRUSAGE": 1, |
| "HAVE_GETTIMEOFDAY": 1, |
| "HAVE_INT64_T": 1, |
| "HAVE_ISATTY": 1, |
| "HAVE_LIBEDIT": 1, |
| "HAVE_LIBPTHREAD": 1, |
| "HAVE_LIBZ": 1, |
| "HAVE_MKDTEMP": 1, |
| "HAVE_MKSTEMP": 1, |
| "HAVE_MKTEMP": 1, |
| "HAVE_PREAD": 1, |
| "HAVE_PTHREAD_GETSPECIFIC": 1, |
| "HAVE_PTHREAD_MUTEX_LOCK": 1, |
| "HAVE_PTHREAD_RWLOCK_INIT": 1, |
| "HAVE_REALPATH": 1, |
| "HAVE_SBRK": 1, |
| "HAVE_SETENV": 1, |
| "HAVE_SETRLIMIT": 1, |
| "HAVE_SIGALTSTACK": 1, |
| "HAVE_STRERROR": 1, |
| "HAVE_STRERROR_R": 1, |
| "HAVE_STRTOLL": 1, |
| "HAVE_SYSCONF": 1, |
| "HAVE_UINT64_T": 1, |
| "HAVE__UNWIND_BACKTRACE": 1, |
| |
| # LLVM features |
| "LLVM_ON_UNIX": 1, |
| "LTDL_SHLIB_EXT": ".so", |
| } |
| |
| # CMake variables specific to the Linux platform |
| linux_cmake_vars = { |
| "HAVE_MALLOC_H": 1, |
| "HAVE_LINK_H": 1, |
| "HAVE_MALLINFO": 1, |
| "HAVE_FUTIMENS": 1, |
| } |
| |
| # CMake variables specific to the FreeBSD platform |
| freebsd_cmake_vars = { |
| "HAVE_MALLOC_H": 1, |
| "HAVE_LINK_H": 1, |
| } |
| |
| # CMake variables specific to the Darwin (Mac OS X) platform. |
| darwin_cmake_vars = { |
| "HAVE_MALLOC_MALLOC_H": 1, |
| "HAVE_MALLOC_ZONE_STATISTICS": 1, |
| } |
| |
| # CMake variables specific to the Windows platform. |
| win32_cmake_vars = { |
| # Headers |
| "HAVE_ERRNO_H": 1, |
| "HAVE_EXECINFO_H": 1, |
| "HAVE_FCNTL_H": 1, |
| "HAVE_FENV_H": 1, |
| "HAVE_INTTYPES_H": 1, |
| "HAVE_MALLOC_H": 1, |
| "HAVE_SIGNAL_H": 1, |
| "HAVE_STDINT_H": 1, |
| "HAVE_SYS_STAT_H": 1, |
| "HAVE_SYS_TYPES_H": 1, |
| "HAVE_ZLIB_H": 1, |
| |
| # Features |
| "BACKTRACE_HEADER": "execinfo.h", |
| "HAVE_GETCWD": 1, |
| "HAVE_INT64_T": 1, |
| "HAVE_STRERROR": 1, |
| "HAVE_STRTOLL": 1, |
| "HAVE_SYSCONF": 1, |
| "HAVE_UINT64_T": 1, |
| "HAVE__CHSIZE_S": 1, |
| "HAVE___CHKSTK": 1, |
| |
| # MSVC specific |
| "stricmp": "_stricmp", |
| "strdup": "_strdup", |
| |
| # LLVM features |
| "LTDL_SHLIB_EXT": ".dll", |
| } |
| |
| # Select a set of CMake variables based on the platform. |
| # TODO(phawkins): use a better method to select the right host triple, rather |
| # than hardcoding x86_64. |
| llvm_all_cmake_vars = select({ |
| "@org_tensorflow//tensorflow:macos": cmake_var_string( |
| _dict_add( |
| cmake_vars, |
| llvm_target_cmake_vars("X86", "x86_64-apple-darwin"), |
| posix_cmake_vars, |
| darwin_cmake_vars, |
| ), |
| ), |
| "@org_tensorflow//tensorflow:linux_ppc64le": cmake_var_string( |
| _dict_add( |
| cmake_vars, |
| llvm_target_cmake_vars("PowerPC", "powerpc64le-unknown-linux_gnu"), |
| posix_cmake_vars, |
| linux_cmake_vars, |
| ), |
| ), |
| "@org_tensorflow//tensorflow:windows": cmake_var_string( |
| _dict_add( |
| cmake_vars, |
| llvm_target_cmake_vars("X86", "x86_64-pc-win32"), |
| win32_cmake_vars, |
| ), |
| ), |
| "@org_tensorflow//tensorflow:freebsd": cmake_var_string( |
| _dict_add( |
| cmake_vars, |
| llvm_target_cmake_vars("X86", "x86_64-unknown-freebsd"), |
| posix_cmake_vars, |
| ), |
| ), |
| "//conditions:default": cmake_var_string( |
| _dict_add( |
| cmake_vars, |
| llvm_target_cmake_vars("X86", "x86_64-unknown-linux_gnu"), |
| posix_cmake_vars, |
| linux_cmake_vars, |
| ), |
| ), |
| }) |
| |
| llvm_linkopts = select({ |
| "@org_tensorflow//tensorflow:windows": [], |
| "@org_tensorflow//tensorflow:freebsd": ["-ldl", "-lm", "-lpthread", "-lexecinfo"], |
| "//conditions:default": ["-ldl", "-lm", "-lpthread"], |
| }) |
| |
| llvm_defines = select({ |
| "@org_tensorflow//tensorflow:windows": [ |
| "_CRT_SECURE_NO_DEPRECATE", |
| "_CRT_SECURE_NO_WARNINGS", |
| "_CRT_NONSTDC_NO_DEPRECATE", |
| "_CRT_NONSTDC_NO_WARNINGS", |
| "_SCL_SECURE_NO_DEPRECATE", |
| "_SCL_SECURE_NO_WARNINGS", |
| "UNICODE", |
| "_UNICODE", |
| ], |
| "//conditions:default": [], |
| }) + [ |
| "LLVM_ENABLE_STATS", |
| "__STDC_LIMIT_MACROS", |
| "__STDC_CONSTANT_MACROS", |
| "__STDC_FORMAT_MACROS", |
| "LLVM_BUILD_GLOBAL_ISEL", |
| ] |
| |
| llvm_copts = select({ |
| "@org_tensorflow//tensorflow:windows": [ |
| "-Zc:inline", |
| "-Zc:strictStrings", |
| "-Zc:rvalueCast", |
| "-Oi", |
| "-wd4141", |
| "-wd4146", |
| "-wd4180", |
| "-wd4244", |
| "-wd4258", |
| "-wd4267", |
| "-wd4291", |
| "-wd4345", |
| "-wd4351", |
| "-wd4355", |
| "-wd4456", |
| "-wd4457", |
| "-wd4458", |
| "-wd4459", |
| "-wd4503", |
| "-wd4624", |
| "-wd4722", |
| "-wd4800", |
| "-wd4100", |
| "-wd4127", |
| "-wd4512", |
| "-wd4505", |
| "-wd4610", |
| "-wd4510", |
| "-wd4702", |
| "-wd4245", |
| "-wd4706", |
| "-wd4310", |
| "-wd4701", |
| "-wd4703", |
| "-wd4389", |
| "-wd4611", |
| "-wd4805", |
| "-wd4204", |
| "-wd4577", |
| "-wd4091", |
| "-wd4592", |
| "-wd4319", |
| "-wd4324", |
| "-w14062", |
| "-we4238", |
| ], |
| "//conditions:default": [], |
| }) |
| |
| # Platform specific sources for libSupport. |
| |
| def llvm_support_platform_specific_srcs_glob(): |
| return select({ |
| "@org_tensorflow//tensorflow:windows": native.glob([ |
| "lib/Support/Windows/*.inc", |
| "lib/Support/Windows/*.h", |
| ]), |
| "//conditions:default": native.glob([ |
| "lib/Support/Unix/*.inc", |
| "lib/Support/Unix/*.h", |
| ]), |
| }) |