From ac986620554a1a90b8e367a0a4b7f2c459507950 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 16:22:18 -0700 Subject: [PATCH 01/22] Unwrap link --- src/items/external-blocks.md | 120 ++++++++++------------------------- 1 file changed, 33 insertions(+), 87 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index b60cb4505..6b64bbb59 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -197,52 +197,37 @@ r[items.extern.attributes.link] ### The `link` attribute r[items.extern.attributes.link.intro] -The *`link` attribute* specifies the name of a native library that the -compiler should link with for the items within an `extern` block. +The *`link` attribute* specifies the name of a native library that the compiler should link with for the items within an `extern` block. r[items.extern.attributes.link.syntax] -It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the -name of the native library to link. The `kind` key is an optional value which -specifies the kind of library with the following possible values: +It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the name of the native library to link. The `kind` key is an optional value which specifies the kind of library with the following possible values: r[items.extern.attributes.link.dylib] -- `dylib` --- Indicates a dynamic library. This is the default if `kind` is not - specified. +- `dylib` --- Indicates a dynamic library. This is the default if `kind` is not specified. r[items.extern.attributes.link.static] - `static` --- Indicates a static library. r[items.extern.attributes.link.framework] -- `framework` --- Indicates a macOS framework. This is only valid for macOS - targets. +- `framework` --- Indicates a macOS framework. This is only valid for macOS targets. r[items.extern.attributes.link.raw-dylib] -- `raw-dylib` --- Indicates a dynamic library where the compiler will generate - an import library to link against (see [`dylib` versus `raw-dylib`] below - for details). This is only valid for Windows targets. +- `raw-dylib` --- Indicates a dynamic library where the compiler will generate an import library to link against (see [`dylib` versus `raw-dylib`] below for details). This is only valid for Windows targets. r[items.extern.attributes.link.name-requirement] The `name` key must be included if `kind` is specified. r[items.extern.attributes.link.modifiers] -The optional `modifiers` argument is a way to specify linking modifiers for the -library to link. +The optional `modifiers` argument is a way to specify linking modifiers for the library to link. r[items.extern.attributes.link.modifiers.syntax] -Modifiers are specified as a comma-delimited string with each modifier prefixed -with either a `+` or `-` to indicate that the modifier is enabled or disabled, -respectively. +Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. r[items.extern.attributes.link.modifiers.multiple] -Specifying multiple `modifiers` arguments in a single `link` attribute, -or multiple identical modifiers in the same `modifiers` argument is not currently supported. \ -Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")]`. +Specifying multiple `modifiers` arguments in a single `link` attribute, or multiple identical modifiers in the same `modifiers` argument is not currently supported. \ Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")]`. r[items.extern.attributes.link.wasm_import_module] -The `wasm_import_module` key may be used to specify the [WebAssembly module] -name for the items within an `extern` block when importing symbols from the -host environment. The default module name is `env` if `wasm_import_module` is -not specified. +The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. ```rust,ignore @@ -263,30 +248,21 @@ unsafe extern { ``` r[items.extern.attributes.link.empty-block] -It is valid to add the `link` attribute on an empty extern block. You can use -this to satisfy the linking requirements of extern blocks elsewhere in your -code (including upstream crates) instead of adding the attribute to each extern -block. +It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. r[items.extern.attributes.link.modifiers.bundle] #### Linking modifiers: `bundle` r[items.extern.attributes.link.modifiers.bundle.allowed-kinds] -This modifier is only compatible with the `static` linking kind. -Using any other kind will result in a compiler error. +This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. r[items.extern.attributes.link.modifiers.bundle.behavior] -When building a rlib or staticlib `+bundle` means that the native static library -will be packed into the rlib or staticlib archive, and then retrieved from there -during linking of the final binary. +When building a rlib or staticlib `+bundle` means that the native static library will be packed into the rlib or staticlib archive, and then retrieved from there during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.behavior-negative] -When building a rlib `-bundle` means that the native static library is registered as a dependency -of that rlib "by name", and object files from it are included only during linking of the final -binary, the file search by that name is also performed during final linking. \ -When building a staticlib `-bundle` means that the native static library is simply not included -into the archive and some higher level build system will need to add it later during linking of -the final binary. +When building a rlib `-bundle` means that the native static library is registered as a dependency of that rlib "by name", and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking. + +When building a staticlib `-bundle` means that the native static library is simply not included into the archive and some higher level build system will need to add it later during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.no-effect] This modifier has no effect when building other targets like executables or dynamic libraries. @@ -294,25 +270,21 @@ This modifier has no effect when building other targets like executables or dyna r[items.extern.attributes.link.modifiers.bundle.default] The default for this modifier is `+bundle`. -More implementation details about this modifier can be found in -[`bundle` documentation for rustc]. +More implementation details about this modifier can be found in [`bundle` documentation for rustc]. r[items.extern.attributes.link.modifiers.whole-archive] #### Linking modifiers: `whole-archive` r[items.extern.attributes.link.modifiers.whole-archive.allowed-kinds] -This modifier is only compatible with the `static` linking kind. -Using any other kind will result in a compiler error. +This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. r[items.extern.attributes.link.modifiers.whole-archive.behavior] -`+whole-archive` means that the static library is linked as a whole archive -without throwing any object files away. +`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. r[items.extern.attributes.link.modifiers.whole-archive.default] The default for this modifier is `-whole-archive`. -More implementation details about this modifier can be found in -[`whole-archive` documentation for rustc]. +More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. r[items.extern.attributes.link.modifiers.verbatim] ### Linking modifiers: `verbatim` @@ -321,75 +293,49 @@ r[items.extern.attributes.link.modifiers.verbatim.allowed-kinds] This modifier is compatible with all linking kinds. r[items.extern.attributes.link.modifiers.verbatim.behavior] -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes -(like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the -linker. +`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. r[items.extern.attributes.link.modifiers.verbatim.behavior-negative] -`-verbatim` means that rustc will either add a target-specific prefix and suffix to the library -name before passing it to linker, or won't prevent linker from implicitly adding it. +`-verbatim` means that rustc will either add a target-specific prefix and suffix to the library name before passing it to linker, or won't prevent linker from implicitly adding it. r[items.extern.attributes.link.modifiers.verbatim.default] The default for this modifier is `-verbatim`. -More implementation details about this modifier can be found in -[`verbatim` documentation for rustc]. +More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. r[items.extern.attributes.link.kind-raw-dylib] #### `dylib` versus `raw-dylib` r[items.extern.attributes.link.kind-raw-dylib.intro] -On Windows, linking against a dynamic library requires that an import library -is provided to the linker: this is a special static library that declares all -of the symbols exported by the dynamic library in such a way that the linker -knows that they have to be dynamically loaded at runtime. +On Windows, linking against a dynamic library requires that an import library is provided to the linker: this is a special static library that declares all of the symbols exported by the dynamic library in such a way that the linker knows that they have to be dynamically loaded at runtime. r[items.extern.attributes.link.kind-raw-dylib.import] -Specifying `kind = "dylib"` instructs the Rust compiler to link an import -library based on the `name` key. The linker will then use its normal library -resolution logic to find that import library. Alternatively, specifying -`kind = "raw-dylib"` instructs the compiler to generate an import library -during compilation and provide that to the linker instead. +Specifying `kind = "dylib"` instructs the Rust compiler to link an import library based on the `name` key. The linker will then use its normal library resolution logic to find that import library. Alternatively, specifying `kind = "raw-dylib"` instructs the compiler to generate an import library during compilation and provide that to the linker instead. r[items.extern.attributes.link.kind-raw-dylib.platform-specific] -`raw-dylib` is only supported on Windows. Using it when targeting other -platforms will result in a compiler error. +`raw-dylib` is only supported on Windows. Using it when targeting other platforms will result in a compiler error. r[items.extern.attributes.link.import_name_type] #### The `import_name_type` key r[items.extern.attributes.link.import_name_type.intro] -On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix -and/or suffix added) to indicate their calling convention. For example, a -`stdcall` calling convention function with the name `fn1` that has no arguments -would be decorated as `_fn1@0`. However, the [PE Format] does also permit names -to have no prefix or be undecorated. Additionally, the MSVC and GNU toolchains -use different decorations for the same calling conventions which means, by -default, some Win32 functions cannot be called using the `raw-dylib` link kind -via the GNU toolchain. +On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix and/or suffix added) to indicate their calling convention. For example, a `stdcall` calling convention function with the name `fn1` that has no arguments would be decorated as `_fn1@0`. However, the [PE Format] does also permit names to have no prefix or be undecorated. Additionally, the MSVC and GNU toolchains use different decorations for the same calling conventions which means, by default, some Win32 functions cannot be called using the `raw-dylib` link kind via the GNU toolchain. r[items.extern.attributes.link.import_name_type.values] -To allow for these differences, when using the `raw-dylib` link kind you may -also specify the `import_name_type` key with one of the following values to -change how functions are named in the generated import library: - -* `decorated`: The function name will be fully-decorated using the MSVC - toolchain format. -* `noprefix`: The function name will be decorated using the MSVC toolchain - format, but skipping the leading `?`, `@`, or optionally `_`. +To allow for these differences, when using the `raw-dylib` link kind you may also specify the `import_name_type` key with one of the following values to change how functions are named in the generated import library: + +* `decorated`: The function name will be fully-decorated using the MSVC toolchain format. +* `noprefix`: The function name will be decorated using the MSVC toolchain format, but skipping the leading `?`, `@`, or optionally `_`. * `undecorated`: The function name will not be decorated. r[items.extern.attributes.link.import_name_type.default] -If the `import_name_type` key is not specified, then the function name will be -fully-decorated using the target toolchain's format. +If the `import_name_type` key is not specified, then the function name will be fully-decorated using the target toolchain's format. r[items.extern.attributes.link.import_name_type.variables] -Variables are never decorated and so the `import_name_type` key has no effect on -how they are named in the generated import library. +Variables are never decorated and so the `import_name_type` key has no effect on how they are named in the generated import library. r[items.extern.attributes.link.import_name_type.platform-specific] -The `import_name_type` key is only supported on x86 Windows. Using it when -targeting other platforms will result in a compiler error. +The `import_name_type` key is only supported on x86 Windows. Using it when targeting other platforms will result in a compiler error. r[items.extern.attributes.link_name] ### The `link_name` attribute From 05591a3b9f0d3753e3050f584d4e26bbeae663ab Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 16:26:37 -0700 Subject: [PATCH 02/22] Link "attribute" --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 6b64bbb59..9add224a9 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -197,7 +197,7 @@ r[items.extern.attributes.link] ### The `link` attribute r[items.extern.attributes.link.intro] -The *`link` attribute* specifies the name of a native library that the compiler should link with for the items within an `extern` block. +The *`link` [attribute][attributes]* specifies the name of a native library that the compiler should link with for the items within an `extern` block. r[items.extern.attributes.link.syntax] It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the name of the native library to link. The `kind` key is an optional value which specifies the kind of library with the following possible values: From c62f29c6be82c401700708abee96509bfc4670a3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 16:27:29 -0700 Subject: [PATCH 03/22] Move link example to the intro --- src/items/external-blocks.md | 37 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 9add224a9..f446ce1c9 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -199,6 +199,25 @@ r[items.extern.attributes.link] r[items.extern.attributes.link.intro] The *`link` [attribute][attributes]* specifies the name of a native library that the compiler should link with for the items within an `extern` block. +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "crypto")] +> unsafe extern { +> // … +> } +> +> #[link(name = "CoreFoundation", kind = "framework")] +> unsafe extern { +> // … +> } +> +> #[link(wasm_import_module = "foo")] +> unsafe extern { +> // … +> } +> ``` + r[items.extern.attributes.link.syntax] It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the name of the native library to link. The `kind` key is an optional value which specifies the kind of library with the following possible values: @@ -229,24 +248,6 @@ Specifying multiple `modifiers` arguments in a single `link` attribute, or multi r[items.extern.attributes.link.wasm_import_module] The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. - -```rust,ignore -#[link(name = "crypto")] -unsafe extern { - // … -} - -#[link(name = "CoreFoundation", kind = "framework")] -unsafe extern { - // … -} - -#[link(wasm_import_module = "foo")] -unsafe extern { - // … -} -``` - r[items.extern.attributes.link.empty-block] It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. From 895c0c6911e0836a10e609d5dcf9de6b7dd1f49f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 16:51:39 -0700 Subject: [PATCH 04/22] Fix wrong heading depth for `verbatim` --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index f446ce1c9..04c09b2a1 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -288,7 +288,7 @@ The default for this modifier is `-whole-archive`. More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. r[items.extern.attributes.link.modifiers.verbatim] -### Linking modifiers: `verbatim` +#### Linking modifiers: `verbatim` r[items.extern.attributes.link.modifiers.verbatim.allowed-kinds] This modifier is compatible with all linking kinds. From 7ab3c2c76f6dd5d03178cd27d3243e81cfdf0a29 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 16:52:51 -0700 Subject: [PATCH 05/22] Rework items.extern.attributes.link.syntax The old text was missing some keys. This adds the keys as a list, with some more explicit organization. --- src/items/external-blocks.md | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 04c09b2a1..6b4550156 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -219,7 +219,24 @@ The *`link` [attribute][attributes]* specifies the name of a native library that > ``` r[items.extern.attributes.link.syntax] -It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the name of the native library to link. The `kind` key is an optional value which specifies the kind of library with the following possible values: +The `link` attribute uses the [MetaListNameValueStr] syntax to specify its inputs. It accepts the following keys: + +- [`name`][items.extern.attributes.link.name] --- the name of the native library to link. +- [`kind`][items.extern.attributes.link.kinds] --- the kind of library. +- [`modifiers`][items.extern.attributes.link.modifiers] --- modifiers that change the behavior of how the library is linked. +- [`wasm_import_module`][items.extern.attributes.link.wasm_import_module] --- specifies the WebAssembly module name. +- [`import_name_type`][items.extern.attributes.link.import_name_type] --- on x86 Windows, this changes how functions are named. + +r[items.extern.attributes.link.name] +#### The `name` key + + + +r[items.extern.attributes.link.name.requirement] +The `name` key must be included unless `wasm_import_module` is used. + +r[items.extern.attributes.link.kinds] +#### The `kind` key r[items.extern.attributes.link.dylib] - `dylib` --- Indicates a dynamic library. This is the default if `kind` is not specified. @@ -233,10 +250,10 @@ r[items.extern.attributes.link.framework] r[items.extern.attributes.link.raw-dylib] - `raw-dylib` --- Indicates a dynamic library where the compiler will generate an import library to link against (see [`dylib` versus `raw-dylib`] below for details). This is only valid for Windows targets. -r[items.extern.attributes.link.name-requirement] -The `name` key must be included if `kind` is specified. - r[items.extern.attributes.link.modifiers] +#### The `modifiers` key + +r[items.extern.attributes.link.modifiers.intro] The optional `modifiers` argument is a way to specify linking modifiers for the library to link. r[items.extern.attributes.link.modifiers.syntax] @@ -246,6 +263,9 @@ r[items.extern.attributes.link.modifiers.multiple] Specifying multiple `modifiers` arguments in a single `link` attribute, or multiple identical modifiers in the same `modifiers` argument is not currently supported. \ Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")]`. r[items.extern.attributes.link.wasm_import_module] +#### The `wasm_import_module` key + +r[items.extern.attributes.link.wasm_import_module.behavior] The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. r[items.extern.attributes.link.empty-block] From 4fa2cf84be7c7986cc6803798e006c7cb491f453 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 16:53:19 -0700 Subject: [PATCH 06/22] Move items.extern.attributes.link.empty-block It was in the wrong section. --- src/items/external-blocks.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 6b4550156..74c998c50 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -227,6 +227,9 @@ The `link` attribute uses the [MetaListNameValueStr] syntax to specify its input - [`wasm_import_module`][items.extern.attributes.link.wasm_import_module] --- specifies the WebAssembly module name. - [`import_name_type`][items.extern.attributes.link.import_name_type] --- on x86 Windows, this changes how functions are named. +r[items.extern.attributes.link.empty-block] +It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. + r[items.extern.attributes.link.name] #### The `name` key @@ -268,9 +271,6 @@ r[items.extern.attributes.link.wasm_import_module] r[items.extern.attributes.link.wasm_import_module.behavior] The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. -r[items.extern.attributes.link.empty-block] -It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. - r[items.extern.attributes.link.modifiers.bundle] #### Linking modifiers: `bundle` From 0f82c08e48ac9d58b9a9a2b536414851efc176c1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:40:30 -0700 Subject: [PATCH 07/22] Add ABI to the example There is a warning without it. --- src/items/external-blocks.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 74c998c50..b853c54dc 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -203,17 +203,17 @@ The *`link` [attribute][attributes]* specifies the name of a native library that > > ```rust,ignore > #[link(name = "crypto")] -> unsafe extern { +> unsafe extern "C" { > // … > } > > #[link(name = "CoreFoundation", kind = "framework")] -> unsafe extern { +> unsafe extern "C" { > // … > } > > #[link(wasm_import_module = "foo")] -> unsafe extern { +> unsafe extern "C" { > // … > } > ``` From d840b52b6d93eb173844e2f95fb1f2974459efef Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:40:47 -0700 Subject: [PATCH 08/22] Clarify that link names cannot be repeated --- src/items/external-blocks.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index b853c54dc..a6cfccc49 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -227,6 +227,8 @@ The `link` attribute uses the [MetaListNameValueStr] syntax to specify its input - [`wasm_import_module`][items.extern.attributes.link.wasm_import_module] --- specifies the WebAssembly module name. - [`import_name_type`][items.extern.attributes.link.import_name_type] --- on x86 Windows, this changes how functions are named. +None of the keys may be specified more than once. + r[items.extern.attributes.link.empty-block] It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. From 5f8ee42d7b60191a43471c657162da2ccd3d6cfe Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:41:08 -0700 Subject: [PATCH 09/22] Add link allowed-positions and duplicates --- src/items/external-blocks.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index a6cfccc49..647e13488 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -229,6 +229,15 @@ The `link` attribute uses the [MetaListNameValueStr] syntax to specify its input None of the keys may be specified more than once. +r[items.extern.attributes.link.allowed-positions] +The `link` attribute may be applied to [`extern` blocks]. + +> [!NOTE] +> `rustc` currently warns in other positions, but this may be rejected in the future. + +r[items.extern.attributes.link.duplicates] +The `link` attribute may be specified multiple times, and the corresponding linking instructions for each attribute will be passed to the linker. + r[items.extern.attributes.link.empty-block] It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. @@ -430,3 +439,4 @@ restrictions as [regular function parameters]. [statics]: static-items.md [unwind-behavior]: functions.md#unwinding [value namespace]: ../names/namespaces.md +[`extern` blocks]: external-blocks.md From b7cb91ea8d210ca4a05e3177f2a5ce3784d32e6b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:42:10 -0700 Subject: [PATCH 10/22] Add link `name` intro --- src/items/external-blocks.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 647e13488..774bf0f30 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -244,7 +244,12 @@ It is valid to add the `link` attribute on an empty extern block. You can use th r[items.extern.attributes.link.name] #### The `name` key - +r[items.extern.attributes.link.name.intro] +The `name` key specifies the name of the library to link. + + + + r[items.extern.attributes.link.name.requirement] The `name` key must be included unless `wasm_import_module` is used. From 683fc499139fcff996aef32d0c4ae24e9fd444f8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:43:14 -0700 Subject: [PATCH 11/22] Rework link kind to not use a list, and add examples --- src/items/external-blocks.md | 51 +++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 774bf0f30..a0d441543 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -222,7 +222,7 @@ r[items.extern.attributes.link.syntax] The `link` attribute uses the [MetaListNameValueStr] syntax to specify its inputs. It accepts the following keys: - [`name`][items.extern.attributes.link.name] --- the name of the native library to link. -- [`kind`][items.extern.attributes.link.kinds] --- the kind of library. +- [`kind`][items.extern.attributes.link.kind] --- the kind of library. - [`modifiers`][items.extern.attributes.link.modifiers] --- modifiers that change the behavior of how the library is linked. - [`wasm_import_module`][items.extern.attributes.link.wasm_import_module] --- specifies the WebAssembly module name. - [`import_name_type`][items.extern.attributes.link.import_name_type] --- on x86 Windows, this changes how functions are named. @@ -254,20 +254,51 @@ The `name` key specifies the name of the library to link. r[items.extern.attributes.link.name.requirement] The `name` key must be included unless `wasm_import_module` is used. -r[items.extern.attributes.link.kinds] +r[items.extern.attributes.link.kind] #### The `kind` key -r[items.extern.attributes.link.dylib] -- `dylib` --- Indicates a dynamic library. This is the default if `kind` is not specified. +r[items.extern.attributes.link.kind.intro] +The `kind` key specifies the kind of the library. -r[items.extern.attributes.link.static] -- `static` --- Indicates a static library. +r[items.extern.attributes.link.kind.dylib] +The `dylib` kind indicates a dynamic library. This is the default if `kind` is not specified. -r[items.extern.attributes.link.framework] -- `framework` --- Indicates a macOS framework. This is only valid for macOS targets. +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "example", kind = "dylib")] +> unsafe extern "C" {} +> ``` + +r[items.extern.attributes.link.kind.static] +The `static` kind indicates a static library. + +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "example", kind = "static")] +> unsafe extern "C" {} +> ``` + +r[items.extern.attributes.link.kind.framework] +The `framework` kind indicates a macOS framework. This is only valid for macOS targets. -r[items.extern.attributes.link.raw-dylib] -- `raw-dylib` --- Indicates a dynamic library where the compiler will generate an import library to link against (see [`dylib` versus `raw-dylib`] below for details). This is only valid for Windows targets. +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "CoreFoundation", kind = "framework")] +> unsafe extern "C" {} +> ``` + +r[items.extern.attributes.link.kind.raw-dylib] +The `raw-dylib` kind indicates a dynamic library where the compiler will generate an import library to link against (see [`dylib` versus `raw-dylib`] below for details). This is only valid for Windows targets. + +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "example", kind = "raw-dylib")] +> unsafe extern "C" {} +> ``` r[items.extern.attributes.link.modifiers] #### The `modifiers` key From cca77414880015a02b31ea2a828dd58457f221de Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:44:21 -0700 Subject: [PATCH 12/22] Move dylib vs raw-dylib into a note block This doesn't look like behavioral rules, but more of an explanation. Also move it to the `raw-dylib` section, since it seems mostly relevant there. --- src/items/external-blocks.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index a0d441543..aa9df3571 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -300,6 +300,13 @@ The `raw-dylib` kind indicates a dynamic library where the compiler will generat > unsafe extern "C" {} > ``` +> [!NOTE] +> ##### `dylib` versus `raw-dylib` +> +> On Windows, linking against a dynamic library requires that an import library is provided to the linker. This is a special static library that declares all of the symbols exported by the dynamic library in such a way that the linker knows that they have to be dynamically loaded at runtime. +> +> Specifying `kind = "dylib"` instructs the Rust compiler to link an import library based on the `name` key. The linker will then use its normal library resolution logic to find that import library. Alternatively, specifying `kind = "raw-dylib"` instructs the compiler to generate an import library during compilation and provide that to the linker instead. + r[items.extern.attributes.link.modifiers] #### The `modifiers` key @@ -371,14 +378,7 @@ The default for this modifier is `-verbatim`. More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. -r[items.extern.attributes.link.kind-raw-dylib] -#### `dylib` versus `raw-dylib` - -r[items.extern.attributes.link.kind-raw-dylib.intro] -On Windows, linking against a dynamic library requires that an import library is provided to the linker: this is a special static library that declares all of the symbols exported by the dynamic library in such a way that the linker knows that they have to be dynamically loaded at runtime. -r[items.extern.attributes.link.kind-raw-dylib.import] -Specifying `kind = "dylib"` instructs the Rust compiler to link an import library based on the `name` key. The linker will then use its normal library resolution logic to find that import library. Alternatively, specifying `kind = "raw-dylib"` instructs the compiler to generate an import library during compilation and provide that to the linker instead. r[items.extern.attributes.link.kind-raw-dylib.platform-specific] `raw-dylib` is only supported on Windows. Using it when targeting other platforms will result in a compiler error. From 04119ec59688fc67ad60e73c68c8ea643ea8b7ba Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:44:41 -0700 Subject: [PATCH 13/22] Delete raw-dylib platform-specific This is already specified in the raw-dylib section. --- src/items/external-blocks.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index aa9df3571..dc666623a 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -380,8 +380,6 @@ More implementation details about this modifier can be found in [`verbatim` docu -r[items.extern.attributes.link.kind-raw-dylib.platform-specific] -`raw-dylib` is only supported on Windows. Using it when targeting other platforms will result in a compiler error. r[items.extern.attributes.link.import_name_type] #### The `import_name_type` key From 359f9a17166473f4ae0069e6073632a81eb2915d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:47:36 -0700 Subject: [PATCH 14/22] Small tweaks to link modifiers Add an example, and slight rewording. --- src/items/external-blocks.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index dc666623a..7e6fb90de 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -313,11 +313,21 @@ r[items.extern.attributes.link.modifiers] r[items.extern.attributes.link.modifiers.intro] The optional `modifiers` argument is a way to specify linking modifiers for the library to link. +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "mylib", kind = "static", modifiers = "+whole-archive")] +> unsafe extern "C" {} +> ``` + r[items.extern.attributes.link.modifiers.syntax] Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. -r[items.extern.attributes.link.modifiers.multiple] -Specifying multiple `modifiers` arguments in a single `link` attribute, or multiple identical modifiers in the same `modifiers` argument is not currently supported. \ Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")]`. +r[items.extern.attributes.link.modifiers.once] +The `modifiers` argument may only be specified once. + +r[items.extern.attributes.link.modifiers.duplicates] +Duplicate modifiers are not allowed within a `modifiers` argument. r[items.extern.attributes.link.wasm_import_module] #### The `wasm_import_module` key From 4763d74a005ffbd47924e5accf9a538837d87ff9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 17:50:15 -0700 Subject: [PATCH 15/22] Move wasm_import_module and add example It was in the middle of the modifiers section. --- src/items/external-blocks.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 7e6fb90de..e4fec7ba3 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -329,12 +329,6 @@ The `modifiers` argument may only be specified once. r[items.extern.attributes.link.modifiers.duplicates] Duplicate modifiers are not allowed within a `modifiers` argument. -r[items.extern.attributes.link.wasm_import_module] -#### The `wasm_import_module` key - -r[items.extern.attributes.link.wasm_import_module.behavior] -The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. - r[items.extern.attributes.link.modifiers.bundle] #### Linking modifiers: `bundle` @@ -388,8 +382,18 @@ The default for this modifier is `-verbatim`. More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. +r[items.extern.attributes.link.wasm_import_module] +#### The `wasm_import_module` key +r[items.extern.attributes.link.wasm_import_module.behavior] +The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(wasm_import_module = "foo")] +> unsafe extern "C" {} +> ``` r[items.extern.attributes.link.import_name_type] #### The `import_name_type` key From 6c428bf5070b7adfcf2994fa91d583445ef3b98c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Jun 2025 18:00:14 -0700 Subject: [PATCH 16/22] Add more link examples --- src/items/external-blocks.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index e4fec7ba3..36f3a4d98 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -332,6 +332,13 @@ Duplicate modifiers are not allowed within a `modifiers` argument. r[items.extern.attributes.link.modifiers.bundle] #### Linking modifiers: `bundle` +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "mylib", kind = "static", modifiers = "+bundle")] +> unsafe extern "C" {} +> ``` + r[items.extern.attributes.link.modifiers.bundle.allowed-kinds] This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. @@ -354,6 +361,13 @@ More implementation details about this modifier can be found in [`bundle` docume r[items.extern.attributes.link.modifiers.whole-archive] #### Linking modifiers: `whole-archive` +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "mylib", kind = "static", modifiers = "+whole-archive")] +> unsafe extern "C" {} +> ``` + r[items.extern.attributes.link.modifiers.whole-archive.allowed-kinds] This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. @@ -368,6 +382,13 @@ More implementation details about this modifier can be found in [`whole-archive` r[items.extern.attributes.link.modifiers.verbatim] #### Linking modifiers: `verbatim` +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "mylib", kind = "static", modifiers = "+verbatim")] +> unsafe extern "C" {} +> ``` + r[items.extern.attributes.link.modifiers.verbatim.allowed-kinds] This modifier is compatible with all linking kinds. @@ -398,6 +419,13 @@ The `wasm_import_module` key may be used to specify the [WebAssembly module] nam r[items.extern.attributes.link.import_name_type] #### The `import_name_type` key +> [!EXAMPLE] +> +> ```rust,ignore +> #[link(name = "mylib", kind = "raw-dylib", import_name_type = "undecorated")] +> unsafe extern "C" {} +> ``` + r[items.extern.attributes.link.import_name_type.intro] On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix and/or suffix added) to indicate their calling convention. For example, a `stdcall` calling convention function with the name `fn1` that has no arguments would be decorated as `_fn1@0`. However, the [PE Format] does also permit names to have no prefix or be undecorated. Additionally, the MSVC and GNU toolchains use different decorations for the same calling conventions which means, by default, some Win32 functions cannot be called using the `raw-dylib` link kind via the GNU toolchain. From cf330087388f585fa86f84151b271c1fec471d1f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 11:20:59 -0700 Subject: [PATCH 17/22] Tweak wording of `dylib` versus `raw-dylib` Dropping the use of "Rust compiler". --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 36f3a4d98..3d5a9d7c3 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -305,7 +305,7 @@ The `raw-dylib` kind indicates a dynamic library where the compiler will generat > > On Windows, linking against a dynamic library requires that an import library is provided to the linker. This is a special static library that declares all of the symbols exported by the dynamic library in such a way that the linker knows that they have to be dynamically loaded at runtime. > -> Specifying `kind = "dylib"` instructs the Rust compiler to link an import library based on the `name` key. The linker will then use its normal library resolution logic to find that import library. Alternatively, specifying `kind = "raw-dylib"` instructs the compiler to generate an import library during compilation and provide that to the linker instead. +> Specifying `kind = "dylib"` links an import library based on the `name` key. The linker will then use its normal library resolution logic to find that import library. Alternatively, specifying `kind = "raw-dylib"` generates an import library during compilation and provide that to the linker instead. r[items.extern.attributes.link.modifiers] #### The `modifiers` key From 1e0bb5c9ee2256bfce5e39e1eeaec562ac453891 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 11:32:19 -0700 Subject: [PATCH 18/22] Reword link allowed-kinds This just simplifies the wording, and links to the relevant section. --- src/items/external-blocks.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 3d5a9d7c3..19e6a96d9 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -340,7 +340,7 @@ r[items.extern.attributes.link.modifiers.bundle] > ``` r[items.extern.attributes.link.modifiers.bundle.allowed-kinds] -This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. +The `bundle` modifier may only be used with [`static` linking]. r[items.extern.attributes.link.modifiers.bundle.behavior] When building a rlib or staticlib `+bundle` means that the native static library will be packed into the rlib or staticlib archive, and then retrieved from there during linking of the final binary. @@ -369,7 +369,7 @@ r[items.extern.attributes.link.modifiers.whole-archive] > ``` r[items.extern.attributes.link.modifiers.whole-archive.allowed-kinds] -This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. +The `whole-archive` modifier may only be used with [`static` linking]. r[items.extern.attributes.link.modifiers.whole-archive.behavior] `+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. @@ -516,3 +516,4 @@ restrictions as [regular function parameters]. [unwind-behavior]: functions.md#unwinding [value namespace]: ../names/namespaces.md [`extern` blocks]: external-blocks.md +[`static` linking]: link.staticlib From 1eaabadacbd117b149f3237cb54cc6f680d20a6a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 11:32:39 -0700 Subject: [PATCH 19/22] Move implementation note into a note block --- src/items/external-blocks.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 19e6a96d9..2f998f49f 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -356,7 +356,8 @@ This modifier has no effect when building other targets like executables or dyna r[items.extern.attributes.link.modifiers.bundle.default] The default for this modifier is `+bundle`. -More implementation details about this modifier can be found in [`bundle` documentation for rustc]. +> [!NOTE] +> More implementation details about this modifier can be found in [`bundle` documentation for rustc]. r[items.extern.attributes.link.modifiers.whole-archive] #### Linking modifiers: `whole-archive` @@ -377,7 +378,8 @@ r[items.extern.attributes.link.modifiers.whole-archive.behavior] r[items.extern.attributes.link.modifiers.whole-archive.default] The default for this modifier is `-whole-archive`. -More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. +> [!NOTE] +> More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. r[items.extern.attributes.link.modifiers.verbatim] #### Linking modifiers: `verbatim` @@ -401,7 +403,8 @@ r[items.extern.attributes.link.modifiers.verbatim.behavior-negative] r[items.extern.attributes.link.modifiers.verbatim.default] The default for this modifier is `-verbatim`. -More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. +> [!NOTE] +> More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. r[items.extern.attributes.link.wasm_import_module] #### The `wasm_import_module` key From 0df56939cec3c3a2070a30ab139d836b32bf3cb3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 11:33:01 -0700 Subject: [PATCH 20/22] Add comma to introductory clause for clarity --- src/items/external-blocks.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 2f998f49f..0d5182a9c 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -343,12 +343,12 @@ r[items.extern.attributes.link.modifiers.bundle.allowed-kinds] The `bundle` modifier may only be used with [`static` linking]. r[items.extern.attributes.link.modifiers.bundle.behavior] -When building a rlib or staticlib `+bundle` means that the native static library will be packed into the rlib or staticlib archive, and then retrieved from there during linking of the final binary. +When building a rlib or staticlib, `+bundle` means that the native static library will be packed into the rlib or staticlib archive, and then retrieved from there during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.behavior-negative] -When building a rlib `-bundle` means that the native static library is registered as a dependency of that rlib "by name", and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking. +When building a rlib, `-bundle` means that the native static library is registered as a dependency of that rlib "by name", and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking. -When building a staticlib `-bundle` means that the native static library is simply not included into the archive and some higher level build system will need to add it later during linking of the final binary. +When building a staticlib, `-bundle` means that the native static library is simply not included into the archive and some higher level build system will need to add it later during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.no-effect] This modifier has no effect when building other targets like executables or dynamic libraries. From 3a068f7f3f690c5534359e4fa1a5d861c93cc5a8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 11:33:13 -0700 Subject: [PATCH 21/22] Specify what "this" is --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 0d5182a9c..ac0b7eab5 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -351,7 +351,7 @@ When building a rlib, `-bundle` means that the native static library is register When building a staticlib, `-bundle` means that the native static library is simply not included into the archive and some higher level build system will need to add it later during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.no-effect] -This modifier has no effect when building other targets like executables or dynamic libraries. +The `bundle` modifier has no effect when building other targets like executables or dynamic libraries. r[items.extern.attributes.link.modifiers.bundle.default] The default for this modifier is `+bundle`. From e368f0b80c397f951929e9118566a1d306f37041 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 11:33:30 -0700 Subject: [PATCH 22/22] Drop use of "rustc" --- src/items/external-blocks.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index ac0b7eab5..d153fae4b 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -395,10 +395,10 @@ r[items.extern.attributes.link.modifiers.verbatim.allowed-kinds] This modifier is compatible with all linking kinds. r[items.extern.attributes.link.modifiers.verbatim.behavior] -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. +`+verbatim` means that the compiler won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. r[items.extern.attributes.link.modifiers.verbatim.behavior-negative] -`-verbatim` means that rustc will either add a target-specific prefix and suffix to the library name before passing it to linker, or won't prevent linker from implicitly adding it. +`-verbatim` means that the compiler will either add a target-specific prefix and suffix to the library name before passing it to linker, or won't prevent linker from implicitly adding it. r[items.extern.attributes.link.modifiers.verbatim.default] The default for this modifier is `-verbatim`.