Skip to content

Commit

Permalink
Merge branch 'master' into feat/indirect-branch-tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota authored Nov 12, 2024
2 parents c02cbac + 8384739 commit d9adeb9
Show file tree
Hide file tree
Showing 16 changed files with 76 additions and 46 deletions.
25 changes: 17 additions & 8 deletions .github/workflows/validate-content.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
name: Validate content
on:
push:
paths:
- docs/syntax_and_semantics/compile_time_flags.md
- .github/workflows/validate-content.yml
pull_request:
branches: [master, release/*]
paths:
- docs/syntax_and_semantics/compile_time_flags.md
- .github/workflows/validate-content.yml
schedule:
- cron: '0 5 * * 1' # Every Monday 5 AM UTC

jobs:
validate-flags:
name: Validate flags
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
- os: macos-latest
- os: windows-latest
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
steps:
- name: Download source
uses: actions/checkout@v4
- name: Install Crystal
uses: crystal-lang/install-crystal@v1
with:
crystal: nightly
- name: Download crystal repo
uses: actions/checkout@v4
with:
repository: crystal-lang/crystal
path: crystal
# If the PR goes against a release branch, we checkout that same release
# branch in the Crystal repo (names are identical).
ref: ${{ (startsWith(github.base_ref, 'release/') && github.base_ref) || 'master' }}
- name: Run test script
run: scripts/validate-flags.sh
env:
STDLIB_SRC: ./crystal/src
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ clean_all: clean clean_vendor
format_api_docs_links:
echo $(DOCS_FILES) | xargs sed -i -E -e 's@\bhttps?://(www\.)?crystal-lang\.org/api/([0-9]+(\.[0-9]+)+|latest|master)/([^ )]+\.html)\b@https://crystal-lang.org/api/\4@g'

.PHONY: format_code_blocks
format_code_blocks:
NO_COLOR=1 LINT=true make clean build 2>&1 | ./scripts/format-code-blocks.cr

.PHONY: help
help: ## Show this help
@echo
Expand Down
32 changes: 11 additions & 21 deletions docs/guides/static_linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,19 @@ macOS doesn't [officially support fully static linking](https://developer.apple.

### Windows

#### MSVC

Windows doesn't support fully static linking because the Win32 libraries are not available as static libraries.

Currently, static linking is the default mode of linking on Windows, and dynamic linking can be opted in via the `-Dpreview_dll` compile-time flag. In order to distinguish static libraries from DLL import libraries, when the compiler searches for a library `foo.lib` in a given directory, `foo-static.lib` will be attempted first while linking statically, and `foo-dynamic.lib` will be attempted first while linking dynamically. The official Windows packages are distributed with both static and DLL import libraries for all third-party dependencies, except for LLVM.
In order to distinguish static libraries from DLL import libraries, when the compiler searches for a library `foo.lib` in a given directory, `foo-static.lib` will be attempted first while linking statically, and `foo-dynamic.lib` will be attempted first while linking dynamically. The official Windows MSVC packages are distributed with both static and DLL import libraries for all third-party dependencies, except for LLVM, which is only available as an import library.

Static linking implies using the static version of Microsoft's Universal C Runtime (`/MT`), and dynamic linking implies the dynamic version (`/MD`); extra C libraries should be built with this in mind to avoid linker warnings about mixing CRT versions. There is currently no way to use the dynamic CRT while linking statically.

#### MinGW-w64

MinGW-w64 provides import libraries for the Win32 APIs and the C runtimes; therefore, unlike the MSVC toolchain, all libraries link against the C runtime dynamically, even for static builds.

Static linking implies using the static version of Microsoft's C runtime library (`/MT`), and dynamic linking implies the dynamic version (`/MD`); extra C libraries should be built with this in mind to avoid linker warnings about mixing CRT versions. There is currently no way to use the dynamic CRT while linking statically.
The default C runtime depends on MinGW-w64's build-time configuration, and this default is always called `libmsvcrt.a`. On an MSYS2 UCRT64 environment, this is a copy of `libucrt.a`, the Universal C Runtime, whereas on a MINGW64 environment, this is a copy of `libmsvcrt-os.a` instead, the old system MSVCRT runtime. This can be overridden using `--link-flags=-mcrtdll=ucrt` or `--link-flags=-mcrtdll=msvcrt-os`, provided the MinGW-w64 installation understands it.

## Identifying Static Dependencies

Expand All @@ -71,7 +79,7 @@ Most systems don't install static libraries by default, so you need to install t
First you have to know which libraries your program links against.

NOTE:
Static libraries have the file extension `.a` on POSIX and `.lib` on Windows. DLL import libraries on Windows also have the `.lib` extension.
Static libraries have the file extension `.a` on POSIX (including MinGW-w64) and `.lib` on Windows MSVC. DLL import libraries on Windows have the `.dll.a` extension for MinGW-w64 and `.lib` for MSVC.
Dynamic libraries have `.so` on Linux and most other POSIX platforms, `.dylib` on macOS and `.dll` on Windows.

On most POSIX systems the tool `ldd` shows which dynamic libraries an executable links to. The equivalent
Expand Down Expand Up @@ -116,21 +124,3 @@ In order to link this program statically, we need static versions of these three
NOTE:
The `*-alpine` docker images ship with static versions of all libraries used by the standard library.
If your program links no other libraries then adding the `--static` flag to the build command is all you need to link fully statically.

## Dynamic library lookup

The lookup paths of dynamic libraries at runtime can be controlled by the `CRYSTAL_LIBRARY_RPATH` environment variable during compilation. Currently this is supported on Linux and Windows.

### Linux

If `CRYSTAL_LIBRARY_RPATH` is defined during compilation, it is passed unmodified to the linker via an `-Wl,rpath` option. The exact behavior depends on the linker; usually, this is appended to the ELF executable's `DT_RUNPATH` or `DT_RPATH` dynamic tag entry. The special `$ORIGIN` / `$LIB` / `$PLATFORM` variables might not be supported on all platforms.

### Windows

The standard library supports experimental [DLL delay loading](https://learn.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded-dlls), and may alter the search order of DLLs by using delay loading.

If a `/DELAYLOAD` linker flag is passed for a given DLL, then the first time an executable loads a symbol from that DLL, it will attempt the semicolon-separated paths in the executable's `CRYSTAL_LIBRARY_RPATH` first, in the order they are declared, before the [default lookup order](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#search-order-for-unpackaged-apps). `$ORIGIN` inside `CRYSTAL_LIBRARY_RPATH` expands into the path of the running executable itself. For example, if `CRYSTAL_LIBRARY_RPATH=$ORIGIN\mylibs;C:\bar` during compilation, `--link-flags=/DELAYLOAD:calc.dll` is supplied, and the executable is located at `C:\foo\test.exe`, then the executable searches for `C:\foo\mylibs\calc.dll`, then `C:\bar\calc.dll`, and uses the default order afterwards.

Non-delay-loaded DLLs are loaded immediately upon program startup, and do not respect `CRYSTAL_LIBRARY_RPATH`.

By default, no DLLs are delay-loaded. However, if the `-Dpreview_win32_delay_load` compile-time flag is specified at compilation time, the compiler will detect all DLL dependencies from their import libraries, inserting a `/DELAYLOAD` linker flag per DLL during compilation.
2 changes: 1 addition & 1 deletion docs/man/required_libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Implementations for `Big` types such as [`BigInt`](https://crystal-lang.org/api/
| Library | Description | License |
|---------|-------------|---------|
| [GMP][libgmp] | GNU multiple precision arithmetic library. | [LGPL v3+ / GPL v2+](https://gmplib.org/manual/Copying)
| [MPIR][libmpir] | Multiple Precision Integers and Rationals, forked from GMP. Used on Windows. | [GPL-3.0](https://github.com/wbhart/mpir/blob/master/COPYING) and [LGPL-3.0](https://github.com/wbhart/mpir/blob/master/COPYING.LIB) |
| [MPIR][libmpir] | Multiple Precision Integers and Rationals, forked from GMP. Used on Windows MSVC. | [GPL-3.0](https://github.com/wbhart/mpir/blob/master/COPYING) and [LGPL-3.0](https://github.com/wbhart/mpir/blob/master/COPYING.LIB) |

### Internationalization conversion

Expand Down
2 changes: 1 addition & 1 deletion docs/syntax_and_semantics/annotations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ end
def method2(
@[MyAnnotation]
bar
bar,
)
end
Expand Down
2 changes: 1 addition & 1 deletion docs/syntax_and_semantics/block_forwarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ end
Or, combining the `&` and `->` syntaxes:

```crystal
twice &->{ puts "Hello" }
twice &-> { puts "Hello" }
```

Or:
Expand Down
2 changes: 1 addition & 1 deletion docs/syntax_and_semantics/c_bindings/callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ lib LibFoo
fun execute_callback
end
LibFoo.store_callback ->{ raise "OH NO!" }
LibFoo.store_callback -> { raise "OH NO!" }
LibFoo.execute_callback
```

Expand Down
6 changes: 3 additions & 3 deletions docs/syntax_and_semantics/closures.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Captured blocks and proc literals closure local variables and `self`. This is be

```crystal
x = 0
proc = ->{ x += 1; x }
proc = -> { x += 1; x }
proc.call # => 1
proc.call # => 2
x # => 2
Expand All @@ -15,7 +15,7 @@ Or with a proc returned from a method:
```crystal
def counter
x = 0
->{ x += 1; x }
-> { x += 1; x }
end
proc = counter
Expand Down Expand Up @@ -76,7 +76,7 @@ This also happens with regular proc literals, even if it's evident that the proc

```crystal
x = 1
->{ x = "hello" }
-> { x = "hello" }
x = 'a'
x # : Int32 | String | Char
Expand Down
2 changes: 0 additions & 2 deletions docs/syntax_and_semantics/compile_time_flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,7 @@ These flags enable or disable language features when building a Crystal program.
|-----------|-------------|
| `no_number_autocast` | Will not [autocast](autocasting.md#number-autocasting) numeric expressions, only literals |
| `no_restrictions_augmenter` | Disable enhanced restrictions augmenter. Introduced in 1.5 ([#12103](https://github.com/crystal-lang/crystal/pull/12103)).
| `preview_dll` | Enable dynamic linking on Windows; experimental |
| `preview_overload_order` | Enable more robust ordering between def overloads. Introduced in 1.6 ([#10711](https://github.com/crystal-lang/crystal/issues/10711)).
| `preview_win32_delay_load` | Delay-load all DLLs on Windows; experimental |
| `strict_multi_assign` | Enable strict semantics for [one-to-many assignment](assignment.md#one-to-many-assignment). Introduced in 1.3.0 ([#11145](https://github.com/crystal-lang/crystal/pull/11145), [#11545](https://github.com/crystal-lang/crystal/pull/11545))

### Codegen features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def foo(
# These are the named parameters:
a, b, c = 2,
# This is the double splat parameter:
**options
**options,
)
end
```
Expand Down
2 changes: 1 addition & 1 deletion docs/syntax_and_semantics/if_var.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ if @@a
end
a = nil
closure = ->{ a = "foo" }
closure = -> { a = "foo" }
if a
# here `a` can be nil
Expand Down
2 changes: 1 addition & 1 deletion docs/syntax_and_semantics/literals/proc.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A [Proc](https://crystal-lang.org/api/Proc.html) represents a function pointer w

```crystal
# A proc without parameters
->{ 1 } # Proc(Int32)
-> { 1 } # Proc(Int32)
# A proc with one parameter
->(x : Int32) { x.to_s } # Proc(Int32, String)
Expand Down
2 changes: 2 additions & 0 deletions docs/syntax_and_semantics/platform_support.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ Most typically, some parts of the standard library are not supported completely.
| Target | Description | Supported versions | Comment |
| ------ | ----------- | ------------------ | ------- |
| `x86_64-windows-msvc` | x64 Windows (MSVC) | 7+ | :material-circle-slice-7: tests<br> :material-checkbox-marked-circle: builds |
| `x86_64-windows-gnu` | x64 Windows (MinGW-w64) | 7+, MSYS2 `UCRT64` or `CLANG64` environment | :material-circle-slice-7: tests<br> :material-checkbox-marked-circle: builds |
| `aarch64-windows-msvc` | ARM64 Windows (MSVC) | 11+ | :material-selection-ellipse: tests<br> :material-selection-ellipse: builds |
| `aarch64-windows-gnu` | ARM64 Windows (MinGW-w64) | 11+, MSYS2 `CLANGARM64` environment | :material-selection-ellipse: tests<br> :material-selection-ellipse: builds |
| `aarch64-linux-android` | aarch64 Android | Bionic C runtime, API level 24+ | :material-selection-ellipse: tests<br> :material-selection-ellipse: builds |
| `x86_64-unknown-dragonfly` | x64 DragonFlyBSD | | :material-selection-ellipse: tests<br> :material-selection-ellipse: builds |
| `x86_64-unknown-netbsd` | x64 NetBSD | | :material-selection-ellipse: tests<br> :material-selection-ellipse: builds |
Expand Down
2 changes: 1 addition & 1 deletion docs/syntax_and_semantics/type_restrictions.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,5 +324,5 @@ end
foo(->(x : Int32, y : Int32) { x + y }) # => Tuple(Int32, Int32)
foo(->(x : Bool) { x ? 1 : 0 }) # => Tuple(Bool)
foo(->{ 1 }) # => Tuple()
foo(-> { 1 }) # => Tuple()
```
23 changes: 23 additions & 0 deletions scripts/format-code-block.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env crystal
#
# This script parses output from `mkdocs build --strict` to find ill-formatted
# code blocks and applies the updated formatting (from the formatter STDOUT).

io = STDIN
docs_path = Path["docs"]

loop do
line = io.gets || exit
line.starts_with?("WARNING - In file") || next
filename = line[/(?<=')[^']+(?=')/]? || next
filename = docs_path / filename

io.gets # skip -------- Input --------

input = IO::Delimited.new(io, "\n-------- Output --------\n").gets_to_end
output = IO::Delimited.new(io, "formatting 'STDIN' produced changes\n").gets_to_end

original_content = File.read(filename)
content = original_content.sub input, output
File.write(filename, content)
end
12 changes: 8 additions & 4 deletions scripts/validate-flags.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#! /bin/sh
#! /bin/bash

set -eu
set -eu -o pipefail

CRYSTAL=${CRYSTAL:-crystal}
CRYSTAL_PATH="$($CRYSTAL env CRYSTAL_PATH)"
STDLIB_SRC="${CRYSTAL_PATH#*:}" # stdlib source directory is the last entry in CRYSTAL_PATH
if [ -z "${STDLIB_SRC-}" ]; then
CRYSTAL_PATH="$($CRYSTAL env CRYSTAL_PATH)"
STDLIB_SRC="${CRYSTAL_PATH#*:}" # stdlib source directory is the last entry in CRYSTAL_PATH
fi

echo "Validating flags for stdlib source ${STDLIB_SRC} ($(cat "${STDLIB_SRC}/VERSION"))"

filter_missing() {
missing=0
Expand Down

0 comments on commit d9adeb9

Please sign in to comment.