Skip to content

Commit e404e51

Browse files
bgeronkrasimirgg
andauthored
fix rustdoc: omit link flags for rustdoc (bazelbuild#2467)
In our project, rust_doc fails because it is generating `-l` arguments to rustdoc, and rustdoc does not support `-l` arguments. In my understanding, these arguments are only relevant for calling the linker at some point, and it won't be called for rustdoc anyway. With this PR, our project can build with rust_doc. --------- Co-authored-by: Krasimir Georgiev <[email protected]>
1 parent bee5316 commit e404e51

File tree

4 files changed

+120
-46
lines changed

4 files changed

+120
-46
lines changed

rust/private/rustc.bzl

Lines changed: 55 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ def get_cc_user_link_flags(ctx):
391391
"""
392392
return ctx.fragments.cpp.linkopts
393393

394-
def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configuration, rpaths, rustdoc = False):
394+
def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configuration, rpaths, add_flags_for_binary = False):
395395
"""Gathers cc_common linker information
396396
397397
Args:
@@ -401,7 +401,7 @@ def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configurati
401401
cc_toolchain (CcToolchain): cc_toolchain for which we are creating build variables.
402402
feature_configuration (FeatureConfiguration): Feature configuration to be queried.
403403
rpaths (depset): Depset of directories where loader will look for libraries at runtime.
404-
rustdoc (bool, optional): Whether to add "bin" link flags to the command regardless of `crate_type`.
404+
add_flags_for_binary (bool, optional): Whether to add "bin" link flags to the command regardless of `crate_type`.
405405
406406
407407
Returns:
@@ -412,7 +412,7 @@ def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configurati
412412
"""
413413
user_link_flags = get_cc_user_link_flags(ctx)
414414

415-
if crate_type in ("bin") or rustdoc:
415+
if crate_type in ("bin") or add_flags_for_binary:
416416
is_linking_dynamic_library = False
417417
action_name = CPP_LINK_EXECUTABLE_ACTION_NAME
418418
elif crate_type in ("dylib"):
@@ -430,7 +430,7 @@ def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configurati
430430
else:
431431
fail("Unknown `crate_type`: {}".format(crate_type))
432432

433-
# Add linkopt's from dependencies. This includes linkopts from transitive
433+
# Add linkopts from dependencies. This includes linkopts from transitive
434434
# dependencies since they get merged up.
435435
for dep in getattr(attr, "deps", []):
436436
if CcInfo in dep and dep[CcInfo].linking_context:
@@ -464,13 +464,15 @@ def get_linker_and_args(ctx, attr, crate_type, cc_toolchain, feature_configurati
464464
def _process_build_scripts(
465465
build_info,
466466
dep_info,
467-
compile_inputs):
467+
compile_inputs,
468+
include_link_flags = True):
468469
"""Gathers the outputs from a target's `cargo_build_script` action.
469470
470471
Args:
471472
build_info (BuildInfo): The target Build's dependency info.
472473
dep_info (DepInfo): The Depinfo provider form the target Crate's set of inputs.
473474
compile_inputs (depset): A set of all files that will participate in the build.
475+
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
474476
475477
Returns:
476478
tuple: A tuple: A tuple of the following items:
@@ -479,7 +481,7 @@ def _process_build_scripts(
479481
- (File): An optional path to a generated environment file from a `cargo_build_script` target
480482
- (depset[File]): All direct and transitive build flags from the current build info.
481483
"""
482-
extra_inputs, out_dir, build_env_file, build_flags_files = _create_extra_input_args(build_info, dep_info)
484+
extra_inputs, out_dir, build_env_file, build_flags_files = _create_extra_input_args(build_info, dep_info, include_link_flags = include_link_flags)
483485
compile_inputs = depset(transitive = [extra_inputs, compile_inputs])
484486
return compile_inputs, out_dir, build_env_file, build_flags_files
485487

@@ -640,7 +642,8 @@ def collect_inputs(
640642
build_info,
641643
stamp = False,
642644
force_depend_on_objects = False,
643-
experimental_use_cc_common_link = False):
645+
experimental_use_cc_common_link = False,
646+
include_link_flags = True):
644647
"""Gather's the inputs and required input information for a rustc action
645648
646649
Args:
@@ -659,7 +662,8 @@ def collect_inputs(
659662
force_depend_on_objects (bool, optional): Forces dependencies of this rule to be objects rather than
660663
metadata, even for libraries. This is used in rustdoc tests.
661664
experimental_use_cc_common_link (bool, optional): Whether rules_rust uses cc_common.link to link
662-
rust binaries.
665+
rust binaries.
666+
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
663667
664668
Returns:
665669
tuple: A tuple: A tuple of the following items:
@@ -773,7 +777,7 @@ def collect_inputs(
773777
# For backwards compatibility, we also check the value of the `rustc_env_files` attribute when
774778
# `crate_info.rustc_env_files` is not populated.
775779
build_env_files = crate_info.rustc_env_files if crate_info.rustc_env_files else getattr(files, "rustc_env_files", [])
776-
compile_inputs, out_dir, build_env_file, build_flags_files = _process_build_scripts(build_info, dep_info, compile_inputs)
780+
compile_inputs, out_dir, build_env_file, build_flags_files = _process_build_scripts(build_info, dep_info, compile_inputs, include_link_flags = include_link_flags)
777781
if build_env_file:
778782
build_env_files = [f for f in build_env_files] + [build_env_file]
779783
compile_inputs = depset(build_env_files, transitive = [compile_inputs])
@@ -798,7 +802,8 @@ def construct_arguments(
798802
build_flags_files,
799803
emit = ["dep-info", "link"],
800804
force_all_deps_direct = False,
801-
rustdoc = False,
805+
add_flags_for_binary = False,
806+
include_link_flags = True,
802807
stamp = False,
803808
remap_path_prefix = "",
804809
use_json_output = False,
@@ -827,7 +832,8 @@ def construct_arguments(
827832
emit (list): Values for the --emit flag to rustc.
828833
force_all_deps_direct (bool, optional): Whether to pass the transitive rlibs with --extern
829834
to the commandline as opposed to -L.
830-
rustdoc (bool, optional): Whether to add "bin" link flags to the command regardless of `emit` and `crate_type`.
835+
add_flags_for_binary (bool, optional): Whether to add "bin" link flags to the command regardless of `emit` and `crate_type`.
836+
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
831837
stamp (bool, optional): Whether or not workspace status stamping is enabled. For more details see
832838
https://docs.bazel.build/versions/main/user-manual.html#flag--stamp
833839
remap_path_prefix (str, optional): A value used to remap `${pwd}` to. If set to None, no prefix will be set.
@@ -993,7 +999,7 @@ def construct_arguments(
993999
add_edition_flags(rustc_flags, crate_info)
9941000

9951001
# Link!
996-
if ("link" in emit and crate_info.type not in ["rlib", "lib"]) or rustdoc:
1002+
if ("link" in emit and crate_info.type not in ["rlib", "lib"]) or add_flags_for_binary:
9971003
# Rust's built-in linker can handle linking wasm files. We don't want to attempt to use the cc
9981004
# linker since it won't understand.
9991005
compilation_mode = ctx.var["COMPILATION_MODE"]
@@ -1004,7 +1010,7 @@ def construct_arguments(
10041010
else:
10051011
rpaths = depset()
10061012

1007-
ld, link_args, link_env = get_linker_and_args(ctx, attr, crate_info.type, cc_toolchain, feature_configuration, rpaths, rustdoc)
1013+
ld, link_args, link_env = get_linker_and_args(ctx, attr, crate_info.type, cc_toolchain, feature_configuration, rpaths, add_flags_for_binary = add_flags_for_binary)
10081014

10091015
env.update(link_env)
10101016
rustc_flags.add(ld, format = "--codegen=linker=%s")
@@ -1013,7 +1019,7 @@ def construct_arguments(
10131019
# Additional context: https://github.com/rust-lang/rust/pull/36574
10141020
rustc_flags.add_all(link_args, format_each = "--codegen=link-arg=%s")
10151021

1016-
_add_native_link_flags(rustc_flags, dep_info, linkstamp_outs, ambiguous_libs, crate_info.type, toolchain, cc_toolchain, feature_configuration, compilation_mode)
1022+
_add_native_link_flags(rustc_flags, dep_info, linkstamp_outs, ambiguous_libs, crate_info.type, toolchain, cc_toolchain, feature_configuration, compilation_mode, include_link_flags = include_link_flags)
10171023

10181024
use_metadata = _depend_on_metadata(crate_info, force_depend_on_objects)
10191025

@@ -1650,12 +1656,13 @@ def add_edition_flags(args, crate):
16501656
if crate.edition != "2015":
16511657
args.add(crate.edition, format = "--edition=%s")
16521658

1653-
def _create_extra_input_args(build_info, dep_info):
1659+
def _create_extra_input_args(build_info, dep_info, include_link_flags = True):
16541660
"""Gather additional input arguments from transitive dependencies
16551661
16561662
Args:
16571663
build_info (BuildInfo): The BuildInfo provider from the target Crate's set of inputs.
16581664
dep_info (DepInfo): The Depinfo provider form the target Crate's set of inputs.
1665+
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
16591666
16601667
Returns:
16611668
tuple: A tuple of the following items:
@@ -1680,7 +1687,7 @@ def _create_extra_input_args(build_info, dep_info):
16801687
build_env_file = build_info.rustc_env
16811688
if build_info.flags:
16821689
build_flags_files.append(build_info.flags)
1683-
if build_info.linker_flags:
1690+
if build_info.linker_flags and include_link_flags:
16841691
build_flags_files.append(build_info.linker_flags)
16851692
input_files.append(build_info.linker_flags)
16861693

@@ -1894,8 +1901,8 @@ def _portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name, for_windows
18941901

18951902
return []
18961903

1897-
def _make_link_flags_windows(linker_input_and_use_pic_and_ambiguous_libs, flavor_msvc):
1898-
linker_input, use_pic, ambiguous_libs = linker_input_and_use_pic_and_ambiguous_libs
1904+
def _make_link_flags_windows(make_link_flags_args, flavor_msvc):
1905+
linker_input, use_pic, ambiguous_libs, include_link_flags = make_link_flags_args
18991906
ret = []
19001907
for lib in linker_input.libraries:
19011908
if lib.alwayslink:
@@ -1910,31 +1917,31 @@ def _make_link_flags_windows(linker_input_and_use_pic_and_ambiguous_libs, flavor
19101917
"-C",
19111918
"link-arg=-Wl,--no-whole-archive",
19121919
])
1913-
else:
1920+
elif include_link_flags:
19141921
ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_for_windows, for_windows = True, flavor_msvc = flavor_msvc))
19151922
return ret
19161923

1917-
def _make_link_flags_windows_msvc(linker_input_and_use_pic_and_ambiguous_libs):
1918-
return _make_link_flags_windows(linker_input_and_use_pic_and_ambiguous_libs, flavor_msvc = True)
1924+
def _make_link_flags_windows_msvc(make_link_flags_args):
1925+
return _make_link_flags_windows(make_link_flags_args, flavor_msvc = True)
19191926

1920-
def _make_link_flags_windows_gnu(linker_input_and_use_pic_and_ambiguous_libs):
1921-
return _make_link_flags_windows(linker_input_and_use_pic_and_ambiguous_libs, flavor_msvc = False)
1927+
def _make_link_flags_windows_gnu(make_link_flags_args):
1928+
return _make_link_flags_windows(make_link_flags_args, flavor_msvc = False)
19221929

1923-
def _make_link_flags_darwin(linker_input_and_use_pic_and_ambiguous_libs):
1924-
linker_input, use_pic, ambiguous_libs = linker_input_and_use_pic_and_ambiguous_libs
1930+
def _make_link_flags_darwin(make_link_flags_args):
1931+
linker_input, use_pic, ambiguous_libs, include_link_flags = make_link_flags_args
19251932
ret = []
19261933
for lib in linker_input.libraries:
19271934
if lib.alwayslink:
19281935
ret.extend([
19291936
"-C",
19301937
("link-arg=-Wl,-force_load,%s" % get_preferred_artifact(lib, use_pic).path),
19311938
])
1932-
else:
1939+
elif include_link_flags:
19331940
ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default, for_darwin = True))
19341941
return ret
19351942

1936-
def _make_link_flags_default(linker_input_and_use_pic_and_ambiguous_libs):
1937-
linker_input, use_pic, ambiguous_libs = linker_input_and_use_pic_and_ambiguous_libs
1943+
def _make_link_flags_default(make_link_flags_args):
1944+
linker_input, use_pic, ambiguous_libs, include_link_flags = make_link_flags_args
19381945
ret = []
19391946
for lib in linker_input.libraries:
19401947
if lib.alwayslink:
@@ -1946,17 +1953,17 @@ def _make_link_flags_default(linker_input_and_use_pic_and_ambiguous_libs):
19461953
"-C",
19471954
"link-arg=-Wl,--no-whole-archive",
19481955
])
1949-
else:
1956+
elif include_link_flags:
19501957
ret.extend(_portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default))
19511958
return ret
19521959

1953-
def _libraries_dirnames(linker_input_and_use_pic_and_ambiguous_libs):
1954-
link_input, use_pic, _ = linker_input_and_use_pic_and_ambiguous_libs
1960+
def _libraries_dirnames(make_link_flags_args):
1961+
link_input, use_pic, _, _ = make_link_flags_args
19551962

19561963
# De-duplicate names.
19571964
return depset([get_preferred_artifact(lib, use_pic).dirname for lib in link_input.libraries]).to_list()
19581965

1959-
def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate_type, toolchain, cc_toolchain, feature_configuration, compilation_mode):
1966+
def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate_type, toolchain, cc_toolchain, feature_configuration, compilation_mode, include_link_flags = True):
19601967
"""Adds linker flags for all dependencies of the current target.
19611968
19621969
Args:
@@ -1969,6 +1976,7 @@ def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate
19691976
cc_toolchain (CcToolchainInfo): The current `cc_toolchain`
19701977
feature_configuration (FeatureConfiguration): feature configuration to use with cc_toolchain
19711978
compilation_mode (bool): The compilation mode for this build.
1979+
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
19721980
"""
19731981
if crate_type in ["lib", "rlib"]:
19741982
return
@@ -1986,15 +1994,15 @@ def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate
19861994
get_lib_name = get_lib_name_default
19871995

19881996
# TODO(hlopko): Remove depset flattening by using lambdas once we are on >=Bazel 5.0
1989-
args_and_pic_and_ambiguous_libs = [(arg, use_pic, ambiguous_libs) for arg in dep_info.transitive_noncrates.to_list()]
1990-
args.add_all(args_and_pic_and_ambiguous_libs, map_each = _libraries_dirnames, uniquify = True, format_each = "-Lnative=%s")
1997+
make_link_flags_args = [(arg, use_pic, ambiguous_libs, include_link_flags) for arg in dep_info.transitive_noncrates.to_list()]
1998+
args.add_all(make_link_flags_args, map_each = _libraries_dirnames, uniquify = True, format_each = "-Lnative=%s")
19911999
if ambiguous_libs:
19922000
# If there are ambiguous libs, the disambiguation symlinks to them are
19932001
# all created in the same directory. Add it to the library search path.
19942002
ambiguous_libs_dirname = ambiguous_libs.values()[0].dirname
19952003
args.add(ambiguous_libs_dirname, format = "-Lnative=%s")
19962004

1997-
args.add_all(args_and_pic_and_ambiguous_libs, map_each = make_link_flags)
2005+
args.add_all(make_link_flags_args, map_each = make_link_flags)
19982006

19992007
args.add_all(linkstamp_outs, before_each = "-C", format_each = "link-args=%s")
20002008

@@ -2006,11 +2014,12 @@ def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate
20062014
map_each = _get_dirname,
20072015
format_each = "-Lnative=%s",
20082016
)
2009-
args.add_all(
2010-
cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration),
2011-
map_each = get_lib_name,
2012-
format_each = "-ldylib=%s",
2013-
)
2017+
if include_link_flags:
2018+
args.add_all(
2019+
cc_toolchain.dynamic_runtime_lib(feature_configuration = feature_configuration),
2020+
map_each = get_lib_name,
2021+
format_each = "-ldylib=%s",
2022+
)
20142023
else:
20152024
# For all other crate types we want to link C++ runtime library statically
20162025
# (for example libstdc++.a or libc++.a).
@@ -2019,11 +2028,12 @@ def _add_native_link_flags(args, dep_info, linkstamp_outs, ambiguous_libs, crate
20192028
map_each = _get_dirname,
20202029
format_each = "-Lnative=%s",
20212030
)
2022-
args.add_all(
2023-
cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration),
2024-
map_each = get_lib_name,
2025-
format_each = "-lstatic=%s",
2026-
)
2031+
if include_link_flags:
2032+
args.add_all(
2033+
cc_toolchain.static_runtime_lib(feature_configuration = feature_configuration),
2034+
map_each = get_lib_name,
2035+
format_each = "-lstatic=%s",
2036+
)
20272037

20282038
def _get_dirname(file):
20292039
"""A helper function for `_add_native_link_flags`.

rust/private/rustdoc.bzl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def rustdoc_compile_action(
9696
build_info = build_info,
9797
# If this is a rustdoc test, we need to depend on rlibs rather than .rmeta.
9898
force_depend_on_objects = is_test,
99+
include_link_flags = False,
99100
)
100101

101102
# Since this crate is not actually producing the output described by the
@@ -123,7 +124,8 @@ def rustdoc_compile_action(
123124
build_flags_files = build_flags_files,
124125
emit = [],
125126
remap_path_prefix = None,
126-
rustdoc = True,
127+
add_flags_for_binary = True,
128+
include_link_flags = False,
127129
force_depend_on_objects = is_test,
128130
skip_expanding_rustc_env = True,
129131
)

test/unit/rustdoc/rustdoc_build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
fn main() {
22
println!("cargo:rustc-env=CONST=xyz");
3+
if cfg!(target_os = "macos") {
4+
println!("cargo:rustc-link-lib=dylib=c++")
5+
} else if cfg!(target_os = "linux") {
6+
println!("cargo:rustc-link-lib=dylib=stdc++")
7+
}
38
}

0 commit comments

Comments
 (0)