blob: 22882acecf1bddbf9737dba9b31fb739c413a1b4 [file] [log] [blame]
load("@//tools/build_rules:select.bzl", "compiler_select")
def _single_fortran_object_impl(ctx):
toolchain_cflags = (ctx.fragments.cpp.compiler_options([]) +
ctx.fragments.cpp.c_options +
ctx.fragments.cpp.unfiltered_compiler_options([]) +
[
"-fPIC",
"-Wno-maybe-uninitialized",
"-Wno-unused-dummy-argument",
"-Wno-conversion",
"-Wno-unused-variable",
"-Wno-character-truncation",
])
cmd = toolchain_cflags + ["-c", ctx.file.src.path, "-o", ctx.outputs.pic_o.path]
filtered_cmd = []
# Strip out the C/C++/Clang specific flags.
exclude_flags = [
"-fcolor-diagnostics",
"-Wswitch-enum",
"-Wpointer-arith",
"-Wcast-qual",
"-Wwrite-strings",
"-Wsign-compare",
"-Wformat=2",
"-Werror",
"-Wextra",
"-Wno-builtin-macro-redefined",
"-Wunused-local-typedefs",
"-D__has_feature(x)=0",
"-fmacro-backtrace-limit=0",
]
for flag in cmd:
if flag not in exclude_flags and not (flag.startswith("-fsanitize") or
flag.startswith("-fno-sanitize")):
filtered_cmd.append(flag)
ctx.action(
inputs = [ctx.file.src] + ctx.files._cc_toolchain,
outputs = [ctx.outputs.pic_o],
mnemonic = "Fortran",
executable = ctx.fragments.cpp.compiler_executable,
arguments = filtered_cmd,
progress_message = "Building %s" % ctx.outputs.pic_o.short_path,
)
def _define_fortran_output(src):
if not src.name.endswith(".f"):
fail("Fortran files must end in '.f'", "src")
fortran_file_base = src.name[:-2]
return {
"pic_o": fortran_file_base + ".pic.o",
}
_single_fortran_object = rule(
attrs = {
"src": attr.label(
single_file = True,
allow_files = FileType([".f"]),
),
"cc_libs": attr.label_list(providers = ["cc"]),
# TODO(Brian): Replace this with something more fine-grained from the
# configuration fragment or something.
"_cc_toolchain": attr.label(
default = Label("@//tools/cpp:toolchain"),
),
},
fragments = [
"cpp",
],
outputs = _define_fortran_output,
implementation = _single_fortran_object_impl,
)
def fortran_library(name, srcs, deps = [], visibility = None):
"""Builds a shared library from a set of fortran files.
Args:
srcs: list of fortran files ending in .f
deps: cc_library or fortran_library dependencies.
"""
pic_o_files = []
for src in srcs:
pic_o_file = src[:-2] + ".pic.o"
_single_fortran_object(
name = name + "_" + pic_o_file,
src = src,
visibility = ["//visibility:private"],
restricted_to = ["@//tools:k8"],
)
pic_o_files.append(pic_o_file)
native.cc_library(
name = name,
deps = deps,
srcs = pic_o_files,
linkopts = [
"-lgfortran",
],
visibility = visibility,
restricted_to = ["@//tools:k8"],
)
f2c_copts = compiler_select({
"clang": [
"-Wno-incompatible-pointer-types-discards-qualifiers",
# Clang appears to be a bit over-eager about this and the comma operator.
"-Wno-sometimes-uninitialized",
],
"gcc": [
# TODO(Brian): Remove this once we can actually disable all the warnings.
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43245 isn't fixed in our
# roborio toolchain yet, so we can't for now.
"-Wno-error",
],
}) + [
# f2c appears to know what it's doing without adding extra ().
"-Wno-parentheses",
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
"-Wno-unused-variable",
]
"""Copts to use when compiling f2c-generated files.
This is useful when building externally-f2ced files."""
def f2c_library(name, srcs, copts = [], **kwargs):
"""Converts Fortran code to C and then compiles it.
Attrs:
srcs: .f source files
**kwargs: passed to native.cc_library
"""
c_srcs = [f[:-2] + ".c" for f in srcs]
out_dir = c_srcs[0].split("/")[:-1]
for c_src in c_srcs:
if c_src.split("/")[:-1] != out_dir:
# Need to figure out how to make multiple f2c calls or something to
# support this, and we haven't had a use case yet.
fail("Multiple output directories not supported", "srcs")
native.genrule(
name = "_%s_f2c" % name,
visibility = ["//visibility:private"],
srcs = srcs,
outs = c_srcs,
tools = [
"@f2c",
"@//tools/build_rules:quiet_success",
],
cmd = " ".join([
"$(location @//tools/build_rules:quiet_success)",
"$(location @f2c)",
"-d$(@D)/%s" % ("/".join(out_dir),),
"$(SRCS)",
]),
)
native.cc_library(
name = name,
srcs = c_srcs,
copts = f2c_copts + copts,
**kwargs
)